merge in oc-dr1-release history after reset to master
diff --git a/Android.mk b/Android.mk
index 5544ea4..6f1c9e6c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -315,6 +315,7 @@
 	core/java/android/companion/IFindDeviceCallback.aidl \
 	core/java/android/service/dreams/IDreamManager.aidl \
 	core/java/android/service/dreams/IDreamService.aidl \
+	core/java/android/service/oemlock/IOemLockService.aidl \
 	core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \
 	core/java/android/service/trust/ITrustAgentService.aidl \
 	core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
@@ -576,11 +577,11 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES :=                          \
     framework-protos                                    \
-    android.hardware.health@1.0-java-constants          \
-    android.hardware.thermal@1.0-java-constants         \
-    android.hardware.tv.input@1.0-java-constants        \
-    android.hardware.usb@1.0-java-constants             \
-    android.hardware.vibrator@1.0-java-constants        \
+    android.hardware.health-V1.0-java-constants          \
+    android.hardware.thermal-V1.0-java-constants         \
+    android.hardware.tv.input-V1.0-java-constants        \
+    android.hardware.usb-V1.0-java-constants             \
+    android.hardware.vibrator-V1.0-java-constants        \
 
 # Loaded with System.loadLibrary by android.view.textclassifier
 LOCAL_REQUIRED_MODULES += libtextclassifier
diff --git a/api/current.txt b/api/current.txt
index 897206e..8375bcd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -210,6 +210,8 @@
   public static final class R.attr {
     ctor public R.attr();
     field public static final int __removed1 = 16844099; // 0x1010543
+    field public static final int __removed2 = 16844104; // 0x1010548
+    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -312,7 +314,6 @@
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
     field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofillMode = 16844116; // 0x1010554
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -992,6 +993,7 @@
     field public static final int persistableMode = 16843821; // 0x101042d
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
+    field public static final int persistentFeature = 16844134; // 0x1010566
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
@@ -1270,7 +1272,6 @@
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
     field public static final int supportsAssist = 16844016; // 0x10104f0
-    field public static final int supportsDismissingWindow = 16844104; // 0x1010548
     field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
     field public static final int supportsLocalInteraction = 16844047; // 0x101050f
     field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
@@ -1540,6 +1541,7 @@
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
+    field public static final int windowSplashscreenContent = 16844135; // 0x1010567
     field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
     field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
     field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -1708,6 +1710,7 @@
     field public static final int ic_notification_clear_all = 17301594; // 0x108005a
     field public static final int ic_notification_overlay = 17301595; // 0x108005b
     field public static final int ic_partial_secure = 17301596; // 0x108005c
+    field public static final int ic_picture_in_picture = 17301685; // 0x10800b5
     field public static final int ic_popup_disk_full = 17301597; // 0x108005d
     field public static final int ic_popup_reminder = 17301598; // 0x108005e
     field public static final int ic_popup_sync = 17301599; // 0x108005f
@@ -2998,6 +3001,7 @@
     method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
     field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
     field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
     field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -3612,6 +3616,7 @@
     method public android.net.Uri getReferrer();
     method public int getRequestedOrientation();
     method public final android.view.SearchEvent getSearchEvent();
+    method public long getStartInitiatedTime();
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
@@ -3844,7 +3849,7 @@
     method public deprecated java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException;
     method public java.util.List<android.app.ActivityManager.RunningAppProcessInfo> getRunningAppProcesses();
     method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
-    method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
+    method public deprecated java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
     method public deprecated java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
     method public deprecated boolean isInLockTaskMode();
     method public boolean isLowRamDevice();
@@ -3938,7 +3943,8 @@
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
     field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
     field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
-    field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82
+    field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6
+    field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82
     field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
     field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96
     field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
@@ -4572,6 +4578,7 @@
     method public final android.app.FragmentManager getFragmentManager();
     method public final java.lang.Object getHost();
     method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
     method public android.transition.Transition getReenterTransition();
@@ -4697,7 +4704,7 @@
   public abstract class FragmentContainer {
     ctor public FragmentContainer();
     method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
-    method public abstract android.view.View onFindViewById(int);
+    method public abstract <T extends android.view.View> T onFindViewById(int);
     method public abstract boolean onHasView();
   }
 
@@ -4748,7 +4755,7 @@
     ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
     method public void onAttachFragment(android.app.Fragment);
     method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public android.view.View onFindViewById(int);
+    method public <T extends android.view.View> T onFindViewById(int);
     method public abstract E onGetHost();
     method public android.view.LayoutInflater onGetLayoutInflater();
     method public int onGetWindowAnimations();
@@ -5599,7 +5606,6 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
-    method public deprecated android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -6087,6 +6093,17 @@
     method public void onDetached();
   }
 
+  public final class WallpaperColors implements android.os.Parcelable {
+    ctor public WallpaperColors(android.os.Parcel);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+    method public int describeContents();
+    method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+    method public boolean supportsDarkText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+  }
+
   public final class WallpaperInfo implements android.os.Parcelable {
     ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
@@ -6109,6 +6126,8 @@
   }
 
   public class WallpaperManager {
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
     method public void clear() throws java.io.IOException;
     method public void clear(int) throws java.io.IOException;
     method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6123,6 +6142,7 @@
     method public android.graphics.drawable.Drawable getDrawable();
     method public android.graphics.drawable.Drawable getFastDrawable();
     method public static android.app.WallpaperManager getInstance(android.content.Context);
+    method public android.app.WallpaperColors getWallpaperColors(int);
     method public android.os.ParcelFileDescriptor getWallpaperFile(int);
     method public int getWallpaperId(int);
     method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6131,6 +6151,7 @@
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
+    method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
     method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
     method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
     method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6155,6 +6176,10 @@
     field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
   }
 
+  public static abstract interface WallpaperManager.OnColorsChangedListener {
+    method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+  }
+
 }
 
 package android.app.admin {
@@ -6603,7 +6628,7 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
-    method public java.lang.String[] getAutoFillHints();
+    method public java.lang.String[] getAutofillHints();
     method public android.view.autofill.AutofillId getAutofillId();
     method public java.lang.String[] getAutofillOptions();
     method public int getAutofillType();
@@ -6792,6 +6817,7 @@
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
+    field public static final int NETWORK_TYPE_METERED = 4; // 0x4
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6866,6 +6892,14 @@
     field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
   }
 
+  public abstract class JobServiceEngine {
+    ctor public JobServiceEngine(android.app.Service);
+    method public final android.os.IBinder getBinder();
+    method public final void jobFinished(android.app.job.JobParameters, boolean);
+    method public abstract boolean onStartJob(android.app.job.JobParameters);
+    method public abstract boolean onStopJob(android.app.job.JobParameters);
+  }
+
   public final class JobWorkItem implements android.os.Parcelable {
     ctor public JobWorkItem(android.content.Intent);
     ctor public JobWorkItem(android.os.Parcel);
@@ -6963,12 +6997,12 @@
   }
 
   public class StorageStatsManager {
-    method public long getFreeBytes(java.lang.String);
-    method public long getTotalBytes(java.lang.String);
-    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
-    method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+    method public long getFreeBytes(java.util.UUID) throws java.io.IOException;
+    method public long getTotalBytes(java.util.UUID) throws java.io.IOException;
+    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -7033,6 +7067,7 @@
     method public static void deleteAllHosts();
     method public void deleteAppWidgetId(int);
     method public void deleteHost();
+    method public int[] getAppWidgetIds();
     method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProvidersChanged();
@@ -8066,7 +8101,12 @@
     method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
     method public void startScan(android.bluetooth.le.ScanCallback);
     method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+    method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
     method public void stopScan(android.bluetooth.le.ScanCallback);
+    method public void stopScan(android.app.PendingIntent);
+    field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+    field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+    field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
   }
 
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8250,6 +8290,8 @@
     method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
     method public void disassociate(java.lang.String);
     method public java.util.List<java.lang.String> getAssociations();
+    method public boolean hasNotificationAccess(android.content.ComponentName);
+    method public void requestNotificationAccess(android.content.ComponentName);
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -9344,6 +9386,7 @@
     field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
+    field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
     field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -9460,6 +9503,7 @@
     field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
     field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
     field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
+    field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
     field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
     field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
     field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -10177,12 +10221,12 @@
     field public java.lang.String[] splitNames;
     field public java.lang.String[] splitPublicSourceDirs;
     field public java.lang.String[] splitSourceDirs;
+    field public java.util.UUID storageUuid;
     field public int targetSdkVersion;
     field public java.lang.String taskAffinity;
     field public int theme;
     field public int uiOptions;
     field public int uid;
-    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -10301,7 +10345,7 @@
 
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
-    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
+    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent);
     method public java.util.List<android.os.UserHandle> getProfiles();
     method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int);
@@ -10357,12 +10401,10 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
-    method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
-    field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10903,12 +10945,13 @@
     method public android.content.pm.VersionedPackage getDeclaringPackage();
     method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
     method public java.lang.String getName();
-    method public int getVersion();
-    method public boolean isBuiltin();
-    method public boolean isDynamic();
-    method public boolean isStatic();
+    method public int getType();
+    method public long getVersion();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int TYPE_BUILTIN = 0; // 0x0
+    field public static final int TYPE_DYNAMIC = 1; // 0x1
+    field public static final int TYPE_STATIC = 2; // 0x2
     field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
   }
 
@@ -10916,9 +10959,6 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
-    method public deprecated android.content.ComponentName[] getChooserComponentNames();
-    method public deprecated android.os.PersistableBundle getChooserExtras();
-    method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -10931,7 +10971,6 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
-    method public deprecated boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -10944,11 +10983,9 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
-    method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
-    method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12537,6 +12574,7 @@
     field public boolean inJustDecodeBounds;
     field public boolean inMutable;
     field public deprecated boolean inPreferQualityOverSpeed;
+    field public android.graphics.ColorSpace inPreferredColorSpace;
     field public android.graphics.Bitmap.Config inPreferredConfig;
     field public boolean inPremultiplied;
     field public deprecated boolean inPurgeable;
@@ -12567,7 +12605,6 @@
 
   public class BitmapShader extends android.graphics.Shader {
     ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
-    method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
   }
 
   public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -12820,8 +12857,6 @@
     ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
     ctor public ColorMatrixColorFilter(float[]);
     method public void getColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrixArray(float[]);
   }
 
   public abstract class ColorSpace {
@@ -12962,8 +12997,6 @@
   public class ComposeShader extends android.graphics.Shader {
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
   }
 
   public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13036,15 +13069,11 @@
     ctor public LightingColorFilter(int, int);
     method public int getColorAdd();
     method public int getColorMultiply();
-    method public void setColorAdd(int);
-    method public void setColorMultiply(int);
   }
 
   public class LinearGradient extends android.graphics.Shader {
     ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public class MaskFilter {
@@ -13554,10 +13583,6 @@
 
   public class PorterDuffColorFilter extends android.graphics.ColorFilter {
     ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public int getColor();
-    method public android.graphics.PorterDuff.Mode getMode();
-    method public void setColor(int);
-    method public void setMode(android.graphics.PorterDuff.Mode);
   }
 
   public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -13567,8 +13592,6 @@
   public class RadialGradient extends android.graphics.Shader {
     ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public final class Rect implements android.os.Parcelable {
@@ -13753,12 +13776,10 @@
   public class SweepGradient extends android.graphics.Shader {
     ctor public SweepGradient(float, float, int[], float[]);
     ctor public SweepGradient(float, float, int, int);
-    method public void set(float, float, int[], float[]);
-    method public void set(float, float, int, int);
   }
 
   public class Typeface {
-    method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+    method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
     method public static android.graphics.Typeface create(java.lang.String, int);
     method public static android.graphics.Typeface create(android.graphics.Typeface, int);
     method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13785,6 +13806,7 @@
     ctor public Typeface.Builder(java.lang.String);
     ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
     method public android.graphics.Typeface build();
+    method public android.graphics.Typeface.Builder setFallback(java.lang.String);
     method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
     method public android.graphics.Typeface.Builder setItalic(boolean);
@@ -13792,7 +13814,7 @@
     method public android.graphics.Typeface.Builder setWeight(int);
   }
 
-  public static abstract interface Typeface.FontRequestCallback {
+  public static abstract deprecated interface Typeface.FontRequestCallback {
     method public abstract void onTypefaceRequestFailed(int);
     method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
     field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
@@ -13824,7 +13846,7 @@
   public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
     method public void draw(android.graphics.Canvas);
     method public android.graphics.drawable.Drawable getBackground();
-    method public static float getExtraInsetPercentage();
+    method public static float getExtraInsetFraction();
     method public android.graphics.drawable.Drawable getForeground();
     method public android.graphics.Path getIconMask();
     method public int getOpacity();
@@ -14860,15 +14882,16 @@
     field public final int type;
   }
 
-  public final class SensorDirectChannel implements java.lang.AutoCloseable {
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
     method public void close();
-    method public boolean isValid();
+    method public int configure(android.hardware.Sensor, int);
+    method public boolean isOpen();
     field public static final int RATE_FAST = 2; // 0x2
     field public static final int RATE_NORMAL = 1; // 0x1
     field public static final int RATE_STOP = 0; // 0x0
     field public static final int RATE_VERY_FAST = 3; // 0x3
-    field public static final int TYPE_ASHMEM = 1; // 0x1
     field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+    field public static final int TYPE_MEMORY_FILE = 1; // 0x1
   }
 
   public class SensorEvent {
@@ -14902,7 +14925,6 @@
 
   public abstract class SensorManager {
     method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
-    method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
     method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
     method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
     method public boolean flush(android.hardware.SensorEventListener);
@@ -15751,7 +15773,6 @@
     method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
     field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
     field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
-    field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
     field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
     field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -20579,7 +20600,7 @@
     method public double getAccumulatedDeltaRangeMeters();
     method public int getAccumulatedDeltaRangeState();
     method public double getAccumulatedDeltaRangeUncertaintyMeters();
-    method public double getAutomaticGainControlLevelInDb();
+    method public double getAutomaticGainControlLevelDb();
     method public long getCarrierCycles();
     method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
@@ -20595,7 +20616,7 @@
     method public int getState();
     method public int getSvid();
     method public double getTimeOffsetNanos();
-    method public boolean hasAutomaticGainControlLevelInDb();
+    method public boolean hasAutomaticGainControlLevelDb();
     method public boolean hasCarrierCycles();
     method public boolean hasCarrierFrequencyHz();
     method public boolean hasCarrierPhase();
@@ -20689,7 +20710,7 @@
     method public int getSatelliteCount();
     method public int getSvid(int);
     method public boolean hasAlmanacData(int);
-    method public boolean hasCarrierFrequency(int);
+    method public boolean hasCarrierFrequencyHz(int);
     method public boolean hasEphemerisData(int);
     method public boolean usedInFix(int);
     field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
@@ -20768,13 +20789,10 @@
     method public boolean hasSpeedAccuracy();
     method public boolean hasVerticalAccuracy();
     method public boolean isFromMockProvider();
-    method public void removeAccuracy();
-    method public void removeAltitude();
-    method public void removeBearing();
-    method public void removeBearingAccuracy();
-    method public void removeSpeed();
-    method public void removeSpeedAccuracy();
-    method public void removeVerticalAccuracy();
+    method public deprecated void removeAccuracy();
+    method public deprecated void removeAltitude();
+    method public deprecated void removeBearing();
+    method public deprecated void removeSpeed();
     method public void reset();
     method public void set(android.location.Location);
     method public void setAccuracy(float);
@@ -21807,24 +21825,19 @@
     field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
   }
 
-  public final class MediaCas {
+  public final class MediaCas implements java.lang.AutoCloseable {
     ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
-    method public void closeSession(byte[]);
+    method public void close();
     method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
     method public static boolean isSystemIdSupported(int);
-    method public byte[] openSession(int) throws android.media.MediaCasException;
-    method public byte[] openSession(int, int) throws android.media.MediaCasException;
-    method public void processEcm(byte[], byte[], int, int) throws android.media.MediaCasException;
-    method public void processEcm(byte[], byte[]) throws android.media.MediaCasException;
+    method public android.media.MediaCas.Session openSession() throws android.media.MediaCasException;
     method public void processEmm(byte[], int, int) throws android.media.MediaCasException;
     method public void processEmm(byte[]) throws android.media.MediaCasException;
     method public void provision(java.lang.String) throws android.media.MediaCasException;
     method public void refreshEntitlements(int, byte[]) throws android.media.MediaCasException;
-    method public void release();
     method public void sendEvent(int, int, byte[]) throws android.media.MediaCasException;
     method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
     method public void setPrivateData(byte[]) throws android.media.MediaCasException;
-    method public void setSessionPrivateData(byte[], byte[]) throws android.media.MediaCasException;
   }
 
   public static abstract interface MediaCas.EventListener {
@@ -21836,6 +21849,13 @@
     method public int getSystemId();
   }
 
+  public final class MediaCas.Session implements java.lang.AutoCloseable {
+    method public void close();
+    method public void processEcm(byte[], int, int) throws android.media.MediaCasException;
+    method public void processEcm(byte[]) throws android.media.MediaCasException;
+    method public void setPrivateData(byte[]) throws android.media.MediaCasException;
+  }
+
   public class MediaCasException extends java.lang.Exception {
   }
 
@@ -21871,7 +21891,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -21969,6 +21989,19 @@
     method public void set(int, int);
   }
 
+  public static final class MediaCodec.MetricsConstants {
+    field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+    field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+    field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+  }
+
   public static abstract interface MediaCodec.OnFrameRenderedListener {
     method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
   }
@@ -22279,12 +22312,12 @@
     method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
   }
 
-  public final class MediaDescrambler {
+  public final class MediaDescrambler implements java.lang.AutoCloseable {
     ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException;
-    method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
-    method public final void release();
+    method public void close();
+    method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
     method public final boolean requiresSecureDecoderComponent(java.lang.String);
-    method public final void setMediaCasSession(byte[]);
+    method public final void setMediaCasSession(android.media.MediaCas.Session);
   }
 
   public class MediaDescription implements android.os.Parcelable {
@@ -22348,7 +22381,7 @@
     method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
     method public void setPropertyByteArray(java.lang.String, byte[]);
     method public void setPropertyString(java.lang.String, java.lang.String);
-    field public static final int EVENT_KEY_EXPIRED = 3; // 0x3
+    field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
     field public static final int EVENT_KEY_REQUIRED = 2; // 0x2
     field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1
     field public static final int EVENT_SESSION_RECLAIMED = 5; // 0x5
@@ -22422,8 +22455,9 @@
     ctor public MediaExtractor();
     method public boolean advance();
     method public long getCachedDuration();
+    method public android.media.MediaExtractor.CasInfo getCasInfo(int);
     method public android.media.DrmInitData getDrmInitData();
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -22453,6 +22487,17 @@
     field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
   }
 
+  public static final class MediaExtractor.CasInfo {
+    method public android.media.MediaCas.Session getSession();
+    method public int getSystemId();
+  }
+
+  public static final class MediaExtractor.MetricsConstants {
+    field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+    field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
   public final class MediaFormat {
     ctor public MediaFormat();
     method public final boolean containsKey(java.lang.String);
@@ -22678,69 +22723,6 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
-  public final class MediaMetricsSet {
-    method public double getDouble(java.lang.String, double);
-    method public int getInt(java.lang.String, int);
-    method public long getLong(java.lang.String, long);
-    method public java.lang.String getString(java.lang.String, java.lang.String);
-    method public boolean isEmpty();
-    method public java.util.Set<java.lang.String> keySet();
-    method public int size();
-  }
-
-  public static final class MediaMetricsSet.MediaCodec {
-    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
-    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
-    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
-    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
-    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
-    field public static final java.lang.String MODE_AUDIO = "audio";
-    field public static final java.lang.String MODE_VIDEO = "video";
-  }
-
-  public static final class MediaMetricsSet.MediaExtractor {
-    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
-    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
-    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-  }
-
-  public static final class MediaMetricsSet.MediaPlayer {
-    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
-    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
-    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
-    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
-    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
-  }
-
-  public static final class MediaMetricsSet.MediaRecorder {
-    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
-    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
-    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
-  }
-
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -22778,8 +22760,8 @@
     method public android.media.MediaPlayer.DrmInfo getDrmInfo();
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
-    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+    method public android.os.PersistableBundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -22792,7 +22774,7 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
-    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningNetworkErrorException, android.media.MediaPlayer.ProvisioningServerErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
     method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
     method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -22819,7 +22801,7 @@
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
-    method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
+    method public void setOnDrmConfigHelper(android.media.MediaPlayer.OnDrmConfigHelper);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
     method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -22860,6 +22842,10 @@
     field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
     field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
     field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+    field public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3; // 0x3
+    field public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1; // 0x1
+    field public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2; // 0x2
+    field public static final int PREPARE_DRM_STATUS_SUCCESS = 0; // 0x0
     field public static final int SEEK_CLOSEST = 3; // 0x3
     field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
     field public static final int SEEK_NEXT_SYNC = 1; // 0x1
@@ -22869,11 +22855,25 @@
   }
 
   public static final class MediaPlayer.DrmInfo {
-    method public java.lang.String[] getMimes();
     method public java.util.Map<java.util.UUID, byte[]> getPssh();
     method public java.util.UUID[] getSupportedSchemes();
   }
 
+  public static final class MediaPlayer.MetricsConstants {
+    field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+  }
+
   public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
     ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
   }
@@ -22886,7 +22886,7 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
-  public static abstract interface MediaPlayer.OnDrmConfigListener {
+  public static abstract interface MediaPlayer.OnDrmConfigHelper {
     method public abstract void onDrmConfig(android.media.MediaPlayer);
   }
 
@@ -22895,7 +22895,7 @@
   }
 
   public static abstract interface MediaPlayer.OnDrmPreparedListener {
-    method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+    method public abstract void onDrmPrepared(android.media.MediaPlayer, int);
   }
 
   public static abstract interface MediaPlayer.OnErrorListener {
@@ -22926,8 +22926,12 @@
     method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
   }
 
-  public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
-    ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+  public static final class MediaPlayer.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningNetworkErrorException(java.lang.String);
+  }
+
+  public static final class MediaPlayer.ProvisioningServerErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningServerErrorException(java.lang.String);
   }
 
   public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
@@ -22948,7 +22952,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -22967,11 +22971,12 @@
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
     method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
-    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
     method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+    method public void setOutputFile(java.io.File);
     method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
     method public void setOutputFormat(int) throws java.lang.IllegalStateException;
     method public void setPreviewDisplay(android.view.Surface);
@@ -23016,6 +23021,25 @@
     field public static final int VOICE_UPLINK = 2; // 0x2
   }
 
+  public static final class MediaRecorder.MetricsConstants {
+    field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+  }
+
   public static abstract interface MediaRecorder.OnErrorListener {
     method public abstract void onError(android.media.MediaRecorder, int, int);
   }
@@ -23979,7 +24003,6 @@
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public boolean isConnected();
-    method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback);
     method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback);
     method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback);
     method public void unsubscribe(java.lang.String);
@@ -24015,12 +24038,6 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
-  public static abstract class MediaBrowser.SearchCallback {
-    ctor public MediaBrowser.SearchCallback();
-    method public void onError(java.lang.String, android.os.Bundle);
-    method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
-  }
-
   public static abstract class MediaBrowser.SubscriptionCallback {
     ctor public MediaBrowser.SubscriptionCallback();
     method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -24229,8 +24246,6 @@
 
   public final class MediaController {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
-    method public void addQueueItem(android.media.MediaDescription);
-    method public void addQueueItem(android.media.MediaDescription, int);
     method public void adjustVolume(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
@@ -24242,15 +24257,11 @@
     method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue();
     method public java.lang.CharSequence getQueueTitle();
     method public int getRatingType();
-    method public int getRepeatMode();
     method public android.app.PendingIntent getSessionActivity();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public android.media.session.MediaController.TransportControls getTransportControls();
-    method public boolean isShuffleModeEnabled();
     method public void registerCallback(android.media.session.MediaController.Callback);
     method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
-    method public void removeQueueItem(android.media.MediaDescription);
-    method public void removeQueueItemAt(int);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void setVolumeTo(int, int);
     method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -24264,10 +24275,8 @@
     method public void onPlaybackStateChanged(android.media.session.PlaybackState);
     method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>);
     method public void onQueueTitleChanged(java.lang.CharSequence);
-    method public void onRepeatModeChanged(int);
     method public void onSessionDestroyed();
     method public void onSessionEvent(java.lang.String, android.os.Bundle);
-    method public void onShuffleModeChanged(boolean);
   }
 
   public static final class MediaController.PlaybackInfo {
@@ -24296,8 +24305,6 @@
     method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
     method public void sendCustomAction(java.lang.String, android.os.Bundle);
     method public void setRating(android.media.Rating);
-    method public void setRepeatMode(int);
-    method public void setShuffleModeEnabled(boolean);
     method public void skipToNext();
     method public void skipToPrevious();
     method public void skipToQueueItem(long);
@@ -24324,18 +24331,13 @@
     method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>);
     method public void setQueueTitle(java.lang.CharSequence);
     method public void setRatingType(int);
-    method public void setRepeatMode(int);
     method public void setSessionActivity(android.app.PendingIntent);
-    method public void setShuffleModeEnabled(boolean);
     field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
-    field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
     field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
   public static abstract class MediaSession.Callback {
     ctor public MediaSession.Callback();
-    method public void onAddQueueItem(android.media.MediaDescription);
-    method public void onAddQueueItem(android.media.MediaDescription, int);
     method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void onCustomAction(java.lang.String, android.os.Bundle);
     method public void onFastForward();
@@ -24349,13 +24351,9 @@
     method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
     method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
-    method public void onRemoveQueueItem(android.media.MediaDescription);
-    method public void onRemoveQueueItemAt(int);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
-    method public void onSetRepeatMode(int);
-    method public void onSetShuffleModeEnabled(boolean);
     method public void onSkipToNext();
     method public void onSkipToPrevious();
     method public void onSkipToQueueItem(long);
@@ -24416,17 +24414,12 @@
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
     field public static final long ACTION_SET_RATING = 128L; // 0x80L
-    field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L
-    field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L
     field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L
     field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
-    field public static final int REPEAT_MODE_ALL = 2; // 0x2
-    field public static final int REPEAT_MODE_NONE = 0; // 0x0
-    field public static final int REPEAT_MODE_ONE = 1; // 0x1
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
     field public static final int STATE_ERROR = 7; // 0x7
@@ -24509,14 +24502,14 @@
     method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
     method public static boolean isChannelUriForTunerInput(android.net.Uri);
     method public static boolean isProgramUri(android.net.Uri);
+    method public static void requestChannelBrowsable(android.content.Context, long);
     field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
-    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
     field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+    field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String AUTHORITY = "android.media.tv";
     field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
-    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
     field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
   }
@@ -24609,9 +24602,10 @@
 
   public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
-    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
-    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+    field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
     field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
     field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
     field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
     field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -24794,9 +24788,10 @@
   public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
     ctor public TvContract.WatchNextPrograms();
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
-    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
-    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+    field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
     field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
     field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
     field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
     field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -25525,14 +25520,10 @@
   }
 
   public final class IpSecManager {
-    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
     method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
     field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -25551,7 +25542,7 @@
   }
 
   public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
-    method public void close();
+    method public void close() throws java.io.IOException;
     method public int getPort();
     method public java.io.FileDescriptor getSocket();
   }
@@ -26749,8 +26740,8 @@
   }
 
   public class DiscoverySession {
-    method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
-    method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+    method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+    method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
     method public void destroy();
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
@@ -26836,8 +26827,8 @@
   }
 
   public class WifiAwareSession {
-    method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
-    method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+    method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+    method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
     method public void destroy();
     method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
     method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
@@ -30768,6 +30759,7 @@
     method public android.util.SizeF getSizeF(java.lang.String);
     method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
+    method public java.util.UUID getUuid(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
     method public void putBinder(java.lang.String, android.os.IBinder);
@@ -30792,6 +30784,7 @@
     method public void putSizeF(java.lang.String, android.util.SizeF);
     method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>);
     method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>);
+    method public void putUuid(java.lang.String, java.util.UUID);
     method public void readFromParcel(android.os.Parcel);
     method public void setClassLoader(java.lang.ClassLoader);
     method public void writeToParcel(android.os.Parcel, int);
@@ -31321,6 +31314,7 @@
     method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
     method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
     method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final java.util.UUID readUuid();
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -31366,6 +31360,7 @@
     method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
     method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
     method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
+    method public final void writeUuid(java.util.UUID);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -31923,7 +31918,7 @@
     field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
     field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
     field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
-    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
+    field public static final deprecated int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
     field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
     field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
     field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -31997,15 +31992,16 @@
   }
 
   public class StorageManager {
-    method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
-    method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes(java.io.File);
-    method public long getCacheSizeBytes(java.io.File);
+    method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException;
+    method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException;
+    method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException;
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
     method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
+    method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
     method public boolean isEncrypted(java.io.File);
@@ -32017,7 +32013,10 @@
     method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException;
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
     field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
+    field public static final java.lang.String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
+    field public static final java.lang.String EXTRA_UUID = "android.os.storage.extra.UUID";
     field public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1
+    field public static final java.util.UUID UUID_DEFAULT;
   }
 
   public final class StorageVolume implements android.os.Parcelable {
@@ -34498,6 +34497,10 @@
   }
 
   public class FontsContract {
+    method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
+    method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
+    method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
   }
 
   public static final class FontsContract.Columns implements android.provider.BaseColumns {
@@ -34514,6 +34517,35 @@
     field public static final java.lang.String WEIGHT = "font_weight";
   }
 
+  public static class FontsContract.FontFamilyResult {
+    method public android.provider.FontsContract.FontInfo[] getFonts();
+    method public int getStatusCode();
+    field public static final int STATUS_OK = 0; // 0x0
+    field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+    field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+  }
+
+  public static class FontsContract.FontInfo {
+    method public android.graphics.fonts.FontVariationAxis[] getAxes();
+    method public int getResultCode();
+    method public int getTtcIndex();
+    method public android.net.Uri getUri();
+    method public int getWeight();
+    method public boolean isItalic();
+  }
+
+  public static class FontsContract.FontRequestCallback {
+    ctor public FontsContract.FontRequestCallback();
+    method public void onTypefaceRequestFailed(int);
+    method public void onTypefaceRetrieved(android.graphics.Typeface);
+    field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+    field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+    field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+    field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+    field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+    field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+  }
+
   public final deprecated class LiveFolders implements android.provider.BaseColumns {
     field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
     field public static final java.lang.String DESCRIPTION = "description";
@@ -35421,6 +35453,16 @@
     field public static final java.lang.String SUBSCRIPTION_ID = "pending_sub_id";
   }
 
+  public static final class Telephony.ServiceStateTable {
+    method public static android.net.Uri getUriForSubId(int);
+    method public static android.net.Uri getUriForSubIdAndField(int, java.lang.String);
+    field public static final java.lang.String AUTHORITY = "service-state";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection";
+    field public static final java.lang.String VOICE_OPERATOR_NUMERIC = "voice_operator_numeric";
+    field public static final java.lang.String VOICE_REG_STATE = "voice_reg_state";
+  }
+
   public static final class Telephony.Sms implements android.provider.BaseColumns android.provider.Telephony.TextBasedSmsColumns {
     method public static java.lang.String getDefaultSmsPackage(android.content.Context);
     field public static final android.net.Uri CONTENT_URI;
@@ -36995,11 +37037,14 @@
   public abstract class AutofillService extends android.app.Service {
     ctor public AutofillService();
     method public final deprecated void disableSelf();
+    method public final android.service.autofill.FillEventHistory getFillEventHistory();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
-    method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+    method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+    method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
@@ -37015,6 +37060,7 @@
     ctor public Dataset.Builder();
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.Dataset.Builder setId(java.lang.String);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews);
   }
@@ -37024,6 +37070,42 @@
     method public void onSuccess(android.service.autofill.FillResponse);
   }
 
+  public final class FillContext implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getRequestId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+  }
+
+  public final class FillEventHistory implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR;
+  }
+
+  public static final class FillEventHistory.Event {
+    method public java.lang.String getDatasetId();
+    method public int getType();
+    field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
+    field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
+    field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
+    field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+  }
+
+  public final class FillRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public int getFlags();
+    method public int getId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+  }
+
   public final class FillResponse implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -37035,7 +37117,9 @@
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
     method public android.service.autofill.FillResponse build();
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
-    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+    method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -37048,6 +37132,7 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
     field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
     field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
     field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -37060,10 +37145,19 @@
     ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
     method public android.service.autofill.SaveInfo build();
     method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setFlags(int);
     method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
   }
 
+  public final class SaveRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+  }
+
 }
 
 package android.service.carrier {
@@ -37183,7 +37277,7 @@
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public final void finish();
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
@@ -37245,7 +37339,6 @@
     method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
     method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle);
     method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>);
-    method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
     method public void setSessionToken(android.media.session.MediaSession.Token);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
   }
@@ -37325,16 +37418,16 @@
     method public final int getCurrentInterruptionFilter();
     method public final int getCurrentListenerHints();
     method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
-    method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
-    method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
+    method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String, android.os.UserHandle);
+    method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String, android.os.UserHandle);
     method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onInterruptionFilterChanged(int);
     method public void onListenerConnected();
     method public void onListenerDisconnected();
     method public void onListenerHintsChanged(int);
-    method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
-    method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
+    method public void onNotificationChannelGroupModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannelGroup, int);
+    method public void onNotificationChannelModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannel, int);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -37347,7 +37440,7 @@
     method public final void requestUnbind();
     method public final void setNotificationsShown(java.lang.String[]);
     method public final void snoozeNotification(java.lang.String, long);
-    method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
+    method public final void updateNotificationChannel(java.lang.String, android.os.UserHandle, android.app.NotificationChannel);
     field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
     field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
@@ -37697,10 +37790,12 @@
     method public int getDesiredMinimumHeight();
     method public int getDesiredMinimumWidth();
     method public android.view.SurfaceHolder getSurfaceHolder();
+    method public void invalidateColors();
     method public boolean isPreview();
     method public boolean isVisible();
     method public void onApplyWindowInsets(android.view.WindowInsets);
     method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+    method public android.app.WallpaperColors onComputeWallpaperColors();
     method public void onCreate(android.view.SurfaceHolder);
     method public void onDesiredSizeChanged(int, int);
     method public void onDestroy();
@@ -39376,6 +39471,8 @@
     field public static final java.lang.String ACTION_CONFIGURE_PHONE_ACCOUNT = "android.telecom.action.CONFIGURE_PHONE_ACCOUNT";
     field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED";
     field public static final deprecated java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
+    field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
+    field public static final java.lang.String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED";
     field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
     field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
     field public static final java.lang.String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION";
@@ -40820,7 +40917,6 @@
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
     method public android.content.ComponentName startService(android.content.Intent);
-    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean stopService(android.content.Intent);
     method public void unbindService(android.content.ServiceConnection);
     method public void unregisterReceiver(android.content.BroadcastReceiver);
@@ -43852,7 +43948,6 @@
     method public boolean isValid();
     method public boolean isWideColorGamut();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
-    field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int FLAG_PRESENTATION = 8; // 0x8
     field public static final int FLAG_PRIVATE = 4; // 0x4
     field public static final int FLAG_ROUND = 16; // 0x10
@@ -45333,7 +45428,6 @@
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
     method public java.lang.String[] getAutofillHints();
-    method public int getAutofillMode();
     method public int getAutofillType();
     method public android.view.autofill.AutofillValue getAutofillValue();
     method public android.graphics.drawable.Drawable getBackground();
@@ -45422,7 +45516,6 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
-    method public int getResolvedAutofillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -45655,7 +45748,6 @@
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
     method public void setAutofillHints(java.lang.String...);
-    method public void setAutofillMode(int);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
     method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -45811,9 +45903,6 @@
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
     field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
-    field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
-    field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
-    field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
     field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
     field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
     field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -45861,7 +45950,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
     field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -46381,7 +46472,6 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
-    method public default int getResolvedAutofillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -47067,7 +47157,6 @@
 
   public final class AccessibilityManager {
     method public void addAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
-    method public boolean addAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
     method public boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
     method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
@@ -47077,16 +47166,11 @@
     method public boolean isEnabled();
     method public boolean isTouchExplorationEnabled();
     method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
-    method public boolean removeAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
     method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
     method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
   }
 
-  public static abstract interface AccessibilityManager.AccessibilityServicesStateChangeListener {
-    method public abstract void onAccessibilityServicesStateChanged();
-  }
-
   public static abstract interface AccessibilityManager.AccessibilityStateChangeListener {
     method public abstract void onAccessibilityStateChanged(boolean);
   }
@@ -47777,7 +47861,7 @@
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
     field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
-    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+    field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
   }
 
   public static abstract class AutofillManager.AutofillCallback {
@@ -49651,6 +49735,7 @@
     method public java.lang.String getFormat();
     method public android.widget.Chronometer.OnChronometerTickListener getOnChronometerTickListener();
     method public boolean isCountDown();
+    method public boolean isTheFinalCountDown();
     method public void setBase(long);
     method public void setCountDown(boolean);
     method public void setFormat(java.lang.String);
@@ -55320,6 +55405,7 @@
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
     method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle explicitCastArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
     method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
diff --git a/api/removed.txt b/api/removed.txt
index d20c08c..b6c2a98 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -5,10 +5,6 @@
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
   }
 
-  public static class Notification.Builder {
-    method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
-  }
-
   public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
     method public deprecated void showAsNotification(android.content.Context);
   }
@@ -26,6 +22,20 @@
 
 }
 
+package android.app.usage {
+
+  public class StorageStatsManager {
+    method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated boolean isQuotaSupported(java.lang.String);
+    method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+  }
+
+}
+
 package android.content {
 
   public abstract class Context {
@@ -41,6 +51,10 @@
 
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String volumeUuid;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -49,6 +63,12 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+  }
+
 }
 
 package android.database {
@@ -100,6 +120,28 @@
 
 }
 
+package android.hardware {
+
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
+    method public deprecated boolean isValid();
+  }
+
+  public abstract class SensorManager {
+    method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+  }
+
+}
+
+package android.location {
+
+  public class Location implements android.os.Parcelable {
+    method public deprecated void removeBearingAccuracy();
+    method public deprecated void removeSpeedAccuracy();
+    method public deprecated void removeVerticalAccuracy();
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
@@ -172,10 +214,14 @@
 package android.os.storage {
 
   public class StorageManager {
-    method public deprecated long getCacheQuotaBytes();
-    method public deprecated long getCacheSizeBytes();
-    method public deprecated long getExternalCacheQuotaBytes();
-    method public deprecated long getExternalCacheSizeBytes();
+    method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException;
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
     method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException;
diff --git a/api/system-current.txt b/api/system-current.txt
index e92968d..3844ac0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -142,12 +142,14 @@
     field public static final java.lang.String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS";
     field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
     field public static final java.lang.String MANAGE_AUTO_FILL = "android.permission.MANAGE_AUTO_FILL";
+    field public static final java.lang.String MANAGE_CARRIER_OEM_UNLOCK_STATE = "android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE";
     field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
     field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
     field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
     field public static final java.lang.String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
     field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
     field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS";
+    field public static final java.lang.String MANAGE_USER_OEM_UNLOCK_STATE = "android.permission.MANAGE_USER_OEM_UNLOCK_STATE";
     field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
     field public static final java.lang.String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
     field public static final java.lang.String MODIFY_APPWIDGET_BIND_PERMISSIONS = "android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS";
@@ -326,6 +328,8 @@
   public static final class R.attr {
     ctor public R.attr();
     field public static final int __removed1 = 16844099; // 0x1010543
+    field public static final int __removed2 = 16844104; // 0x1010548
+    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -428,7 +432,6 @@
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
     field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofillMode = 16844116; // 0x1010554
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -1108,6 +1111,7 @@
     field public static final int persistableMode = 16843821; // 0x101042d
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
+    field public static final int persistentFeature = 16844134; // 0x1010566
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
@@ -1193,6 +1197,8 @@
     field public static final int requiredFeature = 16844119; // 0x1010557
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
     field public static final int requiredNotFeature = 16844120; // 0x1010558
+    field public static final int requiredSystemPropertyName = 16844136; // 0x1010568
+    field public static final int requiredSystemPropertyValue = 16844137; // 0x1010569
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeClip = 16843983; // 0x10104cf
@@ -1390,7 +1396,6 @@
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
     field public static final int supportsAssist = 16844016; // 0x10104f0
-    field public static final int supportsDismissingWindow = 16844104; // 0x1010548
     field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
     field public static final int supportsLocalInteraction = 16844047; // 0x101050f
     field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
@@ -1660,6 +1665,7 @@
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
+    field public static final int windowSplashscreenContent = 16844135; // 0x1010567
     field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
     field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
     field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -1828,6 +1834,7 @@
     field public static final int ic_notification_clear_all = 17301594; // 0x108005a
     field public static final int ic_notification_overlay = 17301595; // 0x108005b
     field public static final int ic_partial_secure = 17301596; // 0x108005c
+    field public static final int ic_picture_in_picture = 17301685; // 0x10800b5
     field public static final int ic_popup_disk_full = 17301597; // 0x108005d
     field public static final int ic_popup_reminder = 17301598; // 0x108005e
     field public static final int ic_popup_sync = 17301599; // 0x108005f
@@ -3122,6 +3129,7 @@
     method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
     field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
     field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
     field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -3738,6 +3746,7 @@
     method public android.net.Uri getReferrer();
     method public int getRequestedOrientation();
     method public final android.view.SearchEvent getSearchEvent();
+    method public long getStartInitiatedTime();
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
@@ -3981,7 +3990,7 @@
     method public deprecated java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException;
     method public java.util.List<android.app.ActivityManager.RunningAppProcessInfo> getRunningAppProcesses();
     method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
-    method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
+    method public deprecated java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
     method public deprecated java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
     method public int getUidImportance(int);
     method public deprecated boolean isInLockTaskMode();
@@ -4082,7 +4091,8 @@
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
     field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
     field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
-    field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82
+    field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6
+    field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82
     field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
     field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96
     field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
@@ -4735,6 +4745,7 @@
     method public final android.app.FragmentManager getFragmentManager();
     method public final java.lang.Object getHost();
     method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
     method public android.transition.Transition getReenterTransition();
@@ -4860,7 +4871,7 @@
   public abstract class FragmentContainer {
     ctor public FragmentContainer();
     method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
-    method public abstract android.view.View onFindViewById(int);
+    method public abstract <T extends android.view.View> T onFindViewById(int);
     method public abstract boolean onHasView();
   }
 
@@ -4911,7 +4922,7 @@
     ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
     method public void onAttachFragment(android.app.Fragment);
     method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public android.view.View onFindViewById(int);
+    method public <T extends android.view.View> T onFindViewById(int);
     method public abstract E onGetHost();
     method public android.view.LayoutInflater onGetLayoutInflater();
     method public int onGetWindowAnimations();
@@ -5797,7 +5808,6 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
-    method public deprecated android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -6289,6 +6299,17 @@
     method public void setPersistentVrModeEnabled(boolean);
   }
 
+  public final class WallpaperColors implements android.os.Parcelable {
+    ctor public WallpaperColors(android.os.Parcel);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+    method public int describeContents();
+    method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+    method public boolean supportsDarkText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+  }
+
   public final class WallpaperInfo implements android.os.Parcelable {
     ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
@@ -6311,6 +6332,8 @@
   }
 
   public class WallpaperManager {
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
     method public void clear() throws java.io.IOException;
     method public void clear(int) throws java.io.IOException;
     method public void clearWallpaper();
@@ -6327,6 +6350,7 @@
     method public android.graphics.drawable.Drawable getDrawable();
     method public android.graphics.drawable.Drawable getFastDrawable();
     method public static android.app.WallpaperManager getInstance(android.content.Context);
+    method public android.app.WallpaperColors getWallpaperColors(int);
     method public android.os.ParcelFileDescriptor getWallpaperFile(int);
     method public int getWallpaperId(int);
     method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6335,6 +6359,7 @@
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
+    method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
     method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
     method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
     method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6362,6 +6387,10 @@
     field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
   }
 
+  public static abstract interface WallpaperManager.OnColorsChangedListener {
+    method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+  }
+
 }
 
 package android.app.admin {
@@ -6844,7 +6873,7 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
-    method public java.lang.String[] getAutoFillHints();
+    method public java.lang.String[] getAutofillHints();
     method public android.view.autofill.AutofillId getAutofillId();
     method public java.lang.String[] getAutofillOptions();
     method public int getAutofillType();
@@ -7223,6 +7252,7 @@
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
+    field public static final int NETWORK_TYPE_METERED = 4; // 0x4
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -7298,6 +7328,14 @@
     field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
   }
 
+  public abstract class JobServiceEngine {
+    ctor public JobServiceEngine(android.app.Service);
+    method public final android.os.IBinder getBinder();
+    method public final void jobFinished(android.app.job.JobParameters, boolean);
+    method public abstract boolean onStartJob(android.app.job.JobParameters);
+    method public abstract boolean onStopJob(android.app.job.JobParameters);
+  }
+
   public final class JobWorkItem implements android.os.Parcelable {
     ctor public JobWorkItem(android.content.Intent);
     ctor public JobWorkItem(android.os.Parcel);
@@ -7424,12 +7462,12 @@
   }
 
   public class StorageStatsManager {
-    method public long getFreeBytes(java.lang.String);
-    method public long getTotalBytes(java.lang.String);
-    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
-    method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+    method public long getFreeBytes(java.util.UUID) throws java.io.IOException;
+    method public long getTotalBytes(java.util.UUID) throws java.io.IOException;
+    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -7495,6 +7533,7 @@
     method public static void deleteAllHosts();
     method public void deleteAppWidgetId(int);
     method public void deleteHost();
+    method public int[] getAppWidgetIds();
     method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProvidersChanged();
@@ -8536,10 +8575,15 @@
     method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
     method public void startScan(android.bluetooth.le.ScanCallback);
     method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+    method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
     method public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
     method public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
     method public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
     method public void stopScan(android.bluetooth.le.ScanCallback);
+    method public void stopScan(android.app.PendingIntent);
+    field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+    field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+    field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
   }
 
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8742,6 +8786,8 @@
     method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
     method public void disassociate(java.lang.String);
     method public java.util.List<java.lang.String> getAssociations();
+    method public boolean hasNotificationAccess(android.content.ComponentName);
+    method public void requestNotificationAccess(android.content.ComponentName);
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -9431,6 +9477,7 @@
     field public static final java.lang.String NFC_SERVICE = "nfc";
     field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
     field public static final java.lang.String NSD_SERVICE = "servicediscovery";
+    field public static final java.lang.String OEM_LOCK_SERVICE = "oem_lock";
     field public static final java.lang.String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
     field public static final java.lang.String POWER_SERVICE = "power";
     field public static final java.lang.String PRINT_SERVICE = "print";
@@ -9847,6 +9894,7 @@
     field public static final java.lang.String ACTION_MANAGE_PACKAGE_STORAGE = "android.intent.action.MANAGE_PACKAGE_STORAGE";
     field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
+    field public static final deprecated java.lang.String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
     field public static final java.lang.String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
     field public static final java.lang.String ACTION_MEDIA_BAD_REMOVAL = "android.intent.action.MEDIA_BAD_REMOVAL";
     field public static final java.lang.String ACTION_MEDIA_BUTTON = "android.intent.action.MEDIA_BUTTON";
@@ -9870,6 +9918,7 @@
     field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
+    field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
     field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -10008,6 +10057,7 @@
     field public static final deprecated java.lang.String EXTRA_EMERGENCY_ONLY = "emergencyOnly";
     field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
     field public static final java.lang.String EXTRA_FORCE_FACTORY_RESET = "android.intent.extra.FORCE_FACTORY_RESET";
+    field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
     field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
     field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
     field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -10746,12 +10796,12 @@
     field public java.lang.String[] splitNames;
     field public java.lang.String[] splitPublicSourceDirs;
     field public java.lang.String[] splitSourceDirs;
+    field public java.util.UUID storageUuid;
     field public int targetSdkVersion;
     field public java.lang.String taskAffinity;
     field public int theme;
     field public int uiOptions;
     field public int uid;
-    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -10960,7 +11010,7 @@
 
   public class LauncherApps {
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
-    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
+    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent);
     method public java.util.List<android.os.UserHandle> getProfiles();
     method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int);
@@ -11016,12 +11066,10 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
-    method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
-    field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -11232,6 +11280,7 @@
     method public abstract byte[] getInstantAppCookie();
     method public abstract int getInstantAppCookieMaxSize();
     method public abstract android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+    method public abstract android.content.ComponentName getInstantAppInstallerComponent();
     method public abstract android.content.ComponentName getInstantAppResolverSettingsComponent();
     method public abstract java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
     method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -11656,12 +11705,13 @@
     method public android.content.pm.VersionedPackage getDeclaringPackage();
     method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
     method public java.lang.String getName();
-    method public int getVersion();
-    method public boolean isBuiltin();
-    method public boolean isDynamic();
-    method public boolean isStatic();
+    method public int getType();
+    method public long getVersion();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int TYPE_BUILTIN = 0; // 0x0
+    field public static final int TYPE_DYNAMIC = 1; // 0x1
+    field public static final int TYPE_STATIC = 2; // 0x2
     field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
   }
 
@@ -11669,9 +11719,6 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
-    method public deprecated android.content.ComponentName[] getChooserComponentNames();
-    method public deprecated android.os.PersistableBundle getChooserExtras();
-    method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -11684,7 +11731,6 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
-    method public deprecated boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -11697,11 +11743,9 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
-    method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
-    method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -13304,6 +13348,7 @@
     field public boolean inJustDecodeBounds;
     field public boolean inMutable;
     field public deprecated boolean inPreferQualityOverSpeed;
+    field public android.graphics.ColorSpace inPreferredColorSpace;
     field public android.graphics.Bitmap.Config inPreferredConfig;
     field public boolean inPremultiplied;
     field public deprecated boolean inPurgeable;
@@ -13334,7 +13379,6 @@
 
   public class BitmapShader extends android.graphics.Shader {
     ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
-    method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
   }
 
   public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -13587,8 +13631,6 @@
     ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
     ctor public ColorMatrixColorFilter(float[]);
     method public void getColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrixArray(float[]);
   }
 
   public abstract class ColorSpace {
@@ -13729,8 +13771,6 @@
   public class ComposeShader extends android.graphics.Shader {
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
   }
 
   public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13803,15 +13843,11 @@
     ctor public LightingColorFilter(int, int);
     method public int getColorAdd();
     method public int getColorMultiply();
-    method public void setColorAdd(int);
-    method public void setColorMultiply(int);
   }
 
   public class LinearGradient extends android.graphics.Shader {
     ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public class MaskFilter {
@@ -14321,10 +14357,6 @@
 
   public class PorterDuffColorFilter extends android.graphics.ColorFilter {
     ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public int getColor();
-    method public android.graphics.PorterDuff.Mode getMode();
-    method public void setColor(int);
-    method public void setMode(android.graphics.PorterDuff.Mode);
   }
 
   public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -14334,8 +14366,6 @@
   public class RadialGradient extends android.graphics.Shader {
     ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public final class Rect implements android.os.Parcelable {
@@ -14520,12 +14550,10 @@
   public class SweepGradient extends android.graphics.Shader {
     ctor public SweepGradient(float, float, int[], float[]);
     ctor public SweepGradient(float, float, int, int);
-    method public void set(float, float, int[], float[]);
-    method public void set(float, float, int, int);
   }
 
   public class Typeface {
-    method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+    method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
     method public static android.graphics.Typeface create(java.lang.String, int);
     method public static android.graphics.Typeface create(android.graphics.Typeface, int);
     method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -14552,6 +14580,7 @@
     ctor public Typeface.Builder(java.lang.String);
     ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
     method public android.graphics.Typeface build();
+    method public android.graphics.Typeface.Builder setFallback(java.lang.String);
     method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
     method public android.graphics.Typeface.Builder setItalic(boolean);
@@ -14559,7 +14588,7 @@
     method public android.graphics.Typeface.Builder setWeight(int);
   }
 
-  public static abstract interface Typeface.FontRequestCallback {
+  public static abstract deprecated interface Typeface.FontRequestCallback {
     method public abstract void onTypefaceRequestFailed(int);
     method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
     field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
@@ -14591,7 +14620,7 @@
   public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
     method public void draw(android.graphics.Canvas);
     method public android.graphics.drawable.Drawable getBackground();
-    method public static float getExtraInsetPercentage();
+    method public static float getExtraInsetFraction();
     method public android.graphics.drawable.Drawable getForeground();
     method public android.graphics.Path getIconMask();
     method public int getOpacity();
@@ -15633,15 +15662,16 @@
     field public final int type;
   }
 
-  public final class SensorDirectChannel implements java.lang.AutoCloseable {
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
     method public void close();
-    method public boolean isValid();
+    method public int configure(android.hardware.Sensor, int);
+    method public boolean isOpen();
     field public static final int RATE_FAST = 2; // 0x2
     field public static final int RATE_NORMAL = 1; // 0x1
     field public static final int RATE_STOP = 0; // 0x0
     field public static final int RATE_VERY_FAST = 3; // 0x3
-    field public static final int TYPE_ASHMEM = 1; // 0x1
     field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+    field public static final int TYPE_MEMORY_FILE = 1; // 0x1
   }
 
   public class SensorEvent {
@@ -15675,7 +15705,6 @@
 
   public abstract class SensorManager {
     method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
-    method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
     method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
     method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
     method public boolean flush(android.hardware.SensorEventListener);
@@ -16537,7 +16566,6 @@
     method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
     field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
     field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
-    field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
     field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
     field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -22079,7 +22107,7 @@
     method public double getAccumulatedDeltaRangeMeters();
     method public int getAccumulatedDeltaRangeState();
     method public double getAccumulatedDeltaRangeUncertaintyMeters();
-    method public double getAutomaticGainControlLevelInDb();
+    method public double getAutomaticGainControlLevelDb();
     method public long getCarrierCycles();
     method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
@@ -22095,7 +22123,7 @@
     method public int getState();
     method public int getSvid();
     method public double getTimeOffsetNanos();
-    method public boolean hasAutomaticGainControlLevelInDb();
+    method public boolean hasAutomaticGainControlLevelDb();
     method public boolean hasCarrierCycles();
     method public boolean hasCarrierFrequencyHz();
     method public boolean hasCarrierPhase();
@@ -22189,7 +22217,7 @@
     method public int getSatelliteCount();
     method public int getSvid(int);
     method public boolean hasAlmanacData(int);
-    method public boolean hasCarrierFrequency(int);
+    method public boolean hasCarrierFrequencyHz(int);
     method public boolean hasEphemerisData(int);
     method public boolean usedInFix(int);
     field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
@@ -22495,13 +22523,10 @@
     method public boolean isComplete();
     method public boolean isFromMockProvider();
     method public void makeComplete();
-    method public void removeAccuracy();
-    method public void removeAltitude();
-    method public void removeBearing();
-    method public void removeBearingAccuracy();
-    method public void removeSpeed();
-    method public void removeSpeedAccuracy();
-    method public void removeVerticalAccuracy();
+    method public deprecated void removeAccuracy();
+    method public deprecated void removeAltitude();
+    method public deprecated void removeBearing();
+    method public deprecated void removeSpeed();
     method public void reset();
     method public void set(android.location.Location);
     method public void setAccuracy(float);
@@ -23636,24 +23661,19 @@
     field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
   }
 
-  public final class MediaCas {
+  public final class MediaCas implements java.lang.AutoCloseable {
     ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
-    method public void closeSession(byte[]);
+    method public void close();
     method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
     method public static boolean isSystemIdSupported(int);
-    method public byte[] openSession(int) throws android.media.MediaCasException;
-    method public byte[] openSession(int, int) throws android.media.MediaCasException;
-    method public void processEcm(byte[], byte[], int, int) throws android.media.MediaCasException;
-    method public void processEcm(byte[], byte[]) throws android.media.MediaCasException;
+    method public android.media.MediaCas.Session openSession() throws android.media.MediaCasException;
     method public void processEmm(byte[], int, int) throws android.media.MediaCasException;
     method public void processEmm(byte[]) throws android.media.MediaCasException;
     method public void provision(java.lang.String) throws android.media.MediaCasException;
     method public void refreshEntitlements(int, byte[]) throws android.media.MediaCasException;
-    method public void release();
     method public void sendEvent(int, int, byte[]) throws android.media.MediaCasException;
     method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
     method public void setPrivateData(byte[]) throws android.media.MediaCasException;
-    method public void setSessionPrivateData(byte[], byte[]) throws android.media.MediaCasException;
   }
 
   public static abstract interface MediaCas.EventListener {
@@ -23665,6 +23685,13 @@
     method public int getSystemId();
   }
 
+  public final class MediaCas.Session implements java.lang.AutoCloseable {
+    method public void close();
+    method public void processEcm(byte[], int, int) throws android.media.MediaCasException;
+    method public void processEcm(byte[]) throws android.media.MediaCasException;
+    method public void setPrivateData(byte[]) throws android.media.MediaCasException;
+  }
+
   public class MediaCasException extends java.lang.Exception {
   }
 
@@ -23700,7 +23727,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -23798,6 +23825,19 @@
     method public void set(int, int);
   }
 
+  public static final class MediaCodec.MetricsConstants {
+    field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+    field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+    field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+  }
+
   public static abstract interface MediaCodec.OnFrameRenderedListener {
     method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
   }
@@ -24108,12 +24148,12 @@
     method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
   }
 
-  public final class MediaDescrambler {
+  public final class MediaDescrambler implements java.lang.AutoCloseable {
     ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException;
-    method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
-    method public final void release();
+    method public void close();
+    method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
     method public final boolean requiresSecureDecoderComponent(java.lang.String);
-    method public final void setMediaCasSession(byte[]);
+    method public final void setMediaCasSession(android.media.MediaCas.Session);
   }
 
   public class MediaDescription implements android.os.Parcelable {
@@ -24177,7 +24217,7 @@
     method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
     method public void setPropertyByteArray(java.lang.String, byte[]);
     method public void setPropertyString(java.lang.String, java.lang.String);
-    field public static final int EVENT_KEY_EXPIRED = 3; // 0x3
+    field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
     field public static final int EVENT_KEY_REQUIRED = 2; // 0x2
     field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1
     field public static final int EVENT_SESSION_RECLAIMED = 5; // 0x5
@@ -24251,8 +24291,9 @@
     ctor public MediaExtractor();
     method public boolean advance();
     method public long getCachedDuration();
+    method public android.media.MediaExtractor.CasInfo getCasInfo(int);
     method public android.media.DrmInitData getDrmInitData();
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -24282,6 +24323,17 @@
     field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
   }
 
+  public static final class MediaExtractor.CasInfo {
+    method public android.media.MediaCas.Session getSession();
+    method public int getSystemId();
+  }
+
+  public static final class MediaExtractor.MetricsConstants {
+    field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+    field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
   public final class MediaFormat {
     ctor public MediaFormat();
     method public final boolean containsKey(java.lang.String);
@@ -24507,69 +24559,6 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
-  public final class MediaMetricsSet {
-    method public double getDouble(java.lang.String, double);
-    method public int getInt(java.lang.String, int);
-    method public long getLong(java.lang.String, long);
-    method public java.lang.String getString(java.lang.String, java.lang.String);
-    method public boolean isEmpty();
-    method public java.util.Set<java.lang.String> keySet();
-    method public int size();
-  }
-
-  public static final class MediaMetricsSet.MediaCodec {
-    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
-    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
-    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
-    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
-    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
-    field public static final java.lang.String MODE_AUDIO = "audio";
-    field public static final java.lang.String MODE_VIDEO = "video";
-  }
-
-  public static final class MediaMetricsSet.MediaExtractor {
-    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
-    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
-    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-  }
-
-  public static final class MediaMetricsSet.MediaPlayer {
-    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
-    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
-    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
-    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
-    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
-  }
-
-  public static final class MediaMetricsSet.MediaRecorder {
-    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
-    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
-    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
-  }
-
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -24607,8 +24596,8 @@
     method public android.media.MediaPlayer.DrmInfo getDrmInfo();
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
-    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+    method public android.os.PersistableBundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -24621,7 +24610,7 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
-    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningNetworkErrorException, android.media.MediaPlayer.ProvisioningServerErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
     method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
     method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -24648,7 +24637,7 @@
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
-    method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
+    method public void setOnDrmConfigHelper(android.media.MediaPlayer.OnDrmConfigHelper);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
     method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -24689,6 +24678,10 @@
     field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
     field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
     field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+    field public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3; // 0x3
+    field public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1; // 0x1
+    field public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2; // 0x2
+    field public static final int PREPARE_DRM_STATUS_SUCCESS = 0; // 0x0
     field public static final int SEEK_CLOSEST = 3; // 0x3
     field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
     field public static final int SEEK_NEXT_SYNC = 1; // 0x1
@@ -24698,11 +24691,25 @@
   }
 
   public static final class MediaPlayer.DrmInfo {
-    method public java.lang.String[] getMimes();
     method public java.util.Map<java.util.UUID, byte[]> getPssh();
     method public java.util.UUID[] getSupportedSchemes();
   }
 
+  public static final class MediaPlayer.MetricsConstants {
+    field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+  }
+
   public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
     ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
   }
@@ -24715,7 +24722,7 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
-  public static abstract interface MediaPlayer.OnDrmConfigListener {
+  public static abstract interface MediaPlayer.OnDrmConfigHelper {
     method public abstract void onDrmConfig(android.media.MediaPlayer);
   }
 
@@ -24724,7 +24731,7 @@
   }
 
   public static abstract interface MediaPlayer.OnDrmPreparedListener {
-    method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+    method public abstract void onDrmPrepared(android.media.MediaPlayer, int);
   }
 
   public static abstract interface MediaPlayer.OnErrorListener {
@@ -24755,8 +24762,12 @@
     method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
   }
 
-  public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
-    ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+  public static final class MediaPlayer.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningNetworkErrorException(java.lang.String);
+  }
+
+  public static final class MediaPlayer.ProvisioningServerErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningServerErrorException(java.lang.String);
   }
 
   public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
@@ -24777,7 +24788,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -24796,11 +24807,12 @@
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
     method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
-    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
     method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+    method public void setOutputFile(java.io.File);
     method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
     method public void setOutputFormat(int) throws java.lang.IllegalStateException;
     method public void setPreviewDisplay(android.view.Surface);
@@ -24847,6 +24859,25 @@
     field public static final int VOICE_UPLINK = 2; // 0x2
   }
 
+  public static final class MediaRecorder.MetricsConstants {
+    field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+  }
+
   public static abstract interface MediaRecorder.OnErrorListener {
     method public abstract void onError(android.media.MediaRecorder, int, int);
   }
@@ -25894,7 +25925,6 @@
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public boolean isConnected();
-    method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback);
     method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback);
     method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback);
     method public void unsubscribe(java.lang.String);
@@ -25930,12 +25960,6 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
-  public static abstract class MediaBrowser.SearchCallback {
-    ctor public MediaBrowser.SearchCallback();
-    method public void onError(java.lang.String, android.os.Bundle);
-    method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
-  }
-
   public static abstract class MediaBrowser.SubscriptionCallback {
     ctor public MediaBrowser.SubscriptionCallback();
     method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -26144,8 +26168,6 @@
 
   public final class MediaController {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
-    method public void addQueueItem(android.media.MediaDescription);
-    method public void addQueueItem(android.media.MediaDescription, int);
     method public void adjustVolume(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
@@ -26157,15 +26179,11 @@
     method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue();
     method public java.lang.CharSequence getQueueTitle();
     method public int getRatingType();
-    method public int getRepeatMode();
     method public android.app.PendingIntent getSessionActivity();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public android.media.session.MediaController.TransportControls getTransportControls();
-    method public boolean isShuffleModeEnabled();
     method public void registerCallback(android.media.session.MediaController.Callback);
     method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
-    method public void removeQueueItem(android.media.MediaDescription);
-    method public void removeQueueItemAt(int);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void setVolumeTo(int, int);
     method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -26179,10 +26197,8 @@
     method public void onPlaybackStateChanged(android.media.session.PlaybackState);
     method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>);
     method public void onQueueTitleChanged(java.lang.CharSequence);
-    method public void onRepeatModeChanged(int);
     method public void onSessionDestroyed();
     method public void onSessionEvent(java.lang.String, android.os.Bundle);
-    method public void onShuffleModeChanged(boolean);
   }
 
   public static final class MediaController.PlaybackInfo {
@@ -26211,8 +26227,6 @@
     method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
     method public void sendCustomAction(java.lang.String, android.os.Bundle);
     method public void setRating(android.media.Rating);
-    method public void setRepeatMode(int);
-    method public void setShuffleModeEnabled(boolean);
     method public void skipToNext();
     method public void skipToPrevious();
     method public void skipToQueueItem(long);
@@ -26239,18 +26253,13 @@
     method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>);
     method public void setQueueTitle(java.lang.CharSequence);
     method public void setRatingType(int);
-    method public void setRepeatMode(int);
     method public void setSessionActivity(android.app.PendingIntent);
-    method public void setShuffleModeEnabled(boolean);
     field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
-    field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
     field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
   public static abstract class MediaSession.Callback {
     ctor public MediaSession.Callback();
-    method public void onAddQueueItem(android.media.MediaDescription);
-    method public void onAddQueueItem(android.media.MediaDescription, int);
     method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void onCustomAction(java.lang.String, android.os.Bundle);
     method public void onFastForward();
@@ -26264,13 +26273,9 @@
     method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
     method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
-    method public void onRemoveQueueItem(android.media.MediaDescription);
-    method public void onRemoveQueueItemAt(int);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
-    method public void onSetRepeatMode(int);
-    method public void onSetShuffleModeEnabled(boolean);
     method public void onSkipToNext();
     method public void onSkipToPrevious();
     method public void onSkipToQueueItem(long);
@@ -26341,17 +26346,12 @@
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
     field public static final long ACTION_SET_RATING = 128L; // 0x80L
-    field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L
-    field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L
     field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L
     field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
-    field public static final int REPEAT_MODE_ALL = 2; // 0x2
-    field public static final int REPEAT_MODE_NONE = 0; // 0x0
-    field public static final int REPEAT_MODE_ONE = 1; // 0x1
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
     field public static final int STATE_ERROR = 7; // 0x7
@@ -26483,12 +26483,15 @@
     method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
     method public static boolean isChannelUriForTunerInput(android.net.Uri);
     method public static boolean isProgramUri(android.net.Uri);
+    method public static void requestChannelBrowsable(android.content.Context, long);
+    field public static final java.lang.String ACTION_CHANNEL_BROWSABLE_REQUESTED = "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED";
     field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
-    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
     field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+    field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String AUTHORITY = "android.media.tv";
+    field public static final java.lang.String EXTRA_BLOCKED_PACKAGES = "android.media.tv.extra.BLOCKED_PACKAGES";
     field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
     field public static final java.lang.String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
     field public static final java.lang.String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
@@ -26496,9 +26499,16 @@
     field public static final java.lang.String EXTRA_EXISTING_COLUMN_NAMES = "android.media.tv.extra.EXISTING_COLUMN_NAMES";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
+    field public static final java.lang.String EXTRA_RESULT_CODE = "android.media.tv.extra.RESULT_CODE";
     field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
     field public static final java.lang.String METHOD_ADD_COLUMN = "add_column";
+    field public static final java.lang.String METHOD_BLOCK_PACKAGE = "block_package";
+    field public static final java.lang.String METHOD_GET_BLOCKED_PACKAGES = "get_blocked_packages";
     field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
+    field public static final java.lang.String METHOD_UNBLOCK_PACKAGE = "unblock_package";
+    field public static final int RESULT_ERROR_INVALID_ARGUMENT = 2; // 0x2
+    field public static final int RESULT_ERROR_IO = 1; // 0x1
+    field public static final int RESULT_OK = 0; // 0x0
   }
 
   public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
@@ -26529,7 +26539,6 @@
     field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
     field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
     field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
-    field public static final java.lang.String COLUMN_SYSTEM_APPROVED = "system_approved";
     field public static final java.lang.String COLUMN_TRANSIENT = "transient";
     field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
     field public static final java.lang.String COLUMN_TYPE = "type";
@@ -26590,9 +26599,10 @@
 
   public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
-    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
-    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+    field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
     field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
     field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
     field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
     field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -26775,9 +26785,10 @@
   public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
     ctor public TvContract.WatchNextPrograms();
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
-    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
-    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+    field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
     field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
     field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
     field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
     field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -27698,14 +27709,10 @@
   }
 
   public final class IpSecManager {
-    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
     method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
     field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -27724,7 +27731,7 @@
   }
 
   public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
-    method public void close();
+    method public void close() throws java.io.IOException;
     method public int getPort();
     method public java.io.FileDescriptor getSocket();
   }
@@ -28127,10 +28134,6 @@
     field public static final java.lang.String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
     field public static final java.lang.String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
     field public static final java.lang.String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
-    field public static final deprecated int BADGING_4K = 30; // 0x1e
-    field public static final deprecated int BADGING_HD = 20; // 0x14
-    field public static final deprecated int BADGING_NONE = 0; // 0x0
-    field public static final deprecated int BADGING_SD = 10; // 0xa
     field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
     field public final android.os.Bundle attributes;
     field public final boolean meteredHint;
@@ -28138,9 +28141,6 @@
     field public final android.net.RssiCurve rssiCurve;
   }
 
-  public static abstract deprecated class ScoredNetwork.Badging implements java.lang.annotation.Annotation {
-  }
-
   public class TrafficStats {
     ctor public TrafficStats();
     method public static void clearThreadStatsTag();
@@ -29483,9 +29483,9 @@
   }
 
   public class DiscoverySession {
-    method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
-    method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
-    method public java.lang.String createNetworkSpecifierPmk(android.net.wifi.aware.PeerHandle, byte[]);
+    method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+    method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+    method public android.net.NetworkSpecifier createNetworkSpecifierPmk(android.net.wifi.aware.PeerHandle, byte[]);
     method public void destroy();
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
@@ -29571,9 +29571,9 @@
   }
 
   public class WifiAwareSession {
-    method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
-    method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
-    method public java.lang.String createNetworkSpecifierPmk(int, byte[], byte[]);
+    method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+    method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+    method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, byte[], byte[]);
     method public void destroy();
     method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
     method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
@@ -33518,6 +33518,7 @@
     method public android.util.SizeF getSizeF(java.lang.String);
     method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
+    method public java.util.UUID getUuid(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
     method public void putBinder(java.lang.String, android.os.IBinder);
@@ -33542,6 +33543,7 @@
     method public void putSizeF(java.lang.String, android.util.SizeF);
     method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>);
     method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>);
+    method public void putUuid(java.lang.String, java.util.UUID);
     method public void readFromParcel(android.os.Parcel);
     method public void setClassLoader(java.lang.ClassLoader);
     method public void writeToParcel(android.os.Parcel, int);
@@ -34101,6 +34103,7 @@
     method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
     method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
     method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final java.util.UUID readUuid();
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -34146,6 +34149,7 @@
     method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
     method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
     method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
+    method public final void writeUuid(java.util.UUID);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -34361,6 +34365,7 @@
     method public static void rebootWipeUserData(android.content.Context) throws java.io.IOException;
     method public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException;
     method public static void verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File) throws java.security.GeneralSecurityException, java.io.IOException;
+    method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException;
   }
 
   public static abstract interface RecoverySystem.ProgressListener {
@@ -34656,7 +34661,7 @@
     field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
     field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
     field public static final java.lang.String DISALLOW_NETWORK_RESET = "no_network_reset";
-    field public static final java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
+    field public static final deprecated java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
     field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
     field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
     field public static final java.lang.String DISALLOW_REMOVE_MANAGED_PROFILE = "no_remove_managed_profile";
@@ -34808,7 +34813,7 @@
     field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
     field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
     field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
-    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
+    field public static final deprecated int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
     field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
     field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
     field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -34882,15 +34887,16 @@
   }
 
   public class StorageManager {
-    method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
-    method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes(java.io.File);
-    method public long getCacheSizeBytes(java.io.File);
+    method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException;
+    method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException;
+    method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException;
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
     method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
+    method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
     method public boolean isEncrypted(java.io.File);
@@ -34902,7 +34908,10 @@
     method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException;
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
     field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
+    field public static final java.lang.String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
+    field public static final java.lang.String EXTRA_UUID = "android.os.storage.extra.UUID";
     field public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1
+    field public static final java.util.UUID UUID_DEFAULT;
   }
 
   public final class StorageVolume implements android.os.Parcelable {
@@ -37475,6 +37484,10 @@
   }
 
   public class FontsContract {
+    method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
+    method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
+    method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
   }
 
   public static final class FontsContract.Columns implements android.provider.BaseColumns {
@@ -37491,6 +37504,35 @@
     field public static final java.lang.String WEIGHT = "font_weight";
   }
 
+  public static class FontsContract.FontFamilyResult {
+    method public android.provider.FontsContract.FontInfo[] getFonts();
+    method public int getStatusCode();
+    field public static final int STATUS_OK = 0; // 0x0
+    field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+    field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+  }
+
+  public static class FontsContract.FontInfo {
+    method public android.graphics.fonts.FontVariationAxis[] getAxes();
+    method public int getResultCode();
+    method public int getTtcIndex();
+    method public android.net.Uri getUri();
+    method public int getWeight();
+    method public boolean isItalic();
+  }
+
+  public static class FontsContract.FontRequestCallback {
+    ctor public FontsContract.FontRequestCallback();
+    method public void onTypefaceRequestFailed(int);
+    method public void onTypefaceRetrieved(android.graphics.Typeface);
+    field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+    field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+    field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+    field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+    field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+    field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+  }
+
   public final deprecated class LiveFolders implements android.provider.BaseColumns {
     field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
     field public static final java.lang.String DESCRIPTION = "description";
@@ -38063,7 +38105,6 @@
     field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
     field public static final java.lang.String MODE_RINGER = "mode_ringer";
     field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
-    field public static final java.lang.String NETWORK_RECOMMENDATIONS_ENABLED = "network_recommendations_enabled";
     field public static final java.lang.String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
     field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth";
     field public static final java.lang.String RADIO_CELL = "cell";
@@ -38513,6 +38554,16 @@
     field public static final java.lang.String SUBSCRIPTION_ID = "pending_sub_id";
   }
 
+  public static final class Telephony.ServiceStateTable {
+    method public static android.net.Uri getUriForSubId(int);
+    method public static android.net.Uri getUriForSubIdAndField(int, java.lang.String);
+    field public static final java.lang.String AUTHORITY = "service-state";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection";
+    field public static final java.lang.String VOICE_OPERATOR_NUMERIC = "voice_operator_numeric";
+    field public static final java.lang.String VOICE_REG_STATE = "voice_reg_state";
+  }
+
   public static final class Telephony.Sms implements android.provider.BaseColumns android.provider.Telephony.TextBasedSmsColumns {
     method public static java.lang.String getDefaultSmsPackage(android.content.Context);
     field public static final android.net.Uri CONTENT_URI;
@@ -40099,11 +40150,14 @@
   public abstract class AutofillService extends android.app.Service {
     ctor public AutofillService();
     method public final deprecated void disableSelf();
+    method public final android.service.autofill.FillEventHistory getFillEventHistory();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
-    method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+    method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+    method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
@@ -40119,6 +40173,7 @@
     ctor public Dataset.Builder();
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.Dataset.Builder setId(java.lang.String);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews);
   }
@@ -40128,6 +40183,42 @@
     method public void onSuccess(android.service.autofill.FillResponse);
   }
 
+  public final class FillContext implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getRequestId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+  }
+
+  public final class FillEventHistory implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR;
+  }
+
+  public static final class FillEventHistory.Event {
+    method public java.lang.String getDatasetId();
+    method public int getType();
+    field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
+    field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
+    field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
+    field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+  }
+
+  public final class FillRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public int getFlags();
+    method public int getId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+  }
+
   public final class FillResponse implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -40139,7 +40230,9 @@
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
     method public android.service.autofill.FillResponse build();
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
-    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+    method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -40152,6 +40245,7 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
     field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
     field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
     field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -40164,10 +40258,19 @@
     ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
     method public android.service.autofill.SaveInfo build();
     method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setFlags(int);
     method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
   }
 
+  public final class SaveRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+  }
+
 }
 
 package android.service.carrier {
@@ -40287,7 +40390,7 @@
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public final void finish();
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
@@ -40349,7 +40452,6 @@
     method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
     method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle);
     method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>);
-    method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
     method public void setSessionToken(android.media.session.MediaSession.Token);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
   }
@@ -40457,16 +40559,16 @@
     method public final int getCurrentInterruptionFilter();
     method public final int getCurrentListenerHints();
     method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
-    method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
-    method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
+    method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String, android.os.UserHandle);
+    method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String, android.os.UserHandle);
     method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onInterruptionFilterChanged(int);
     method public void onListenerConnected();
     method public void onListenerDisconnected();
     method public void onListenerHintsChanged(int);
-    method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
-    method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
+    method public void onNotificationChannelGroupModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannelGroup, int);
+    method public void onNotificationChannelModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannel, int);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -40483,7 +40585,7 @@
     method public final void snoozeNotification(java.lang.String, java.lang.String);
     method public final void snoozeNotification(java.lang.String, long);
     method public void unregisterAsSystemService() throws android.os.RemoteException;
-    method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
+    method public final void updateNotificationChannel(java.lang.String, android.os.UserHandle, android.app.NotificationChannel);
     field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
     field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
@@ -40581,15 +40683,26 @@
 
 }
 
+package android.service.oemlock {
+
+  public class OemLockManager {
+    method public boolean isOemUnlockAllowedByCarrier();
+    method public boolean isOemUnlockAllowedByUser();
+    method public void setOemUnlockAllowedByCarrier(boolean, byte[]);
+    method public void setOemUnlockAllowedByUser(boolean);
+  }
+
+}
+
 package android.service.persistentdata {
 
   public class PersistentDataBlockManager {
     method public int getDataBlockSize();
     method public int getFlashLockState();
     method public long getMaximumDataBlockSize();
-    method public boolean getOemUnlockEnabled();
+    method public deprecated boolean getOemUnlockEnabled();
     method public byte[] read();
-    method public void setOemUnlockEnabled(boolean);
+    method public deprecated void setOemUnlockEnabled(boolean);
     method public void wipe();
     method public int write(byte[]);
     field public static final int FLASH_LOCK_LOCKED = 1; // 0x1
@@ -40932,10 +41045,12 @@
     method public int getDesiredMinimumHeight();
     method public int getDesiredMinimumWidth();
     method public android.view.SurfaceHolder getSurfaceHolder();
+    method public void invalidateColors();
     method public boolean isPreview();
     method public boolean isVisible();
     method public void onApplyWindowInsets(android.view.WindowInsets);
     method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+    method public android.app.WallpaperColors onComputeWallpaperColors();
     method public void onCreate(android.view.SurfaceHolder);
     method public void onDesiredSizeChanged(int, int);
     method public void onDestroy();
@@ -43643,7 +43758,7 @@
     method public boolean isSmsCapable();
     method public boolean isTtyModeSupported();
     method public boolean isVideoCallingEnabled();
-    method public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
+    method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isVoiceCapable();
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
@@ -43660,7 +43775,7 @@
     method public boolean setPreferredNetworkTypeToGlobal();
     method public boolean setRadio(boolean);
     method public boolean setRadioPower(boolean);
-    method public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
+    method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
     method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
     method public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
     method public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
@@ -44359,7 +44474,6 @@
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
     method public android.content.ComponentName startService(android.content.Intent);
-    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean stopService(android.content.Intent);
     method public void unbindService(android.content.ServiceConnection);
     method public void unregisterReceiver(android.content.BroadcastReceiver);
@@ -44461,6 +44575,7 @@
     method public byte[] getInstantAppCookie();
     method public int getInstantAppCookieMaxSize();
     method public android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String);
+    method public android.content.ComponentName getInstantAppInstallerComponent();
     method public android.content.ComponentName getInstantAppResolverSettingsComponent();
     method public java.util.List<android.content.pm.InstantAppInfo> getInstantApps();
     method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -47409,7 +47524,6 @@
     method public boolean isValid();
     method public boolean isWideColorGamut();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
-    field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int FLAG_PRESENTATION = 8; // 0x8
     field public static final int FLAG_PRIVATE = 4; // 0x4
     field public static final int FLAG_ROUND = 16; // 0x10
@@ -48890,7 +49004,6 @@
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
     method public java.lang.String[] getAutofillHints();
-    method public int getAutofillMode();
     method public int getAutofillType();
     method public android.view.autofill.AutofillValue getAutofillValue();
     method public android.graphics.drawable.Drawable getBackground();
@@ -48979,7 +49092,6 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
-    method public int getResolvedAutofillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -49212,7 +49324,6 @@
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
     method public void setAutofillHints(java.lang.String...);
-    method public void setAutofillMode(int);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
     method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -49368,9 +49479,6 @@
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
     field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
-    field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
-    field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
-    field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
     field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
     field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
     field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -49418,7 +49526,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
     field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -49938,7 +50048,6 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
-    method public default int getResolvedAutofillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -50627,7 +50736,6 @@
 
   public final class AccessibilityManager {
     method public void addAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
-    method public boolean addAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
     method public boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
     method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
@@ -50637,16 +50745,11 @@
     method public boolean isEnabled();
     method public boolean isTouchExplorationEnabled();
     method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
-    method public boolean removeAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
     method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
     method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
   }
 
-  public static abstract interface AccessibilityManager.AccessibilityServicesStateChangeListener {
-    method public abstract void onAccessibilityServicesStateChanged();
-  }
-
   public static abstract interface AccessibilityManager.AccessibilityStateChangeListener {
     method public abstract void onAccessibilityStateChanged(boolean);
   }
@@ -51337,7 +51440,7 @@
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
     field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
-    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+    field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
   }
 
   public static abstract class AutofillManager.AutofillCallback {
@@ -53576,6 +53679,7 @@
     method public java.lang.String getFormat();
     method public android.widget.Chronometer.OnChronometerTickListener getOnChronometerTickListener();
     method public boolean isCountDown();
+    method public boolean isTheFinalCountDown();
     method public void setBase(long);
     method public void setCountDown(boolean);
     method public void setFormat(java.lang.String);
@@ -59245,6 +59349,7 @@
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
     method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle explicitCastArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
     method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 1effe9c..6d82a49 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -5,10 +5,6 @@
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
   }
 
-  public static class Notification.Builder {
-    method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
-  }
-
   public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
     method public deprecated void showAsNotification(android.content.Context);
   }
@@ -24,6 +20,20 @@
 
 }
 
+package android.app.usage {
+
+  public class StorageStatsManager {
+    method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated boolean isQuotaSupported(java.lang.String);
+    method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+  }
+
+}
+
 package android.content {
 
   public abstract class Context {
@@ -39,6 +49,10 @@
 
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String volumeUuid;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -47,6 +61,12 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+  }
+
 }
 
 package android.database {
@@ -98,6 +118,28 @@
 
 }
 
+package android.hardware {
+
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
+    method public deprecated boolean isValid();
+  }
+
+  public abstract class SensorManager {
+    method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+  }
+
+}
+
+package android.location {
+
+  public class Location implements android.os.Parcelable {
+    method public deprecated void removeBearingAccuracy();
+    method public deprecated void removeSpeedAccuracy();
+    method public deprecated void removeVerticalAccuracy();
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
@@ -166,10 +208,14 @@
 package android.os.storage {
 
   public class StorageManager {
-    method public deprecated long getCacheQuotaBytes();
-    method public deprecated long getCacheSizeBytes();
-    method public deprecated long getExternalCacheQuotaBytes();
-    method public deprecated long getExternalCacheSizeBytes();
+    method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException;
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
     method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException;
diff --git a/api/test-current.txt b/api/test-current.txt
index 48ade55..54b093d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -210,6 +210,8 @@
   public static final class R.attr {
     ctor public R.attr();
     field public static final int __removed1 = 16844099; // 0x1010543
+    field public static final int __removed2 = 16844104; // 0x1010548
+    field public static final int __removed3 = 16844116; // 0x1010554
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -312,7 +314,6 @@
     field public static final int autoUrlDetect = 16843404; // 0x101028c
     field public static final int autoVerify = 16844014; // 0x10104ee
     field public static final int autofillHints = 16844121; // 0x1010559
-    field public static final int autofillMode = 16844116; // 0x1010554
     field public static final int background = 16842964; // 0x10100d4
     field public static final int backgroundDimAmount = 16842802; // 0x1010032
     field public static final int backgroundDimEnabled = 16843295; // 0x101021f
@@ -992,6 +993,7 @@
     field public static final int persistableMode = 16843821; // 0x101042d
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
+    field public static final int persistentFeature = 16844134; // 0x1010566
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
@@ -1270,7 +1272,6 @@
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
     field public static final int supportsAssist = 16844016; // 0x10104f0
-    field public static final int supportsDismissingWindow = 16844104; // 0x1010548
     field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
     field public static final int supportsLocalInteraction = 16844047; // 0x101050f
     field public static final int supportsPictureInPicture = 16844023; // 0x10104f7
@@ -1540,6 +1541,7 @@
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
+    field public static final int windowSplashscreenContent = 16844135; // 0x1010567
     field public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
     field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
     field public static final int windowTitleSize = 16842842; // 0x101005a
@@ -1708,6 +1710,7 @@
     field public static final int ic_notification_clear_all = 17301594; // 0x108005a
     field public static final int ic_notification_overlay = 17301595; // 0x108005b
     field public static final int ic_partial_secure = 17301596; // 0x108005c
+    field public static final int ic_picture_in_picture = 17301685; // 0x10800b5
     field public static final int ic_popup_disk_full = 17301597; // 0x108005d
     field public static final int ic_popup_reminder = 17301598; // 0x108005e
     field public static final int ic_popup_sync = 17301599; // 0x108005f
@@ -2998,6 +3001,7 @@
     method public android.accounts.AccountManagerFuture<android.os.Bundle> startAddAccountSession(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> startUpdateCredentialsSession(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> updateCredentials(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
+    field public static final java.lang.String ACTION_ACCOUNT_REMOVED = "android.accounts.action.ACCOUNT_REMOVED";
     field public static final java.lang.String ACTION_AUTHENTICATOR_INTENT = "android.accounts.AccountAuthenticator";
     field public static final java.lang.String AUTHENTICATOR_ATTRIBUTES_NAME = "account-authenticator";
     field public static final java.lang.String AUTHENTICATOR_META_DATA_NAME = "android.accounts.AccountAuthenticator";
@@ -3614,6 +3618,7 @@
     method public android.net.Uri getReferrer();
     method public int getRequestedOrientation();
     method public final android.view.SearchEvent getSearchEvent();
+    method public long getStartInitiatedTime();
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
@@ -3848,7 +3853,7 @@
     method public deprecated java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException;
     method public java.util.List<android.app.ActivityManager.RunningAppProcessInfo> getRunningAppProcesses();
     method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
-    method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
+    method public deprecated java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
     method public deprecated java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
     method public int getUidImportance(int);
     method public deprecated boolean isInLockTaskMode();
@@ -3948,7 +3953,8 @@
     field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
     field public static final int IMPORTANCE_FOREGROUND_SERVICE = 125; // 0x7d
     field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
-    field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82
+    field public static final int IMPORTANCE_PERCEPTIBLE = 230; // 0xe6
+    field public static final deprecated int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130; // 0x82
     field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
     field public static final int IMPORTANCE_TOP_SLEEPING = 150; // 0x96
     field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
@@ -4585,6 +4591,7 @@
     method public final android.app.FragmentManager getFragmentManager();
     method public final java.lang.Object getHost();
     method public final int getId();
+    method public final android.view.LayoutInflater getLayoutInflater();
     method public android.app.LoaderManager getLoaderManager();
     method public final android.app.Fragment getParentFragment();
     method public android.transition.Transition getReenterTransition();
@@ -4710,7 +4717,7 @@
   public abstract class FragmentContainer {
     ctor public FragmentContainer();
     method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle);
-    method public abstract android.view.View onFindViewById(int);
+    method public abstract <T extends android.view.View> T onFindViewById(int);
     method public abstract boolean onHasView();
   }
 
@@ -4761,7 +4768,7 @@
     ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
     method public void onAttachFragment(android.app.Fragment);
     method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
-    method public android.view.View onFindViewById(int);
+    method public <T extends android.view.View> T onFindViewById(int);
     method public abstract E onGetHost();
     method public android.view.LayoutInflater onGetLayoutInflater();
     method public int onGetWindowAnimations();
@@ -5613,7 +5620,6 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
-    method public deprecated android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -6107,6 +6113,17 @@
     method public void onDetached();
   }
 
+  public final class WallpaperColors implements android.os.Parcelable {
+    ctor public WallpaperColors(android.os.Parcel);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>);
+    ctor public WallpaperColors(java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>>, boolean);
+    method public int describeContents();
+    method public java.util.List<android.util.Pair<android.graphics.Color, java.lang.Integer>> getColors();
+    method public boolean supportsDarkText();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
+  }
+
   public final class WallpaperInfo implements android.os.Parcelable {
     ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
@@ -6129,6 +6146,8 @@
   }
 
   public class WallpaperManager {
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
+    method public void addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler);
     method public void clear() throws java.io.IOException;
     method public void clear(int) throws java.io.IOException;
     method public void clearWallpaperOffsets(android.os.IBinder);
@@ -6143,6 +6162,7 @@
     method public android.graphics.drawable.Drawable getDrawable();
     method public android.graphics.drawable.Drawable getFastDrawable();
     method public static android.app.WallpaperManager getInstance(android.content.Context);
+    method public android.app.WallpaperColors getWallpaperColors(int);
     method public android.os.ParcelFileDescriptor getWallpaperFile(int);
     method public int getWallpaperId(int);
     method public android.app.WallpaperInfo getWallpaperInfo();
@@ -6151,6 +6171,7 @@
     method public boolean isWallpaperSupported();
     method public android.graphics.drawable.Drawable peekDrawable();
     method public android.graphics.drawable.Drawable peekFastDrawable();
+    method public void removeOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener);
     method public void sendWallpaperCommand(android.os.IBinder, java.lang.String, int, int, int, android.os.Bundle);
     method public void setBitmap(android.graphics.Bitmap) throws java.io.IOException;
     method public int setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean) throws java.io.IOException;
@@ -6175,6 +6196,10 @@
     field public static final java.lang.String WALLPAPER_PREVIEW_META_DATA = "android.wallpaper.preview";
   }
 
+  public static abstract interface WallpaperManager.OnColorsChangedListener {
+    method public abstract void onColorsChanged(android.app.WallpaperColors, int);
+  }
+
 }
 
 package android.app.admin {
@@ -6633,7 +6658,7 @@
 
   public static class AssistStructure.ViewNode {
     method public float getAlpha();
-    method public java.lang.String[] getAutoFillHints();
+    method public java.lang.String[] getAutofillHints();
     method public android.view.autofill.AutofillId getAutofillId();
     method public java.lang.String[] getAutofillOptions();
     method public int getAutofillType();
@@ -6822,6 +6847,7 @@
     field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L
     field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L
     field public static final int NETWORK_TYPE_ANY = 1; // 0x1
+    field public static final int NETWORK_TYPE_METERED = 4; // 0x4
     field public static final int NETWORK_TYPE_NONE = 0; // 0x0
     field public static final int NETWORK_TYPE_NOT_ROAMING = 3; // 0x3
     field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2
@@ -6896,6 +6922,14 @@
     field public static final java.lang.String PERMISSION_BIND = "android.permission.BIND_JOB_SERVICE";
   }
 
+  public abstract class JobServiceEngine {
+    ctor public JobServiceEngine(android.app.Service);
+    method public final android.os.IBinder getBinder();
+    method public final void jobFinished(android.app.job.JobParameters, boolean);
+    method public abstract boolean onStartJob(android.app.job.JobParameters);
+    method public abstract boolean onStopJob(android.app.job.JobParameters);
+  }
+
   public final class JobWorkItem implements android.os.Parcelable {
     ctor public JobWorkItem(android.content.Intent);
     ctor public JobWorkItem(android.os.Parcel);
@@ -6993,13 +7027,13 @@
   }
 
   public class StorageStatsManager {
-    method public long getFreeBytes(java.lang.String);
-    method public long getTotalBytes(java.lang.String);
-    method public boolean isQuotaSupported(java.lang.String);
-    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle);
-    method public android.app.usage.StorageStats queryStatsForUid(java.lang.String, int);
-    method public android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle);
+    method public long getFreeBytes(java.util.UUID) throws java.io.IOException;
+    method public long getTotalBytes(java.util.UUID) throws java.io.IOException;
+    method public boolean isQuotaSupported(java.util.UUID);
+    method public android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForPackage(java.util.UUID, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public android.app.usage.StorageStats queryStatsForUid(java.util.UUID, int) throws java.io.IOException;
+    method public android.app.usage.StorageStats queryStatsForUser(java.util.UUID, android.os.UserHandle) throws java.io.IOException;
   }
 
   public final class UsageEvents implements android.os.Parcelable {
@@ -7064,6 +7098,7 @@
     method public static void deleteAllHosts();
     method public void deleteAppWidgetId(int);
     method public void deleteHost();
+    method public int[] getAppWidgetIds();
     method protected android.appwidget.AppWidgetHostView onCreateView(android.content.Context, int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProviderChanged(int, android.appwidget.AppWidgetProviderInfo);
     method protected void onProvidersChanged();
@@ -8097,7 +8132,12 @@
     method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
     method public void startScan(android.bluetooth.le.ScanCallback);
     method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
+    method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
     method public void stopScan(android.bluetooth.le.ScanCallback);
+    method public void stopScan(android.app.PendingIntent);
+    field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+    field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+    field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
   }
 
   public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
@@ -8281,6 +8321,8 @@
     method public void associate(android.companion.AssociationRequest, android.companion.CompanionDeviceManager.Callback, android.os.Handler);
     method public void disassociate(java.lang.String);
     method public java.util.List<java.lang.String> getAssociations();
+    method public boolean hasNotificationAccess(android.content.ComponentName);
+    method public void requestNotificationAccess(android.content.ComponentName);
     field public static final java.lang.String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
@@ -9378,6 +9420,7 @@
     field public static final java.lang.String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED";
     field public static final java.lang.String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED";
+    field public static final java.lang.String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
     field public static final java.lang.String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
     field public static final java.lang.String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED";
     field public static final deprecated java.lang.String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
@@ -9494,6 +9537,7 @@
     field public static final java.lang.String EXTRA_DONT_KILL_APP = "android.intent.extra.DONT_KILL_APP";
     field public static final java.lang.String EXTRA_EMAIL = "android.intent.extra.EMAIL";
     field public static final java.lang.String EXTRA_EXCLUDE_COMPONENTS = "android.intent.extra.EXCLUDE_COMPONENTS";
+    field public static final java.lang.String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
     field public static final java.lang.String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
     field public static final java.lang.String EXTRA_INDEX = "android.intent.extra.INDEX";
     field public static final java.lang.String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
@@ -10213,12 +10257,12 @@
     field public java.lang.String[] splitNames;
     field public java.lang.String[] splitPublicSourceDirs;
     field public java.lang.String[] splitSourceDirs;
+    field public java.util.UUID storageUuid;
     field public int targetSdkVersion;
     field public java.lang.String taskAffinity;
     field public int theme;
     field public int uiOptions;
     field public int uid;
-    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -10338,7 +10382,7 @@
   public class LauncherApps {
     ctor public LauncherApps(android.content.Context);
     method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
-    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle);
+    method public android.content.pm.ApplicationInfo getApplicationInfo(java.lang.String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent);
     method public java.util.List<android.os.UserHandle> getProfiles();
     method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int);
@@ -10394,12 +10438,10 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
-    method public deprecated android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
-    field public static final deprecated int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10944,12 +10986,13 @@
     method public android.content.pm.VersionedPackage getDeclaringPackage();
     method public java.util.List<android.content.pm.VersionedPackage> getDependentPackages();
     method public java.lang.String getName();
-    method public int getVersion();
-    method public boolean isBuiltin();
-    method public boolean isDynamic();
-    method public boolean isStatic();
+    method public int getType();
+    method public long getVersion();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
+    field public static final int TYPE_BUILTIN = 0; // 0x0
+    field public static final int TYPE_DYNAMIC = 1; // 0x1
+    field public static final int TYPE_STATIC = 2; // 0x2
     field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
   }
 
@@ -10957,9 +11000,6 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
-    method public deprecated android.content.ComponentName[] getChooserComponentNames();
-    method public deprecated android.os.PersistableBundle getChooserExtras();
-    method public deprecated android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -10972,7 +11012,6 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
-    method public deprecated boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -10985,11 +11024,9 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
-    method public deprecated android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
-    method public deprecated android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -12579,6 +12616,7 @@
     field public boolean inJustDecodeBounds;
     field public boolean inMutable;
     field public deprecated boolean inPreferQualityOverSpeed;
+    field public android.graphics.ColorSpace inPreferredColorSpace;
     field public android.graphics.Bitmap.Config inPreferredConfig;
     field public boolean inPremultiplied;
     field public deprecated boolean inPurgeable;
@@ -12609,7 +12647,6 @@
 
   public class BitmapShader extends android.graphics.Shader {
     ctor public BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
-    method public void set(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
   }
 
   public class BlurMaskFilter extends android.graphics.MaskFilter {
@@ -12862,8 +12899,6 @@
     ctor public ColorMatrixColorFilter(android.graphics.ColorMatrix);
     ctor public ColorMatrixColorFilter(float[]);
     method public void getColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrix(android.graphics.ColorMatrix);
-    method public void setColorMatrixArray(float[]);
   }
 
   public abstract class ColorSpace {
@@ -13004,8 +13039,6 @@
   public class ComposeShader extends android.graphics.Shader {
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
     ctor public ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode);
-    method public void set(android.graphics.Shader, android.graphics.Shader, android.graphics.PorterDuff.Mode);
   }
 
   public class CornerPathEffect extends android.graphics.PathEffect {
@@ -13078,15 +13111,11 @@
     ctor public LightingColorFilter(int, int);
     method public int getColorAdd();
     method public int getColorMultiply();
-    method public void setColorAdd(int);
-    method public void setColorMultiply(int);
   }
 
   public class LinearGradient extends android.graphics.Shader {
     ctor public LinearGradient(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public LinearGradient(float, float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public class MaskFilter {
@@ -13596,10 +13625,6 @@
 
   public class PorterDuffColorFilter extends android.graphics.ColorFilter {
     ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public int getColor();
-    method public android.graphics.PorterDuff.Mode getMode();
-    method public void setColor(int);
-    method public void setMode(android.graphics.PorterDuff.Mode);
   }
 
   public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -13609,8 +13634,6 @@
   public class RadialGradient extends android.graphics.Shader {
     ctor public RadialGradient(float, float, float, int[], float[], android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, int, int, android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int[], float[], android.graphics.Shader.TileMode);
-    method public void set(float, float, float, int, int, android.graphics.Shader.TileMode);
   }
 
   public final class Rect implements android.os.Parcelable {
@@ -13795,12 +13818,10 @@
   public class SweepGradient extends android.graphics.Shader {
     ctor public SweepGradient(float, float, int[], float[]);
     ctor public SweepGradient(float, float, int, int);
-    method public void set(float, float, int[], float[]);
-    method public void set(float, float, int, int);
   }
 
   public class Typeface {
-    method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+    method public static deprecated void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
     method public static android.graphics.Typeface create(java.lang.String, int);
     method public static android.graphics.Typeface create(android.graphics.Typeface, int);
     method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13827,6 +13848,7 @@
     ctor public Typeface.Builder(java.lang.String);
     ctor public Typeface.Builder(android.content.res.AssetManager, java.lang.String);
     method public android.graphics.Typeface build();
+    method public android.graphics.Typeface.Builder setFallback(java.lang.String);
     method public android.graphics.Typeface.Builder setFontVariationSettings(java.lang.String) throws android.graphics.fonts.FontVariationAxis.InvalidFormatException;
     method public android.graphics.Typeface.Builder setFontVariationSettings(android.graphics.fonts.FontVariationAxis[]);
     method public android.graphics.Typeface.Builder setItalic(boolean);
@@ -13834,7 +13856,7 @@
     method public android.graphics.Typeface.Builder setWeight(int);
   }
 
-  public static abstract interface Typeface.FontRequestCallback {
+  public static abstract deprecated interface Typeface.FontRequestCallback {
     method public abstract void onTypefaceRequestFailed(int);
     method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
     field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
@@ -13866,7 +13888,7 @@
   public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
     method public void draw(android.graphics.Canvas);
     method public android.graphics.drawable.Drawable getBackground();
-    method public static float getExtraInsetPercentage();
+    method public static float getExtraInsetFraction();
     method public android.graphics.drawable.Drawable getForeground();
     method public android.graphics.Path getIconMask();
     method public int getOpacity();
@@ -14347,6 +14369,7 @@
     method public void setPadding(android.graphics.Rect);
     method public void setShaderFactory(android.graphics.drawable.ShapeDrawable.ShaderFactory);
     method public void setShape(android.graphics.drawable.shapes.Shape);
+    method public void setXfermode(android.graphics.Xfermode);
   }
 
   public static abstract class ShapeDrawable.ShaderFactory {
@@ -14904,15 +14927,16 @@
     field public final int type;
   }
 
-  public final class SensorDirectChannel implements java.lang.AutoCloseable {
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
     method public void close();
-    method public boolean isValid();
+    method public int configure(android.hardware.Sensor, int);
+    method public boolean isOpen();
     field public static final int RATE_FAST = 2; // 0x2
     field public static final int RATE_NORMAL = 1; // 0x1
     field public static final int RATE_STOP = 0; // 0x0
     field public static final int RATE_VERY_FAST = 3; // 0x3
-    field public static final int TYPE_ASHMEM = 1; // 0x1
     field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+    field public static final int TYPE_MEMORY_FILE = 1; // 0x1
   }
 
   public class SensorEvent {
@@ -14946,7 +14970,6 @@
 
   public abstract class SensorManager {
     method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
-    method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
     method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
     method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
     method public boolean flush(android.hardware.SensorEventListener);
@@ -15799,7 +15822,6 @@
     method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
     field public static final java.lang.String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
     field public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 16; // 0x10
-    field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 8; // 0x8
     field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
     field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
@@ -20647,7 +20669,7 @@
     method public double getAccumulatedDeltaRangeMeters();
     method public int getAccumulatedDeltaRangeState();
     method public double getAccumulatedDeltaRangeUncertaintyMeters();
-    method public double getAutomaticGainControlLevelInDb();
+    method public double getAutomaticGainControlLevelDb();
     method public long getCarrierCycles();
     method public float getCarrierFrequencyHz();
     method public double getCarrierPhase();
@@ -20663,7 +20685,7 @@
     method public int getState();
     method public int getSvid();
     method public double getTimeOffsetNanos();
-    method public boolean hasAutomaticGainControlLevelInDb();
+    method public boolean hasAutomaticGainControlLevelDb();
     method public boolean hasCarrierCycles();
     method public boolean hasCarrierFrequencyHz();
     method public boolean hasCarrierPhase();
@@ -20794,7 +20816,7 @@
     method public int getSatelliteCount();
     method public int getSvid(int);
     method public boolean hasAlmanacData(int);
-    method public boolean hasCarrierFrequency(int);
+    method public boolean hasCarrierFrequencyHz(int);
     method public boolean hasEphemerisData(int);
     method public boolean usedInFix(int);
     field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
@@ -20873,13 +20895,10 @@
     method public boolean hasSpeedAccuracy();
     method public boolean hasVerticalAccuracy();
     method public boolean isFromMockProvider();
-    method public void removeAccuracy();
-    method public void removeAltitude();
-    method public void removeBearing();
-    method public void removeBearingAccuracy();
-    method public void removeSpeed();
-    method public void removeSpeedAccuracy();
-    method public void removeVerticalAccuracy();
+    method public deprecated void removeAccuracy();
+    method public deprecated void removeAltitude();
+    method public deprecated void removeBearing();
+    method public deprecated void removeSpeed();
     method public void reset();
     method public void set(android.location.Location);
     method public void setAccuracy(float);
@@ -21913,24 +21932,19 @@
     field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
   }
 
-  public final class MediaCas {
+  public final class MediaCas implements java.lang.AutoCloseable {
     ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
-    method public void closeSession(byte[]);
+    method public void close();
     method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
     method public static boolean isSystemIdSupported(int);
-    method public byte[] openSession(int) throws android.media.MediaCasException;
-    method public byte[] openSession(int, int) throws android.media.MediaCasException;
-    method public void processEcm(byte[], byte[], int, int) throws android.media.MediaCasException;
-    method public void processEcm(byte[], byte[]) throws android.media.MediaCasException;
+    method public android.media.MediaCas.Session openSession() throws android.media.MediaCasException;
     method public void processEmm(byte[], int, int) throws android.media.MediaCasException;
     method public void processEmm(byte[]) throws android.media.MediaCasException;
     method public void provision(java.lang.String) throws android.media.MediaCasException;
     method public void refreshEntitlements(int, byte[]) throws android.media.MediaCasException;
-    method public void release();
     method public void sendEvent(int, int, byte[]) throws android.media.MediaCasException;
     method public void setEventListener(android.media.MediaCas.EventListener, android.os.Handler);
     method public void setPrivateData(byte[]) throws android.media.MediaCasException;
-    method public void setSessionPrivateData(byte[], byte[]) throws android.media.MediaCasException;
   }
 
   public static abstract interface MediaCas.EventListener {
@@ -21942,6 +21956,13 @@
     method public int getSystemId();
   }
 
+  public final class MediaCas.Session implements java.lang.AutoCloseable {
+    method public void close();
+    method public void processEcm(byte[], int, int) throws android.media.MediaCasException;
+    method public void processEcm(byte[]) throws android.media.MediaCasException;
+    method public void setPrivateData(byte[]) throws android.media.MediaCasException;
+  }
+
   public class MediaCasException extends java.lang.Exception {
   }
 
@@ -21977,7 +21998,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22075,6 +22096,19 @@
     method public void set(int, int);
   }
 
+  public static final class MediaCodec.MetricsConstants {
+    field public static final java.lang.String CODEC = "android.media.mediacodec.codec";
+    field public static final java.lang.String ENCODER = "android.media.mediacodec.encoder";
+    field public static final java.lang.String HEIGHT = "android.media.mediacodec.height";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediacodec.mime";
+    field public static final java.lang.String MODE = "android.media.mediacodec.mode";
+    field public static final java.lang.String MODE_AUDIO = "audio";
+    field public static final java.lang.String MODE_VIDEO = "video";
+    field public static final java.lang.String ROTATION = "android.media.mediacodec.rotation";
+    field public static final java.lang.String SECURE = "android.media.mediacodec.secure";
+    field public static final java.lang.String WIDTH = "android.media.mediacodec.width";
+  }
+
   public static abstract interface MediaCodec.OnFrameRenderedListener {
     method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
   }
@@ -22385,12 +22419,12 @@
     method public abstract int readAt(long, byte[], int, int) throws java.io.IOException;
   }
 
-  public final class MediaDescrambler {
+  public final class MediaDescrambler implements java.lang.AutoCloseable {
     ctor public MediaDescrambler(int) throws android.media.MediaCasException.UnsupportedCasException;
-    method public final int descramble(java.nio.ByteBuffer, int, java.nio.ByteBuffer, int, android.media.MediaCodec.CryptoInfo);
-    method public final void release();
+    method public void close();
+    method public final int descramble(java.nio.ByteBuffer, java.nio.ByteBuffer, android.media.MediaCodec.CryptoInfo);
     method public final boolean requiresSecureDecoderComponent(java.lang.String);
-    method public final void setMediaCasSession(byte[]);
+    method public final void setMediaCasSession(android.media.MediaCas.Session);
   }
 
   public class MediaDescription implements android.os.Parcelable {
@@ -22454,7 +22488,7 @@
     method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
     method public void setPropertyByteArray(java.lang.String, byte[]);
     method public void setPropertyString(java.lang.String, java.lang.String);
-    field public static final int EVENT_KEY_EXPIRED = 3; // 0x3
+    field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
     field public static final int EVENT_KEY_REQUIRED = 2; // 0x2
     field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1
     field public static final int EVENT_SESSION_RECLAIMED = 5; // 0x5
@@ -22528,8 +22562,9 @@
     ctor public MediaExtractor();
     method public boolean advance();
     method public long getCachedDuration();
+    method public android.media.MediaExtractor.CasInfo getCasInfo(int);
     method public android.media.DrmInitData getDrmInitData();
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public java.util.Map<java.util.UUID, byte[]> getPsshInfo();
     method public boolean getSampleCryptoInfo(android.media.MediaCodec.CryptoInfo);
     method public int getSampleFlags();
@@ -22559,6 +22594,17 @@
     field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
   }
 
+  public static final class MediaExtractor.CasInfo {
+    method public android.media.MediaCas.Session getSession();
+    method public int getSystemId();
+  }
+
+  public static final class MediaExtractor.MetricsConstants {
+    field public static final java.lang.String FORMAT = "android.media.mediaextractor.fmt";
+    field public static final java.lang.String MIME_TYPE = "android.media.mediaextractor.mime";
+    field public static final java.lang.String TRACKS = "android.media.mediaextractor.ntrk";
+  }
+
   public final class MediaFormat {
     ctor public MediaFormat();
     method public final boolean containsKey(java.lang.String);
@@ -22784,69 +22830,6 @@
     field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
   }
 
-  public final class MediaMetricsSet {
-    method public double getDouble(java.lang.String, double);
-    method public int getInt(java.lang.String, int);
-    method public long getLong(java.lang.String, long);
-    method public java.lang.String getString(java.lang.String, java.lang.String);
-    method public boolean isEmpty();
-    method public java.util.Set<java.lang.String> keySet();
-    method public int size();
-  }
-
-  public static final class MediaMetricsSet.MediaCodec {
-    field public static final java.lang.String KEY_CODEC = "android.media.mediacodec.codec";
-    field public static final java.lang.String KEY_ENCODER = "android.media.mediacodec.encoder";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediacodec.height";
-    field public static final java.lang.String KEY_MIME = "android.media.mediacodec.mime";
-    field public static final java.lang.String KEY_MODE = "android.media.mediacodec.mode";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediacodec.rotation";
-    field public static final java.lang.String KEY_SECURE = "android.media.mediacodec.secure";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediacodec.width";
-    field public static final java.lang.String MODE_AUDIO = "audio";
-    field public static final java.lang.String MODE_VIDEO = "video";
-  }
-
-  public static final class MediaMetricsSet.MediaExtractor {
-    field public static final java.lang.String KEY_FORMAT = "android.media.mediaextractor.fmt";
-    field public static final java.lang.String KEY_MIME = "android.media.mediaextractor.mime";
-    field public static final java.lang.String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-  }
-
-  public static final class MediaMetricsSet.MediaPlayer {
-    field public static final java.lang.String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-    field public static final java.lang.String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-    field public static final java.lang.String KEY_DURATION = "android.media.mediaplayer.durationMs";
-    field public static final java.lang.String KEY_ERRORS = "android.media.mediaplayer.err";
-    field public static final java.lang.String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-    field public static final java.lang.String KEY_FRAMES = "android.media.mediaplayer.frames";
-    field public static final java.lang.String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediaplayer.height";
-    field public static final java.lang.String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-    field public static final java.lang.String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-    field public static final java.lang.String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediaplayer.width";
-  }
-
-  public static final class MediaMetricsSet.MediaRecorder {
-    field public static final java.lang.String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-    field public static final java.lang.String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-    field public static final java.lang.String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-    field public static final java.lang.String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-    field public static final java.lang.String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-    field public static final java.lang.String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-    field public static final java.lang.String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-    field public static final java.lang.String KEY_HEIGHT = "android.media.mediarecorder.height";
-    field public static final java.lang.String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-    field public static final java.lang.String KEY_ROTATION = "android.media.mediarecorder.rotation";
-    field public static final java.lang.String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-    field public static final java.lang.String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-    field public static final java.lang.String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-    field public static final java.lang.String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-    field public static final java.lang.String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-    field public static final java.lang.String KEY_WIDTH = "android.media.mediarecorder.width";
-  }
-
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
     ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
@@ -22884,8 +22867,8 @@
     method public android.media.MediaPlayer.DrmInfo getDrmInfo();
     method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
-    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+    method public android.os.PersistableBundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -22898,7 +22881,7 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
-    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningNetworkErrorException, android.media.MediaPlayer.ProvisioningServerErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
     method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
     method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -22925,7 +22908,7 @@
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
-    method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
+    method public void setOnDrmConfigHelper(android.media.MediaPlayer.OnDrmConfigHelper);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
     method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -22966,6 +22949,10 @@
     field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
     field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
     field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+    field public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3; // 0x3
+    field public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1; // 0x1
+    field public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2; // 0x2
+    field public static final int PREPARE_DRM_STATUS_SUCCESS = 0; // 0x0
     field public static final int SEEK_CLOSEST = 3; // 0x3
     field public static final int SEEK_CLOSEST_SYNC = 2; // 0x2
     field public static final int SEEK_NEXT_SYNC = 1; // 0x1
@@ -22975,11 +22962,25 @@
   }
 
   public static final class MediaPlayer.DrmInfo {
-    method public java.lang.String[] getMimes();
     method public java.util.Map<java.util.UUID, byte[]> getPssh();
     method public java.util.UUID[] getSupportedSchemes();
   }
 
+  public static final class MediaPlayer.MetricsConstants {
+    field public static final java.lang.String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+    field public static final java.lang.String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+    field public static final java.lang.String DURATION = "android.media.mediaplayer.durationMs";
+    field public static final java.lang.String ERRORS = "android.media.mediaplayer.err";
+    field public static final java.lang.String ERROR_CODE = "android.media.mediaplayer.errcode";
+    field public static final java.lang.String FRAMES = "android.media.mediaplayer.frames";
+    field public static final java.lang.String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+    field public static final java.lang.String HEIGHT = "android.media.mediaplayer.height";
+    field public static final java.lang.String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+    field public static final java.lang.String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+    field public static final java.lang.String PLAYING = "android.media.mediaplayer.playingMs";
+    field public static final java.lang.String WIDTH = "android.media.mediaplayer.width";
+  }
+
   public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
     ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
   }
@@ -22992,7 +22993,7 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
-  public static abstract interface MediaPlayer.OnDrmConfigListener {
+  public static abstract interface MediaPlayer.OnDrmConfigHelper {
     method public abstract void onDrmConfig(android.media.MediaPlayer);
   }
 
@@ -23001,7 +23002,7 @@
   }
 
   public static abstract interface MediaPlayer.OnDrmPreparedListener {
-    method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+    method public abstract void onDrmPrepared(android.media.MediaPlayer, int);
   }
 
   public static abstract interface MediaPlayer.OnErrorListener {
@@ -23032,8 +23033,12 @@
     method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
   }
 
-  public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
-    ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+  public static final class MediaPlayer.ProvisioningNetworkErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningNetworkErrorException(java.lang.String);
+  }
+
+  public static final class MediaPlayer.ProvisioningServerErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningServerErrorException(java.lang.String);
   }
 
   public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
@@ -23054,7 +23059,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
-    method public android.media.MediaMetricsSet getMetrics();
+    method public android.os.PersistableBundle getMetrics();
     method public android.view.Surface getSurface();
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
@@ -23073,11 +23078,12 @@
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
     method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
-    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.io.File) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
     method public void setOutputFile(java.io.FileDescriptor) throws java.lang.IllegalStateException;
+    method public void setOutputFile(java.io.File);
     method public void setOutputFile(java.lang.String) throws java.lang.IllegalStateException;
     method public void setOutputFormat(int) throws java.lang.IllegalStateException;
     method public void setPreviewDisplay(android.view.Surface);
@@ -23122,6 +23128,25 @@
     field public static final int VOICE_UPLINK = 2; // 0x2
   }
 
+  public static final class MediaRecorder.MetricsConstants {
+    field public static final java.lang.String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+    field public static final java.lang.String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+    field public static final java.lang.String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+    field public static final java.lang.String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+    field public static final java.lang.String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+    field public static final java.lang.String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+    field public static final java.lang.String FRAMERATE = "android.media.mediarecorder.frame-rate";
+    field public static final java.lang.String HEIGHT = "android.media.mediarecorder.height";
+    field public static final java.lang.String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+    field public static final java.lang.String ROTATION = "android.media.mediarecorder.rotation";
+    field public static final java.lang.String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+    field public static final java.lang.String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+    field public static final java.lang.String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+    field public static final java.lang.String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+    field public static final java.lang.String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+    field public static final java.lang.String WIDTH = "android.media.mediarecorder.width";
+  }
+
   public static abstract interface MediaRecorder.OnErrorListener {
     method public abstract void onError(android.media.MediaRecorder, int, int);
   }
@@ -24085,7 +24110,6 @@
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public boolean isConnected();
-    method public void search(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SearchCallback);
     method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback);
     method public void subscribe(java.lang.String, android.os.Bundle, android.media.browse.MediaBrowser.SubscriptionCallback);
     method public void unsubscribe(java.lang.String);
@@ -24121,12 +24145,6 @@
     field public static final int FLAG_PLAYABLE = 2; // 0x2
   }
 
-  public static abstract class MediaBrowser.SearchCallback {
-    ctor public MediaBrowser.SearchCallback();
-    method public void onError(java.lang.String, android.os.Bundle);
-    method public void onSearchResult(java.lang.String, android.os.Bundle, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
-  }
-
   public static abstract class MediaBrowser.SubscriptionCallback {
     ctor public MediaBrowser.SubscriptionCallback();
     method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
@@ -24335,8 +24353,6 @@
 
   public final class MediaController {
     ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
-    method public void addQueueItem(android.media.MediaDescription);
-    method public void addQueueItem(android.media.MediaDescription, int);
     method public void adjustVolume(int, int);
     method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
     method public android.os.Bundle getExtras();
@@ -24348,15 +24364,11 @@
     method public java.util.List<android.media.session.MediaSession.QueueItem> getQueue();
     method public java.lang.CharSequence getQueueTitle();
     method public int getRatingType();
-    method public int getRepeatMode();
     method public android.app.PendingIntent getSessionActivity();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public android.media.session.MediaController.TransportControls getTransportControls();
-    method public boolean isShuffleModeEnabled();
     method public void registerCallback(android.media.session.MediaController.Callback);
     method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
-    method public void removeQueueItem(android.media.MediaDescription);
-    method public void removeQueueItemAt(int);
     method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void setVolumeTo(int, int);
     method public void unregisterCallback(android.media.session.MediaController.Callback);
@@ -24370,10 +24382,8 @@
     method public void onPlaybackStateChanged(android.media.session.PlaybackState);
     method public void onQueueChanged(java.util.List<android.media.session.MediaSession.QueueItem>);
     method public void onQueueTitleChanged(java.lang.CharSequence);
-    method public void onRepeatModeChanged(int);
     method public void onSessionDestroyed();
     method public void onSessionEvent(java.lang.String, android.os.Bundle);
-    method public void onShuffleModeChanged(boolean);
   }
 
   public static final class MediaController.PlaybackInfo {
@@ -24402,8 +24412,6 @@
     method public void sendCustomAction(android.media.session.PlaybackState.CustomAction, android.os.Bundle);
     method public void sendCustomAction(java.lang.String, android.os.Bundle);
     method public void setRating(android.media.Rating);
-    method public void setRepeatMode(int);
-    method public void setShuffleModeEnabled(boolean);
     method public void skipToNext();
     method public void skipToPrevious();
     method public void skipToQueueItem(long);
@@ -24430,18 +24438,13 @@
     method public void setQueue(java.util.List<android.media.session.MediaSession.QueueItem>);
     method public void setQueueTitle(java.lang.CharSequence);
     method public void setRatingType(int);
-    method public void setRepeatMode(int);
     method public void setSessionActivity(android.app.PendingIntent);
-    method public void setShuffleModeEnabled(boolean);
     field public static final deprecated int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
-    field public static final int FLAG_HANDLES_QUEUE_COMMANDS = 4; // 0x4
     field public static final deprecated int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
   public static abstract class MediaSession.Callback {
     ctor public MediaSession.Callback();
-    method public void onAddQueueItem(android.media.MediaDescription);
-    method public void onAddQueueItem(android.media.MediaDescription, int);
     method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
     method public void onCustomAction(java.lang.String, android.os.Bundle);
     method public void onFastForward();
@@ -24455,13 +24458,9 @@
     method public void onPrepareFromMediaId(java.lang.String, android.os.Bundle);
     method public void onPrepareFromSearch(java.lang.String, android.os.Bundle);
     method public void onPrepareFromUri(android.net.Uri, android.os.Bundle);
-    method public void onRemoveQueueItem(android.media.MediaDescription);
-    method public void onRemoveQueueItemAt(int);
     method public void onRewind();
     method public void onSeekTo(long);
     method public void onSetRating(android.media.Rating);
-    method public void onSetRepeatMode(int);
-    method public void onSetShuffleModeEnabled(boolean);
     method public void onSkipToNext();
     method public void onSkipToPrevious();
     method public void onSkipToQueueItem(long);
@@ -24522,17 +24521,12 @@
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
     field public static final long ACTION_SET_RATING = 128L; // 0x80L
-    field public static final long ACTION_SET_REPEAT_MODE = 262144L; // 0x40000L
-    field public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 524288L; // 0x80000L
     field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L
     field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
-    field public static final int REPEAT_MODE_ALL = 2; // 0x2
-    field public static final int REPEAT_MODE_NONE = 0; // 0x0
-    field public static final int REPEAT_MODE_ONE = 1; // 0x1
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
     field public static final int STATE_ERROR = 7; // 0x7
@@ -24615,14 +24609,14 @@
     method public static boolean isChannelUriForPassthroughInput(android.net.Uri);
     method public static boolean isChannelUriForTunerInput(android.net.Uri);
     method public static boolean isProgramUri(android.net.Uri);
+    method public static void requestChannelBrowsable(android.content.Context, long);
     field public static final java.lang.String ACTION_INITIALIZE_PROGRAMS = "android.media.tv.action.INITIALIZE_PROGRAMS";
-    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT = "android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT";
     field public static final java.lang.String ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED";
+    field public static final java.lang.String ACTION_REQUEST_CHANNEL_BROWSABLE = "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED = "android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED";
     field public static final java.lang.String AUTHORITY = "android.media.tv";
     field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
-    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PREVIEW_PROGRAM_ID = "android.media.tv.extra.PREVIEW_PROGRAM_ID";
     field public static final java.lang.String EXTRA_WATCH_NEXT_PROGRAM_ID = "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
   }
@@ -24715,9 +24709,10 @@
 
   public static final class TvContract.PreviewPrograms implements android.media.tv.TvContract.BaseTvColumns {
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
-    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
-    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+    field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
     field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
     field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
     field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
     field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -24900,9 +24895,10 @@
   public static final class TvContract.WatchNextPrograms implements android.media.tv.TvContract.BaseTvColumns {
     ctor public TvContract.WatchNextPrograms();
     field public static final int ASPECT_RATIO_16_9 = 0; // 0x0
-    field public static final int ASPECT_RATIO_1_1 = 2; // 0x2
-    field public static final int ASPECT_RATIO_2_3 = 3; // 0x3
+    field public static final int ASPECT_RATIO_1_1 = 3; // 0x3
+    field public static final int ASPECT_RATIO_2_3 = 4; // 0x4
     field public static final int ASPECT_RATIO_3_2 = 1; // 0x1
+    field public static final int ASPECT_RATIO_4_3 = 2; // 0x2
     field public static final int AVAILABILITY_AVAILABLE = 0; // 0x0
     field public static final int AVAILABILITY_FREE_WITH_SUBSCRIPTION = 1; // 0x1
     field public static final int AVAILABILITY_PAID_CONTENT = 2; // 0x2
@@ -25631,14 +25627,10 @@
   }
 
   public final class IpSecManager {
-    method public void applyTransportModeTransform(java.net.Socket, android.net.IpSecTransform) throws java.io.IOException;
-    method public void applyTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform) throws java.io.IOException;
     method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
-    method public void removeTransportModeTransform(java.net.Socket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.net.DatagramSocket, android.net.IpSecTransform);
-    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform);
+    method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
     method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
     field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
@@ -25657,7 +25649,7 @@
   }
 
   public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
-    method public void close();
+    method public void close() throws java.io.IOException;
     method public int getPort();
     method public java.io.FileDescriptor getSocket();
   }
@@ -26855,8 +26847,8 @@
   }
 
   public class DiscoverySession {
-    method public java.lang.String createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
-    method public java.lang.String createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
+    method public android.net.NetworkSpecifier createNetworkSpecifierOpen(android.net.wifi.aware.PeerHandle);
+    method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(android.net.wifi.aware.PeerHandle, java.lang.String);
     method public void destroy();
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
@@ -26942,8 +26934,8 @@
   }
 
   public class WifiAwareSession {
-    method public java.lang.String createNetworkSpecifierOpen(int, byte[]);
-    method public java.lang.String createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
+    method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, byte[]);
+    method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, byte[], java.lang.String);
     method public void destroy();
     method public void publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
     method public void subscribe(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler);
@@ -30874,6 +30866,7 @@
     method public android.util.SizeF getSizeF(java.lang.String);
     method public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
     method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
+    method public java.util.UUID getUuid(java.lang.String);
     method public boolean hasFileDescriptors();
     method public void putAll(android.os.Bundle);
     method public void putBinder(java.lang.String, android.os.IBinder);
@@ -30898,6 +30891,7 @@
     method public void putSizeF(java.lang.String, android.util.SizeF);
     method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>);
     method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>);
+    method public void putUuid(java.lang.String, java.util.UUID);
     method public void readFromParcel(android.os.Parcel);
     method public void setClassLoader(java.lang.ClassLoader);
     method public void writeToParcel(android.os.Parcel, int);
@@ -31448,6 +31442,7 @@
     method public final <T> void readTypedArray(T[], android.os.Parcelable.Creator<T>);
     method public final <T> void readTypedList(java.util.List<T>, android.os.Parcelable.Creator<T>);
     method public final <T> T readTypedObject(android.os.Parcelable.Creator<T>);
+    method public final java.util.UUID readUuid();
     method public final java.lang.Object readValue(java.lang.ClassLoader);
     method public final void recycle();
     method public final void setDataCapacity(int);
@@ -31493,6 +31488,7 @@
     method public final <T extends android.os.Parcelable> void writeTypedArray(T[], int);
     method public final <T extends android.os.Parcelable> void writeTypedList(java.util.List<T>);
     method public final <T extends android.os.Parcelable> void writeTypedObject(T, int);
+    method public final void writeUuid(java.util.UUID);
     method public final void writeValue(java.lang.Object);
     field public static final android.os.Parcelable.Creator<java.lang.String> STRING_CREATOR;
   }
@@ -32054,7 +32050,7 @@
     field public static final int MEASUREMENT_BLUETOOTH_TX_MS = 10022; // 0x2726
     field public static final int MEASUREMENT_BLUETOOTH_TX_PACKETS = 10059; // 0x274b
     field public static final int MEASUREMENT_BUTTON_USER_ACTIVITY_COUNT = 10046; // 0x273e
-    field public static final int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
+    field public static final deprecated int MEASUREMENT_CPU_POWER_MAMS = 10064; // 0x2750
     field public static final int MEASUREMENT_MOBILE_IDLE_MS = 10024; // 0x2728
     field public static final int MEASUREMENT_MOBILE_POWER_MAMS = 10027; // 0x272b
     field public static final int MEASUREMENT_MOBILE_RX_BYTES = 10048; // 0x2740
@@ -32128,15 +32124,16 @@
   }
 
   public class StorageManager {
-    method public void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public void allocateBytes(java.util.UUID, long, int) throws java.io.IOException;
     method public void allocateBytes(java.io.FileDescriptor, long, int) throws java.io.IOException;
-    method public long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
-    method public long getCacheQuotaBytes(java.io.File);
-    method public long getCacheSizeBytes(java.io.File);
+    method public long getAllocatableBytes(java.util.UUID, int) throws java.io.IOException;
+    method public long getCacheQuotaBytes(java.util.UUID) throws java.io.IOException;
+    method public long getCacheSizeBytes(java.util.UUID) throws java.io.IOException;
     method public java.lang.String getMountedObbPath(java.lang.String);
     method public android.os.storage.StorageVolume getPrimaryStorageVolume();
     method public android.os.storage.StorageVolume getStorageVolume(java.io.File);
     method public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
+    method public java.util.UUID getUuidForPath(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorGroup(java.io.File) throws java.io.IOException;
     method public boolean isCacheBehaviorTombstone(java.io.File) throws java.io.IOException;
     method public boolean isEncrypted(java.io.File);
@@ -32148,7 +32145,10 @@
     method public void setCacheBehaviorTombstone(java.io.File, boolean) throws java.io.IOException;
     method public boolean unmountObb(java.lang.String, boolean, android.os.storage.OnObbStateChangeListener);
     field public static final java.lang.String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
+    field public static final java.lang.String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
+    field public static final java.lang.String EXTRA_UUID = "android.os.storage.extra.UUID";
     field public static final int FLAG_ALLOCATE_AGGRESSIVE = 1; // 0x1
+    field public static final java.util.UUID UUID_DEFAULT;
   }
 
   public final class StorageVolume implements android.os.Parcelable {
@@ -34632,6 +34632,10 @@
   }
 
   public class FontsContract {
+    method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
+    method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
+    method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
   }
 
   public static final class FontsContract.Columns implements android.provider.BaseColumns {
@@ -34648,6 +34652,35 @@
     field public static final java.lang.String WEIGHT = "font_weight";
   }
 
+  public static class FontsContract.FontFamilyResult {
+    method public android.provider.FontsContract.FontInfo[] getFonts();
+    method public int getStatusCode();
+    field public static final int STATUS_OK = 0; // 0x0
+    field public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; // 0x2
+    field public static final int STATUS_WRONG_CERTIFICATES = 1; // 0x1
+  }
+
+  public static class FontsContract.FontInfo {
+    method public android.graphics.fonts.FontVariationAxis[] getAxes();
+    method public int getResultCode();
+    method public int getTtcIndex();
+    method public android.net.Uri getUri();
+    method public int getWeight();
+    method public boolean isItalic();
+  }
+
+  public static class FontsContract.FontRequestCallback {
+    ctor public FontsContract.FontRequestCallback();
+    method public void onTypefaceRequestFailed(int);
+    method public void onTypefaceRetrieved(android.graphics.Typeface);
+    field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+    field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+    field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+    field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+    field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+    field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+  }
+
   public final deprecated class LiveFolders implements android.provider.BaseColumns {
     field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
     field public static final java.lang.String DESCRIPTION = "description";
@@ -35560,6 +35593,16 @@
     field public static final java.lang.String SUBSCRIPTION_ID = "pending_sub_id";
   }
 
+  public static final class Telephony.ServiceStateTable {
+    method public static android.net.Uri getUriForSubId(int);
+    method public static android.net.Uri getUriForSubIdAndField(int, java.lang.String);
+    field public static final java.lang.String AUTHORITY = "service-state";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection";
+    field public static final java.lang.String VOICE_OPERATOR_NUMERIC = "voice_operator_numeric";
+    field public static final java.lang.String VOICE_REG_STATE = "voice_reg_state";
+  }
+
   public static final class Telephony.Sms implements android.provider.BaseColumns android.provider.Telephony.TextBasedSmsColumns {
     method public static java.lang.String getDefaultSmsPackage(android.content.Context);
     field public static final android.net.Uri CONTENT_URI;
@@ -37147,11 +37190,14 @@
   public abstract class AutofillService extends android.app.Service {
     ctor public AutofillService();
     method public final deprecated void disableSelf();
+    method public final android.service.autofill.FillEventHistory getFillEventHistory();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
     method public void onDisconnected();
-    method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
+    method public void onFillRequest(android.service.autofill.FillRequest, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public abstract deprecated void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback);
+    method public void onSaveRequest(android.service.autofill.SaveRequest, android.service.autofill.SaveCallback);
+    method public abstract deprecated void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
@@ -37167,6 +37213,7 @@
     ctor public Dataset.Builder();
     method public android.service.autofill.Dataset build();
     method public android.service.autofill.Dataset.Builder setAuthentication(android.content.IntentSender);
+    method public android.service.autofill.Dataset.Builder setId(java.lang.String);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue);
     method public android.service.autofill.Dataset.Builder setValue(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, android.widget.RemoteViews);
   }
@@ -37176,6 +37223,42 @@
     method public void onSuccess(android.service.autofill.FillResponse);
   }
 
+  public final class FillContext implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getRequestId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillContext> CREATOR;
+  }
+
+  public final class FillEventHistory implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillEventHistory.Event> getEvents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillEventHistory> CREATOR;
+  }
+
+  public static final class FillEventHistory.Event {
+    method public java.lang.String getDatasetId();
+    method public int getType();
+    field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
+    field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
+    field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
+    field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
+  }
+
+  public final class FillRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public int getFlags();
+    method public int getId();
+    method public android.app.assist.AssistStructure getStructure();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.FillRequest> CREATOR;
+    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+  }
+
   public final class FillResponse implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -37187,7 +37270,9 @@
     method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
     method public android.service.autofill.FillResponse build();
     method public android.service.autofill.FillResponse.Builder setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews);
-    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setClientState(android.os.Bundle);
+    method public deprecated android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
+    method public android.service.autofill.FillResponse.Builder setIgnoredIds(android.view.autofill.AutofillId...);
     method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
   }
 
@@ -37200,6 +37285,7 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
+    field public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
     field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
     field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
     field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -37212,10 +37298,19 @@
     ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
     method public android.service.autofill.SaveInfo build();
     method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
+    method public android.service.autofill.SaveInfo.Builder setFlags(int);
     method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
     method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
   }
 
+  public final class SaveRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getClientState();
+    method public java.util.List<android.service.autofill.FillContext> getFillContexts();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
+  }
+
 }
 
 package android.service.carrier {
@@ -37335,7 +37430,7 @@
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public boolean dispatchTouchEvent(android.view.MotionEvent);
     method public boolean dispatchTrackballEvent(android.view.MotionEvent);
-    method public android.view.View findViewById(int);
+    method public <T extends android.view.View> T findViewById(int);
     method public final void finish();
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
@@ -37397,7 +37492,6 @@
     method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
     method public void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>, android.os.Bundle);
     method public void onLoadItem(java.lang.String, android.service.media.MediaBrowserService.Result<android.media.browse.MediaBrowser.MediaItem>);
-    method public void onSearch(java.lang.String, android.os.Bundle, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
     method public void setSessionToken(android.media.session.MediaSession.Token);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
   }
@@ -37503,16 +37597,16 @@
     method public final int getCurrentInterruptionFilter();
     method public final int getCurrentListenerHints();
     method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
-    method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String);
-    method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String);
+    method public final java.util.List<android.app.NotificationChannelGroup> getNotificationChannelGroups(java.lang.String, android.os.UserHandle);
+    method public final java.util.List<android.app.NotificationChannel> getNotificationChannels(java.lang.String, android.os.UserHandle);
     method public final android.service.notification.StatusBarNotification[] getSnoozedNotifications();
     method public android.os.IBinder onBind(android.content.Intent);
     method public void onInterruptionFilterChanged(int);
     method public void onListenerConnected();
     method public void onListenerDisconnected();
     method public void onListenerHintsChanged(int);
-    method public void onNotificationChannelGroupModified(java.lang.String, android.app.NotificationChannelGroup, int);
-    method public void onNotificationChannelModified(java.lang.String, android.app.NotificationChannel, int);
+    method public void onNotificationChannelGroupModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannelGroup, int);
+    method public void onNotificationChannelModified(java.lang.String, android.os.UserHandle, android.app.NotificationChannel, int);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification);
     method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
     method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
@@ -37526,7 +37620,7 @@
     method public final void setNotificationsShown(java.lang.String[]);
     method public final void snoozeNotification(java.lang.String, java.lang.String);
     method public final void snoozeNotification(java.lang.String, long);
-    method public final void updateNotificationChannel(java.lang.String, android.app.NotificationChannel);
+    method public final void updateNotificationChannel(java.lang.String, android.os.UserHandle, android.app.NotificationChannel);
     field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
     field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
     field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
@@ -37890,10 +37984,12 @@
     method public int getDesiredMinimumHeight();
     method public int getDesiredMinimumWidth();
     method public android.view.SurfaceHolder getSurfaceHolder();
+    method public void invalidateColors();
     method public boolean isPreview();
     method public boolean isVisible();
     method public void onApplyWindowInsets(android.view.WindowInsets);
     method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
+    method public android.app.WallpaperColors onComputeWallpaperColors();
     method public void onCreate(android.view.SurfaceHolder);
     method public void onDesiredSizeChanged(int, int);
     method public void onDestroy();
@@ -39585,6 +39681,8 @@
     field public static final java.lang.String ACTION_CONFIGURE_PHONE_ACCOUNT = "android.telecom.action.CONFIGURE_PHONE_ACCOUNT";
     field public static final java.lang.String ACTION_DEFAULT_DIALER_CHANGED = "android.telecom.action.DEFAULT_DIALER_CHANGED";
     field public static final deprecated java.lang.String ACTION_INCOMING_CALL = "android.telecom.action.INCOMING_CALL";
+    field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
+    field public static final java.lang.String ACTION_PHONE_ACCOUNT_UNREGISTERED = "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED";
     field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
     field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
     field public static final java.lang.String ACTION_SHOW_MISSED_CALLS_NOTIFICATION = "android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION";
@@ -41030,7 +41128,6 @@
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
     method public android.content.ComponentName startService(android.content.Intent);
-    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean stopService(android.content.Intent);
     method public void unbindService(android.content.ServiceConnection);
     method public void unregisterReceiver(android.content.BroadcastReceiver);
@@ -44230,7 +44327,6 @@
     method public boolean isValid();
     method public boolean isWideColorGamut();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
-    field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int FLAG_PRESENTATION = 8; // 0x8
     field public static final int FLAG_PRIVATE = 4; // 0x4
     field public static final int FLAG_ROUND = 16; // 0x10
@@ -44301,6 +44397,7 @@
     method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
     method public android.view.View findNextKeyboardNavigationCluster(android.view.View, android.view.View, int);
     method public static android.view.FocusFinder getInstance();
+    method public static void sort(android.view.View[], int, int, android.view.ViewGroup, boolean);
   }
 
   public final class FrameMetrics {
@@ -45713,7 +45810,6 @@
     method public android.view.animation.Animation getAnimation();
     method public android.os.IBinder getApplicationWindowToken();
     method public java.lang.String[] getAutofillHints();
-    method public int getAutofillMode();
     method public int getAutofillType();
     method public android.view.autofill.AutofillValue getAutofillValue();
     method public android.graphics.drawable.Drawable getBackground();
@@ -45802,7 +45898,6 @@
     method public float getPivotX();
     method public float getPivotY();
     method public android.view.PointerIcon getPointerIcon();
-    method public int getResolvedAutofillMode();
     method public android.content.res.Resources getResources();
     method public final boolean getRevealOnFocusHint();
     method public final int getRight();
@@ -46038,7 +46133,6 @@
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
     method public void setAutofillHints(java.lang.String...);
-    method public void setAutofillMode(int);
     method public void setAutofilled(boolean);
     method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
@@ -46195,9 +46289,6 @@
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
     field public static final java.lang.String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
     field public static final java.lang.String AUTOFILL_HINT_USERNAME = "username";
-    field public static final int AUTOFILL_MODE_AUTO = 1; // 0x1
-    field public static final int AUTOFILL_MODE_INHERIT = 0; // 0x0
-    field public static final int AUTOFILL_MODE_MANUAL = 2; // 0x2
     field public static final int AUTOFILL_TYPE_DATE = 4; // 0x4
     field public static final int AUTOFILL_TYPE_LIST = 3; // 0x3
     field public static final int AUTOFILL_TYPE_NONE = 0; // 0x0
@@ -46245,7 +46336,9 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0; // 0x0
     field public static final int IMPORTANT_FOR_AUTOFILL_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -46769,7 +46862,6 @@
     method public abstract int getLayoutDirection();
     method public abstract android.view.ViewParent getParent();
     method public abstract android.view.ViewParent getParentForAccessibility();
-    method public default int getResolvedAutofillMode();
     method public abstract int getTextAlignment();
     method public abstract int getTextDirection();
     method public abstract deprecated void invalidateChild(android.view.View, android.graphics.Rect);
@@ -47457,7 +47549,6 @@
 
   public final class AccessibilityManager {
     method public void addAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
-    method public boolean addAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
     method public boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
     method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
@@ -47467,16 +47558,11 @@
     method public boolean isEnabled();
     method public boolean isTouchExplorationEnabled();
     method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
-    method public boolean removeAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
     method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
     method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
   }
 
-  public static abstract interface AccessibilityManager.AccessibilityServicesStateChangeListener {
-    method public abstract void onAccessibilityServicesStateChanged();
-  }
-
   public static abstract interface AccessibilityManager.AccessibilityStateChangeListener {
     method public abstract void onAccessibilityStateChanged(boolean);
   }
@@ -48169,7 +48255,7 @@
     field public static final java.lang.String EXTRA_ASSIST_STRUCTURE = "android.view.autofill.extra.ASSIST_STRUCTURE";
     field public static final java.lang.String EXTRA_AUTHENTICATION_RESULT = "android.view.autofill.extra.AUTHENTICATION_RESULT";
     field public static final java.lang.String EXTRA_DATA_EXTRAS = "android.view.autofill.extra.DATA_EXTRAS";
-    field public static final int FLAG_MANUAL_REQUEST = 1; // 0x1
+    field public static final deprecated int FLAG_MANUAL_REQUEST = 1; // 0x1
   }
 
   public static abstract class AutofillManager.AutofillCallback {
@@ -50044,6 +50130,7 @@
     method public java.lang.String getFormat();
     method public android.widget.Chronometer.OnChronometerTickListener getOnChronometerTickListener();
     method public boolean isCountDown();
+    method public boolean isTheFinalCountDown();
     method public void setBase(long);
     method public void setCountDown(boolean);
     method public void setFormat(java.lang.String);
@@ -55727,6 +55814,7 @@
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.util.List<java.lang.Class<?>>);
     method public static java.lang.invoke.MethodHandle dropArguments(java.lang.invoke.MethodHandle, int, java.lang.Class<?>...);
     method public static java.lang.invoke.MethodHandle exactInvoker(java.lang.invoke.MethodType);
+    method public static java.lang.invoke.MethodHandle explicitCastArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType);
     method public static java.lang.invoke.MethodHandle filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...);
     method public static java.lang.invoke.MethodHandle filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
     method public static java.lang.invoke.MethodHandle foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index d20c08c..b6c2a98 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -5,10 +5,6 @@
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
   }
 
-  public static class Notification.Builder {
-    method public deprecated android.app.Notification.Builder chooseBadgeIcon(int);
-  }
-
   public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
     method public deprecated void showAsNotification(android.content.Context);
   }
@@ -26,6 +22,20 @@
 
 }
 
+package android.app.usage {
+
+  public class StorageStatsManager {
+    method public deprecated long getFreeBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated long getTotalBytes(java.lang.String) throws java.io.IOException;
+    method public deprecated boolean isQuotaSupported(java.lang.String);
+    method public deprecated android.app.usage.ExternalStorageStats queryExternalStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForPackage(java.lang.String, java.lang.String, android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUid(java.lang.String, int) throws java.io.IOException;
+    method public deprecated android.app.usage.StorageStats queryStatsForUser(java.lang.String, android.os.UserHandle) throws java.io.IOException;
+  }
+
+}
+
 package android.content {
 
   public abstract class Context {
@@ -41,6 +51,10 @@
 
 package android.content.pm {
 
+  public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+    field public deprecated java.lang.String volumeUuid;
+  }
+
   public class ComponentInfo extends android.content.pm.PackageItemInfo {
     field public deprecated boolean encryptionAware;
   }
@@ -49,6 +63,12 @@
     field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
   }
 
+  public final class SharedLibraryInfo implements android.os.Parcelable {
+    method public boolean isBuiltin();
+    method public boolean isDynamic();
+    method public boolean isStatic();
+  }
+
 }
 
 package android.database {
@@ -100,6 +120,28 @@
 
 }
 
+package android.hardware {
+
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
+    method public deprecated boolean isValid();
+  }
+
+  public abstract class SensorManager {
+    method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+  }
+
+}
+
+package android.location {
+
+  public class Location implements android.os.Parcelable {
+    method public deprecated void removeBearingAccuracy();
+    method public deprecated void removeSpeedAccuracy();
+    method public deprecated void removeVerticalAccuracy();
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
@@ -172,10 +214,14 @@
 package android.os.storage {
 
   public class StorageManager {
-    method public deprecated long getCacheQuotaBytes();
-    method public deprecated long getCacheSizeBytes();
-    method public deprecated long getExternalCacheQuotaBytes();
-    method public deprecated long getExternalCacheSizeBytes();
+    method public deprecated void allocateBytes(java.io.File, long, int) throws java.io.IOException;
+    method public deprecated long getAllocatableBytes(java.io.File, int) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes(java.io.File) throws java.io.IOException;
+    method public deprecated long getCacheSizeBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheQuotaBytes() throws java.io.IOException;
+    method public deprecated long getExternalCacheSizeBytes() throws java.io.IOException;
     method public android.os.storage.StorageVolume getPrimaryVolume();
     method public android.os.storage.StorageVolume[] getVolumeList();
     method public deprecated boolean isCacheBehaviorAtomic(java.io.File) throws java.io.IOException;
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 7394490..4f772c3 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -158,10 +158,6 @@
     asset->close();
     delete asset;
 
-    // ensure we can call getPixels(). No need to call unlock, since the
-    // bitmap will go out of scope when we return from this method.
-    bitmap.lockPixels();
-
     const int w = bitmap.width();
     const int h = bitmap.height();
     const void* p = bitmap.getPixels();
@@ -216,10 +212,6 @@
     // the packed resource can be released.
     delete map;
 
-    // ensure we can call getPixels(). No need to call unlock, since the
-    // bitmap will go out of scope when we return from this method.
-    bitmap.lockPixels();
-
     const int w = bitmap.width();
     const int h = bitmap.height();
     const void* p = bitmap.getPixels();
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index 67874a8..d69dd79 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -10,6 +10,7 @@
 #include <androidfw/StreamingZipInflater.h>
 #include <androidfw/ZipFileRO.h>
 #include <cutils/jstring.h>
+#include <cutils/properties.h>
 #include <private/android_filesystem_config.h> // for AID_SYSTEM
 #include <utils/SortedVector.h>
 #include <utils/String16.h>
@@ -82,12 +83,26 @@
         return String8(tmp);
     }
 
+    bool check_property(String16 property, String16 value) {
+        const char *prop;
+        const char *val;
+
+        prop = strndup16to8(property.string(), property.size());
+        char propBuf[PROPERTY_VALUE_MAX];
+        property_get(prop, propBuf, NULL);
+        val = strndup16to8(value.string(), value.size());
+
+        return (strcmp(propBuf, val) == 0);
+    }
+
     int parse_overlay_tag(const ResXMLTree& parser, const char *target_package_name,
             bool* is_static_overlay)
     {
         const size_t N = parser.getAttributeCount();
         String16 target;
         int priority = -1;
+        String16 propName = String16();
+        String16 propValue = String16();
         for (size_t i = 0; i < N; ++i) {
             size_t len;
             String16 key(parser.getAttributeName(i, &len));
@@ -109,36 +124,34 @@
                 if (parser.getAttributeValue(i, &v) == sizeof(Res_value)) {
                     *is_static_overlay = (v.data != 0);
                 }
+            } else if (key == String16("requiredSystemPropertyName")) {
+                const char16_t *p = parser.getAttributeStringValue(i, &len);
+                if (p != NULL) {
+                    propName = String16(p, len);
+                }
+            } else if (key == String16("requiredSystemPropertyValue")) {
+                const char16_t *p = parser.getAttributeStringValue(i, &len);
+                if (p != NULL) {
+                    propValue = String16(p, len);
+                }
             }
         }
+
+        // Note that conditional property enablement/exclusion only applies if
+        // the attribute is present. In its absence, all overlays are presumed enabled.
+        if (propName.size() > 0 && propValue.size() > 0) {
+            // if property set & equal to value, then include overlay - otherwise skip
+            if (!check_property(propName, propValue)) {
+                return NO_OVERLAY_TAG;
+            }
+        }
+
         if (target == String16(target_package_name)) {
             return priority;
         }
         return NO_OVERLAY_TAG;
     }
 
-    String16 parse_package_name(const ResXMLTree& parser)
-    {
-        const size_t N = parser.getAttributeCount();
-        String16 package_name;
-        for (size_t i = 0; i < N; ++i) {
-            size_t len;
-            String16 key(parser.getAttributeName(i, &len));
-            if (key == String16("package")) {
-                const char16_t *p = parser.getAttributeStringValue(i, &len);
-                if (p != NULL) {
-                    package_name = String16(p, len);
-                }
-            }
-        }
-        return package_name;
-    }
-
-    bool isValidStaticOverlayPackage(const String16& package_name) {
-        // TODO(b/35742444): Need to support selection method based on a package name.
-        return package_name.size() > 0;
-    }
-
     int parse_manifest(const void *data, size_t size, const char *target_package_name)
     {
         ResXMLTree parser;
@@ -149,7 +162,6 @@
         }
 
         ResXMLParser::event_code_t type;
-        String16 package_name;
         bool is_static_overlay = false;
         int priority = NO_OVERLAY_TAG;
         do {
@@ -157,16 +169,14 @@
             if (type == ResXMLParser::START_TAG) {
                 size_t len;
                 String16 tag(parser.getElementName(&len));
-                if (tag == String16("manifest")) {
-                    package_name = parse_package_name(parser);
-                } else if (tag == String16("overlay")) {
+                if (tag == String16("overlay")) {
                     priority = parse_overlay_tag(parser, target_package_name, &is_static_overlay);
                     break;
                 }
             }
         } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT);
 
-        if (is_static_overlay && isValidStaticOverlayPackage(package_name)) {
+        if (is_static_overlay) {
             return priority;
         }
         return NO_OVERLAY_TAG;
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
index 4be4654..9df229c 100644
--- a/cmds/media/src/com/android/commands/media/Media.java
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -228,16 +228,6 @@
             System.out.println("onVolumeInfoChanged " + info);
         }
 
-        @Override
-        public void onRepeatModeChanged(int repeatMode) throws RemoteException {
-            System.out.println("onRepeatModeChanged " + repeatMode);
-        }
-
-        @Override
-        public void onShuffleModeChanged(boolean enabled) throws RemoteException {
-            System.out.println("onShuffleModeChanged " + enabled);
-        }
-
         void printUsageMessage() {
             try {
                 System.out.println("V2Monitoring session " + mController.getTag()
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 8052288..b320d5d 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -335,6 +335,7 @@
      * are removed, or an account's credentials (saved password, etc) are changed.
      *
      * @see #addOnAccountsUpdatedListener
+     * @see #ACTION_ACCOUNT_REMOVED
      *
      * @deprecated use {@link #addOnAccountsUpdatedListener} to get account updates in runtime.
      */
@@ -344,6 +345,14 @@
         "android.accounts.LOGIN_ACCOUNTS_CHANGED";
 
     /**
+     * Action sent as a broadcast Intent by the AccountsService when any account is removed.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @BroadcastBehavior(includeBackground = true)
+    public static final String ACTION_ACCOUNT_REMOVED =
+        "android.accounts.action.ACCOUNT_REMOVED";
+
+    /**
      * Action sent as a broadcast Intent to specific package by the AccountsService
      * when account visibility or account's credentials (saved password, etc) are changed.
      *
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index 16a45ba..9f2c39b 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -77,7 +77,7 @@
         setContentView(R.layout.choose_account);
 
         // Setup the list
-        ListView list = (ListView) findViewById(android.R.id.list);
+        ListView list = findViewById(android.R.id.list);
         // Use an existing ListAdapter that will map an array of strings to TextViews
         list.setAdapter(new AccountArrayAdapter(this,
                 android.R.layout.simple_list_item_1, mAccountInfos));
diff --git a/core/java/android/accounts/ChooseAccountTypeActivity.java b/core/java/android/accounts/ChooseAccountTypeActivity.java
index a3222d8..e3352bc 100644
--- a/core/java/android/accounts/ChooseAccountTypeActivity.java
+++ b/core/java/android/accounts/ChooseAccountTypeActivity.java
@@ -99,7 +99,7 @@
 
         setContentView(R.layout.choose_account_type);
         // Setup the list
-        ListView list = (ListView) findViewById(android.R.id.list);
+        ListView list = findViewById(android.R.id.list);
         // Use an existing ListAdapter that will map an array of strings to TextViews
         list.setAdapter(new AccountArrayAdapter(this,
                 android.R.layout.simple_list_item_1, mAuthenticatorInfosToDisplay));
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 8442585..6680ce6 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -248,7 +248,7 @@
         populateUIAccountList(listItems);
 
         // Only enable "OK" button if something has been selected.
-        mOkButton = (Button) findViewById(android.R.id.button2);
+        mOkButton = findViewById(android.R.id.button2);
         mOkButton.setEnabled(mSelectedItemIndex != SELECTED_ITEM_NONE);
     }
 
@@ -592,7 +592,7 @@
      * If not specified then makes the description invisible.
      */
     private void overrideDescriptionIfSupplied(String descriptionOverride) {
-      TextView descriptionView = (TextView) findViewById(R.id.description);
+      TextView descriptionView = findViewById(R.id.description);
       if (!TextUtils.isEmpty(descriptionOverride)) {
           descriptionView.setText(descriptionOverride);
       } else {
@@ -605,7 +605,7 @@
      * based on {@code mSelectedItemIndex} member variable.
      */
     private final void populateUIAccountList(String[] listItems) {
-      ListView list = (ListView) findViewById(android.R.id.list);
+      ListView list = findViewById(android.R.id.list);
       list.setAdapter(new ArrayAdapter<String>(this,
               android.R.layout.simple_list_item_single_choice, listItems));
       list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index 38eab29..af74b03 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -84,7 +84,7 @@
             return;
         }
 
-        final TextView authTokenTypeView = (TextView) findViewById(R.id.authtoken_type);
+        final TextView authTokenTypeView = findViewById(R.id.authtoken_type);
         authTokenTypeView.setVisibility(View.GONE);
 
         final AccountManagerCallback<String> callback = new AccountManagerCallback<String>() {
@@ -116,7 +116,7 @@
         findViewById(R.id.allow_button).setOnClickListener(this);
         findViewById(R.id.deny_button).setOnClickListener(this);
 
-        LinearLayout packagesListView = (LinearLayout) findViewById(R.id.packages_list);
+        LinearLayout packagesListView = findViewById(R.id.packages_list);
 
         for (String pkg : packages) {
             String packageLabel;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 06291ab..c4b7ed7 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,20 +16,16 @@
 
 package android.app;
 
-import android.metrics.LogMaker;
 import android.graphics.Rect;
+import android.os.SystemClock;
 import android.view.ViewRootImpl.ActivityConfigCallback;
-import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillPopupWindow;
-import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutofillWindowPresenter;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.ToolbarActionBar;
 import com.android.internal.app.WindowDecorActionBar;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.policy.PhoneWindow;
 
 import android.annotation.CallSuper;
@@ -1233,6 +1229,13 @@
         mFragments.doLoaderStart();
 
         getApplication().dispatchActivityStarted(this);
+
+        if (mAutoFillResetNeeded) {
+            AutofillManager afm = getAutofillManager();
+            if (afm != null) {
+                afm.onVisibleForAutofill();
+            }
+        }
     }
 
     /**
@@ -2067,6 +2070,7 @@
             if (args == null) {
                 throw new IllegalArgumentException("Expected non-null picture-in-picture args");
             }
+            updatePictureInPictureArgsForContentInsets(args);
             return ActivityManagerNative.getDefault().enterPictureInPictureMode(mToken, args);
         } catch (RemoteException e) {
             return false;
@@ -2084,11 +2088,27 @@
             if (args == null) {
                 throw new IllegalArgumentException("Expected non-null picture-in-picture args");
             }
+            updatePictureInPictureArgsForContentInsets(args);
             ActivityManagerNative.getDefault().setPictureInPictureArgs(mToken, args);
         } catch (RemoteException e) {
         }
     }
 
+    /**
+     * Updates the provided {@param args} with the last known content insets for this activity, to
+     * be used with the source hint rect for the transition into PiP.
+     */
+    private void updatePictureInPictureArgsForContentInsets(PictureInPictureArgs args) {
+        if (args != null && args.hasSourceBoundsHint() && getWindow() != null &&
+                getWindow().peekDecorView() != null &&
+                getWindow().peekDecorView().getViewRootImpl() != null) {
+            args.setSourceRectHintInsets(
+                    getWindow().peekDecorView().getViewRootImpl().getLastContentInsets());
+        } else {
+            args.setSourceRectHintInsets(null);
+        }
+    }
+
     void dispatchMovedToDisplay(int displayId, Configuration config) {
         updateDisplay(displayId);
         onMovedToDisplay(displayId, config);
@@ -4521,12 +4541,20 @@
      */
     public void startActivityForResultAsUser(Intent intent, int requestCode,
             @Nullable Bundle options, UserHandle user) {
+        startActivityForResultAsUser(intent, mEmbeddedID, requestCode, options, user);
+    }
+
+    /**
+     * @hide Implement to provide correct calling token.
+     */
+    public void startActivityForResultAsUser(Intent intent, String resultWho, int requestCode,
+            @Nullable Bundle options, UserHandle user) {
         if (mParent != null) {
             throw new RuntimeException("Can't be called from a child");
         }
         options = transferSpringboardActivityOptions(options);
         Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
-                this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode,
+                this, mMainThread.getApplicationThread(), mToken, resultWho, intent, requestCode,
                 options, user);
         if (ar != null) {
             mMainThread.sendActivityResult(
@@ -4563,7 +4591,7 @@
         options = transferSpringboardActivityOptions(options);
         Instrumentation.ActivityResult ar =
                 mInstrumentation.execStartActivity(
-                        this, mMainThread.getApplicationThread(), mToken, this,
+                        this, mMainThread.getApplicationThread(), mToken, mEmbeddedID,
                         intent, -1, options, user);
         if (ar != null) {
             mMainThread.sendActivityResult(
@@ -5092,6 +5120,15 @@
     /**
      * @hide
      */
+    public void startActivityAsUserFromFragment(@NonNull Fragment fragment,
+            @RequiresPermission Intent intent, int requestCode, @Nullable Bundle options,
+            UserHandle user) {
+        startActivityForResultAsUser(intent, fragment.mWho, requestCode, options, user);
+    }
+
+    /**
+     * @hide
+     */
     @Override
     public void startActivityForResult(
             String who, Intent intent, int requestCode, @Nullable Bundle options) {
@@ -5924,7 +5961,7 @@
      */
     public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
         if (mTaskDescription != taskDescription) {
-            mTaskDescription.copyFrom(taskDescription);
+            mTaskDescription.copyFromPreserveHiddenFields(taskDescription);
             // Scale the icon down to something reasonable if it is provided
             if (taskDescription.getIconFilename() == null && taskDescription.getIcon() != null) {
                 final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
@@ -7389,6 +7426,54 @@
         return true;
     }
 
+    /** @hide */
+    @Override
+    public boolean getViewVisibility(int viewId) {
+        Window window = getWindow();
+        if (window == null) {
+            Log.i(TAG, "no window");
+            return false;
+        }
+
+        View decorView = window.peekDecorView();
+        if (decorView == null) {
+            Log.i(TAG, "no decorView");
+            return false;
+        }
+
+        View view = decorView.findViewByAccessibilityIdTraversal(viewId);
+        if (view == null) {
+            Log.i(TAG, "cannot find view");
+            return false;
+        }
+
+        // Check if the view is visible by checking all parents
+        while (view != null) {
+            if (view == decorView) {
+                break;
+            }
+
+            if (view.getVisibility() != View.VISIBLE) {
+                Log.i(TAG, view + " is not visible");
+                return false;
+            }
+
+            if (view.getParent() instanceof View) {
+                view = (View) view.getParent();
+            } else {
+                break;
+            }
+        }
+
+        return true;
+    }
+
+    /** @hide */
+    @Override
+    public boolean isVisibleForAutofill() {
+        return !mStopped;
+    }
+
     /**
      * If set to true, this indicates to the system that it should never take a
      * screenshot of the activity to be used as a representation while it is not in a started state.
@@ -7416,6 +7501,25 @@
         }
     }
 
+    /**
+     * Return the timestamp at which this activity start was last initiated by the system in the
+     * {@link SystemClock#uptimeMillis()} time base.
+     *
+     * This can be used to understand how much time is taken for an activity to be started and
+     * displayed to the user.
+     *
+     * @return timestamp at which this activity start was initiated by the system
+     *         or {@code 0} if for any reason the timestamp could not be retrieved.
+     */
+    public long getStartInitiatedTime() {
+        try {
+            return ActivityManager.getService().getActivityStartInitiatedTime(mToken);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to call getActivityStartTime", e);
+            return 0;
+        }
+    }
+
     class HostCallbacks extends FragmentHostCallback<Activity> {
         public HostCallbacks() {
             super(Activity.this /*activity*/);
@@ -7463,6 +7567,14 @@
         }
 
         @Override
+        public void onStartActivityAsUserFromFragment(
+                Fragment fragment, Intent intent, int requestCode, Bundle options,
+                UserHandle user) {
+            Activity.this.startActivityAsUserFromFragment(
+                    fragment, intent, requestCode, options, user);
+        }
+
+        @Override
         public void onStartIntentSenderFromFragment(Fragment fragment, IntentSender intent,
                 int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,
                 int extraFlags, Bundle options) throws IntentSender.SendIntentException {
@@ -7501,7 +7613,7 @@
 
         @Nullable
         @Override
-        public View onFindViewById(int id) {
+        public <T extends View> T onFindViewById(int id) {
             return Activity.this.findViewById(id);
         }
 
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 80482ca..35615ed 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -30,6 +30,8 @@
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.os.BatteryStats;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 
@@ -138,14 +140,17 @@
 
     static final class UidObserver extends IUidObserver.Stub {
         final OnUidImportanceListener mListener;
+        final Context mContext;
 
-        UidObserver(OnUidImportanceListener listener) {
+        UidObserver(OnUidImportanceListener listener, Context clientContext) {
             mListener = listener;
+            mContext = clientContext;
         }
 
         @Override
         public void onUidStateChanged(int uid, int procState, long procStateSeq) {
-            mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportance(procState));
+            mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportanceForClient(
+                    procState, mContext));
         }
 
         @Override
@@ -600,6 +605,9 @@
      */
     public static final int COMPAT_MODE_TOGGLE = 2;
 
+    private static final boolean DEVELOPMENT_FORCE_LOW_RAM =
+            SystemProperties.getBoolean("debug.force_low_ram", false);
+
     /** @hide */
     public static class StackId {
         /** Invalid stack ID. */
@@ -1055,7 +1063,20 @@
 
     /** @hide */
     public static boolean isLowRamDeviceStatic() {
-        return RoSystemProperties.CONFIG_LOW_RAM;
+        return RoSystemProperties.CONFIG_LOW_RAM ||
+                (Build.IS_DEBUGGABLE && DEVELOPMENT_FORCE_LOW_RAM);
+    }
+
+    /**
+     * Returns true if this is a small battery device. Exactly whether a device is considered to be
+     * small battery is ultimately up to the device configuration, but currently it generally means
+     * something in the class of a device with 1000 mAh or less. This is mostly intended to be used
+     * to determine whether certain features should be altered to account for a drastically smaller
+     * battery.
+     * @hide
+     */
+    public static boolean isSmallBatteryDevice() {
+        return RoSystemProperties.CONFIG_SMALL_BATTERY;
     }
 
     /**
@@ -1222,6 +1243,27 @@
             mNavigationBarColor = other.mNavigationBarColor;
         }
 
+        /**
+         * Copies this the values from another TaskDescription, but preserves the hidden fields
+         * if they weren't set on {@code other}
+         * @hide
+         */
+        public void copyFromPreserveHiddenFields(TaskDescription other) {
+            mLabel = other.mLabel;
+            mIcon = other.mIcon;
+            mIconFilename = other.mIconFilename;
+            mColorPrimary = other.mColorPrimary;
+            if (other.mColorBackground != 0) {
+                mColorBackground = other.mColorBackground;
+            }
+            if (other.mStatusBarColor != 0) {
+                mStatusBarColor = other.mStatusBarColor;
+            }
+            if (other.mNavigationBarColor != 0) {
+                mNavigationBarColor = other.mNavigationBarColor;
+            }
+        }
+
         private TaskDescription(Parcel source) {
             readFromParcel(source);
         }
@@ -2538,6 +2580,10 @@
      * <p><b>Note: this method is only intended for debugging or implementing
      * service management type user interfaces.</b></p>
      *
+     * @deprecated As of {@link android.os.Build.VERSION_CODES#O}, this method
+     * is no longer available to third party applications.  For backwards compatibility,
+     * it will still return the caller's own services.
+     *
      * @param maxNum The maximum number of entries to return in the list.  The
      * actual number returned may be smaller, depending on how many services
      * are running.
@@ -2545,6 +2591,7 @@
      * @return Returns a list of RunningServiceInfo records describing each of
      * the running tasks.
      */
+    @Deprecated
     public List<RunningServiceInfo> getRunningServices(int maxNum)
             throws SecurityException {
         try {
@@ -3081,10 +3128,32 @@
         public static final int IMPORTANCE_VISIBLE = 200;
 
         /**
-         * Constant for {@link #importance}: This process is not something the user
-         * is directly aware of, but is otherwise perceptable to them to some degree.
+         * Constant for {@link #importance}: {@link #IMPORTANCE_PERCEPTIBLE} had this wrong value
+         * before {@link Build.VERSION_CODES#O}.  Since the {@link Build.VERSION_CODES#O} SDK,
+         * the value of {@link #IMPORTANCE_PERCEPTIBLE} has been fixed.
+         *
+         * @deprecated Use {@link #IMPORTANCE_PERCEPTIBLE} instead.
          */
-        public static final int IMPORTANCE_PERCEPTIBLE = 130;
+        @Deprecated
+        public static final int IMPORTANCE_PERCEPTIBLE_DEPRECATED = 130;
+
+        /**
+         * Constant for {@link #importance}: This process is not something the user
+         * is directly aware of, but is otherwise perceptible to them to some degree.
+         */
+        public static final int IMPORTANCE_PERCEPTIBLE = 230;
+
+        /**
+         * Constant for {@link #importance}: {@link #IMPORTANCE_CANT_SAVE_STATE} had
+         * this wrong value
+         * before {@link Build.VERSION_CODES#O}.  Since the {@link Build.VERSION_CODES#O} SDK,
+         * the value of {@link #IMPORTANCE_CANT_SAVE_STATE} has been fixed.
+         *
+         * @deprecated Use {@link #IMPORTANCE_CANT_SAVE_STATE} instead.
+         * @hide
+         */
+        @Deprecated
+        public static final int IMPORTANCE_CANT_SAVE_STATE_DEPRECATED = 170;
 
         /**
          * Constant for {@link #importance}: This process is running an
@@ -3092,7 +3161,7 @@
          * while in the background.
          * @hide
          */
-        public static final int IMPORTANCE_CANT_SAVE_STATE = 170;
+        public static final int IMPORTANCE_CANT_SAVE_STATE= 270;
 
         /**
          * Constant for {@link #importance}: This process is contains services
@@ -3128,7 +3197,11 @@
          */
         public static final int IMPORTANCE_GONE = 1000;
 
-        /** @hide */
+        /**
+         * Convert a proc state to the correspondent IMPORTANCE_* constant.  If the return value
+         * will be passed to a client, use {@link #procStateToImportanceForClient}.
+         * @hide
+         */
         public static int procStateToImportance(int procState) {
             if (procState == PROCESS_STATE_NONEXISTENT) {
                 return IMPORTANCE_GONE;
@@ -3151,6 +3224,28 @@
             }
         }
 
+        /**
+         * Convert a proc state to the correspondent IMPORTANCE_* constant for a client represented
+         * by a given {@link Context}, with converting {@link #IMPORTANCE_PERCEPTIBLE}
+         * and {@link #IMPORTANCE_CANT_SAVE_STATE} to the corresponding "wrong" value if the
+         * client's target SDK < {@link VERSION_CODES#O}.
+         * @hide
+         */
+        public static int procStateToImportanceForClient(int procState, Context clientContext) {
+            final int importance = procStateToImportance(procState);
+
+            // For pre O apps, convert to the old, wrong values.
+            if (clientContext.getApplicationInfo().targetSdkVersion < VERSION_CODES.O) {
+                switch (importance) {
+                    case IMPORTANCE_PERCEPTIBLE:
+                        return IMPORTANCE_PERCEPTIBLE_DEPRECATED;
+                    case IMPORTANCE_CANT_SAVE_STATE:
+                        return IMPORTANCE_CANT_SAVE_STATE_DEPRECATED;
+                }
+            }
+            return importance;
+        }
+
         /** @hide */
         public static int importanceToProcState(int importance) {
             if (importance == IMPORTANCE_GONE) {
@@ -3380,7 +3475,7 @@
         try {
             int procState = getService().getPackageProcessState(packageName,
                     mContext.getOpPackageName());
-            return RunningAppProcessInfo.procStateToImportance(procState);
+            return RunningAppProcessInfo.procStateToImportanceForClient(procState, mContext);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -3400,7 +3495,7 @@
         try {
             int procState = getService().getUidProcessState(uid,
                     mContext.getOpPackageName());
-            return RunningAppProcessInfo.procStateToImportance(procState);
+            return RunningAppProcessInfo.procStateToImportanceForClient(procState, mContext);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -3450,7 +3545,7 @@
                 throw new IllegalArgumentException("Listener already registered: " + listener);
             }
             // TODO: implement the cut point in the system process to avoid IPCs.
-            UidObserver observer = new UidObserver(listener);
+            UidObserver observer = new UidObserver(listener, mContext);
             try {
                 getService().registerUidObserver(observer,
                         UID_OBSERVER_PROCSTATE | UID_OBSERVER_GONE,
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 9928512..7d81c4c 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -48,7 +48,7 @@
  * and add your view to it:
  *
  * <pre>
- * FrameLayout fl = (FrameLayout) findViewById(android.R.id.custom);
+ * FrameLayout fl = findViewById(android.R.id.custom);
  * fl.addView(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
  * </pre>
  *
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a6838f8b..027ddf5 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -79,6 +79,8 @@
 import android.os.storage.VolumeInfo;
 import android.provider.Settings;
 import android.util.ArrayMap;
+import android.util.IconDrawableFactory;
+import android.util.LauncherIcons;
 import android.util.Log;
 import android.view.Display;
 
@@ -1245,16 +1247,9 @@
         if (!isManagedProfile(user.getIdentifier())) {
             return icon;
         }
-        Drawable badgeShadow = getDrawable("system",
-                com.android.internal.R.drawable.ic_corp_icon_badge_shadow, null);
-        Drawable badgeColor = getDrawable("system",
-                com.android.internal.R.drawable.ic_corp_icon_badge_color, null);
-        badgeColor.setTint(getUserBadgeColor(user));
-        Drawable badgeForeground = getDrawable("system",
-                com.android.internal.R.drawable.ic_corp_icon_badge_case, null);
-
-        Drawable badge = new LayerDrawable(
-                new Drawable[] {badgeShadow, badgeColor, badgeForeground });
+        Drawable badge = new LauncherIcons(mContext).getBadgeDrawable(
+                com.android.internal.R.drawable.ic_corp_icon_badge_case,
+                getUserBadgeColor(user));
         return getBadgedDrawable(icon, badge, null, true);
     }
 
@@ -1268,14 +1263,6 @@
         return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
     }
 
-    // Should have enough colors to cope with UserManagerService.getMaxManagedProfiles()
-    @VisibleForTesting
-    public static final int[] CORP_BADGE_COLORS = new int[] {
-        com.android.internal.R.color.profile_badge_1,
-        com.android.internal.R.color.profile_badge_2,
-        com.android.internal.R.color.profile_badge_3
-    };
-
     @VisibleForTesting
     public static final int[] CORP_BADGE_LABEL_RES_ID = new int[] {
         com.android.internal.R.string.managed_profile_label_badge,
@@ -1284,12 +1271,7 @@
     };
 
     private int getUserBadgeColor(UserHandle user) {
-        int badge = getUserManager().getManagedProfileBadge(user.getIdentifier());
-        if (badge < 0) {
-            badge = 0;
-        }
-        int resourceId = CORP_BADGE_COLORS[badge % CORP_BADGE_COLORS.length];
-        return Resources.getSystem().getColor(resourceId, null);
+        return IconDrawableFactory.getUserBadgeColor(getUserManager(), user.getIdentifier());
     }
 
     @Override
@@ -2639,4 +2621,13 @@
             throw e.rethrowAsRuntimeException();
         }
     }
+
+    @Override
+    public ComponentName getInstantAppInstallerComponent() {
+        try {
+            return mPM.getInstantAppInstallerComponent();
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 79041e2..f0e5444 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1446,21 +1446,13 @@
     @Override
     public ComponentName startService(Intent service) {
         warnIfCallingFromSystemProcess();
-        return startServiceCommon(service, -1, null, false, mUser);
+        return startServiceCommon(service, false, mUser);
     }
 
     @Override
     public ComponentName startForegroundService(Intent service) {
         warnIfCallingFromSystemProcess();
-        return startServiceCommon(service, -1, null, true, mUser);
-    }
-
-    // STOPSHIP: remove when NotificationManager.startServiceInForeground() is retired
-    @Override
-    public ComponentName startServiceInForeground(Intent service,
-            int id, Notification notification) {
-        warnIfCallingFromSystemProcess();
-        return startServiceCommon(service, id, notification, false, mUser);
+        return startServiceCommon(service, true, mUser);
     }
 
     @Override
@@ -1471,29 +1463,22 @@
 
     @Override
     public ComponentName startServiceAsUser(Intent service, UserHandle user) {
-        return startServiceCommon(service, -1, null, false, user);
+        return startServiceCommon(service, false, user);
     }
 
     @Override
     public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
-        return startServiceCommon(service, -1, null, true, user);
+        return startServiceCommon(service, true, user);
     }
 
-    // STOPSHIP: remove when NotificationManager.startServiceInForeground() is retired
-    @Override
-    public ComponentName startServiceInForegroundAsUser(Intent service,
-            int id, Notification notification, UserHandle user) {
-        return startServiceCommon(service, id, notification, false, user);
-    }
-
-    private ComponentName startServiceCommon(Intent service, int id, Notification notification,
-            boolean requireForeground, UserHandle user) {
+    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
+            UserHandle user) {
         try {
             validateServiceIntent(service);
             service.prepareToLeaveProcess(this);
             ComponentName cn = ActivityManager.getService().startService(
                 mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
-                            getContentResolver()), id, notification, requireForeground,
+                            getContentResolver()), requireForeground,
                             getOpPackageName(), user.getIdentifier());
             if (cn != null) {
                 if (cn.getPackageName().equals("!")) {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index a3c123f..c5b93cd 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -34,6 +34,7 @@
 import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.transition.Transition;
 import android.transition.TransitionInflater;
 import android.transition.TransitionSet;
@@ -508,6 +509,10 @@
     // True if mHidden has been changed and the animation should be scheduled.
     boolean mHiddenChanged;
 
+    // The cached value from onGetLayoutInflater(Bundle) that will be returned from
+    // getLayoutInflater()
+    LayoutInflater mLayoutInflater;
+
     /**
      * State information that has been retrieved from a fragment instance
      * through {@link FragmentManager#saveFragmentInstanceState(Fragment)
@@ -1188,6 +1193,19 @@
     }
 
     /**
+     * @hide
+     * Call {@link Activity#startActivityForResultAsUser(Intent, int, UserHandle)} from the
+     * fragment's containing Activity.
+     */
+    public void startActivityForResultAsUser(
+            Intent intent, int requestCode, Bundle options, UserHandle user) {
+        if (mHost == null) {
+            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+        }
+        mHost.onStartActivityAsUserFromFragment(this, intent, requestCode, options, user);
+    }
+
+    /**
      * Call {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int,
      * Bundle)} from the fragment's containing Activity.
      */
@@ -1375,6 +1393,38 @@
     }
 
     /**
+     * Returns the cached LayoutInflater used to inflate Views of this Fragment. If
+     * {@link #onGetLayoutInflater(Bundle)} has not been called {@link #onGetLayoutInflater(Bundle)}
+     * will be called with a {@code null} argument and that value will be cached.
+     * <p>
+     * The cached LayoutInflater will be replaced immediately prior to
+     * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} and cleared immediately after
+     * {@link #onDetach()}.
+     *
+     * @return The LayoutInflater used to inflate Views of this Fragment.
+     */
+    public final LayoutInflater getLayoutInflater() {
+        if (mLayoutInflater == null) {
+            return performGetLayoutInflater(null);
+        }
+        return mLayoutInflater;
+    }
+
+    /**
+     * Calls {@link #onGetLayoutInflater(Bundle)} and caches the result for use by
+     * {@link #getLayoutInflater()}.
+     *
+     * @param savedInstanceState If the fragment is being re-created from
+     * a previous saved state, this is the state.
+     * @return The LayoutInflater used to inflate Views of this Fragment.
+     */
+    LayoutInflater performGetLayoutInflater(Bundle savedInstanceState) {
+        LayoutInflater layoutInflater = onGetLayoutInflater(savedInstanceState);
+        mLayoutInflater = layoutInflater;
+        return mLayoutInflater;
+    }
+
+    /**
      * @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead.
      */
     @Deprecated
@@ -2513,7 +2563,7 @@
         mChildFragmentManager.attachController(mHost, new FragmentContainer() {
             @Override
             @Nullable
-            public View onFindViewById(int id) {
+            public <T extends View> T onFindViewById(int id) {
                 if (mView == null) {
                     throw new IllegalStateException("Fragment does not have a view");
                 }
@@ -2821,6 +2871,7 @@
     void performDetach() {
         mCalled = false;
         onDetach();
+        mLayoutInflater = null;
         if (!mCalled) {
             throw new SuperNotCalledException("Fragment " + this
                     + " did not call through to super.onDetach()");
diff --git a/core/java/android/app/FragmentContainer.java b/core/java/android/app/FragmentContainer.java
index 6ed54dc..77c9c31 100644
--- a/core/java/android/app/FragmentContainer.java
+++ b/core/java/android/app/FragmentContainer.java
@@ -31,7 +31,7 @@
      * view is not a child of this container.
      */
     @Nullable
-    public abstract View onFindViewById(@IdRes int id);
+    public abstract <T extends View> T onFindViewById(@IdRes int id);
 
     /**
      * Return {@code true} if the container holds any view.
diff --git a/core/java/android/app/FragmentHostCallback.java b/core/java/android/app/FragmentHostCallback.java
index 41a885e..5ef23e6 100644
--- a/core/java/android/app/FragmentHostCallback.java
+++ b/core/java/android/app/FragmentHostCallback.java
@@ -23,6 +23,7 @@
 import android.content.IntentSender;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -146,6 +147,20 @@
     }
 
     /**
+     * @hide
+     * Starts a new {@link Activity} from the given fragment.
+     * See {@link Activity#startActivityForResult(Intent, int)}.
+     */
+    public void onStartActivityAsUserFromFragment(Fragment fragment, Intent intent, int requestCode,
+            Bundle options, UserHandle userHandle) {
+        if (requestCode != -1) {
+            throw new IllegalStateException(
+                    "Starting activity with a requestCode requires a FragmentActivity host");
+        }
+        mContext.startActivityAsUser(intent, userHandle);
+    }
+
+    /**
      * Starts a new {@link IntentSender} from the given fragment.
      * See {@link Activity#startIntentSender(IntentSender, Intent, int, int, int, Bundle)}.
      */
@@ -192,7 +207,7 @@
 
     @Nullable
     @Override
-    public View onFindViewById(int id) {
+    public <T extends View> T onFindViewById(int id) {
         return null;
     }
 
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 75d6295..c1161a2 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1243,7 +1243,7 @@
                                                     + f
                                                     + " for a container view with no id"));
                                 }
-                                container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
+                                container = mContainer.onFindViewById(f.mContainerId);
                                 if (container == null && !f.mRestored) {
                                     String resName;
                                     try {
@@ -1259,7 +1259,7 @@
                                 }
                             }
                             f.mContainer = container;
-                            f.mView = f.performCreateView(f.onGetLayoutInflater(
+                            f.mView = f.performCreateView(f.performGetLayoutInflater(
                                     f.mSavedFragmentState), container, f.mSavedFragmentState);
                             if (f.mView != null) {
                                 f.mView.setSaveFromParentEnabled(false);
@@ -1431,7 +1431,7 @@
 
     void ensureInflatedFragmentView(Fragment f) {
         if (f.mFromLayout && !f.mPerformedCreateView) {
-            f.mView = f.performCreateView(f.onGetLayoutInflater(
+            f.mView = f.performCreateView(f.performGetLayoutInflater(
                     f.mSavedFragmentState), null, f.mSavedFragmentState);
             if (f.mView != null) {
                 f.mView.setSaveFromParentEnabled(false);
@@ -1462,18 +1462,22 @@
                     if (fragment.isHideReplaced()) {
                         fragment.setHideReplaced(false);
                     } else {
+                        final ViewGroup container = fragment.mContainer;
+                        final View animatingView = fragment.mView;
+                        container.startViewTransition(animatingView);
                         // Delay the actual hide operation until the animation finishes, otherwise
                         // the fragment will just immediately disappear
                         anim.addListener(new AnimatorListenerAdapter() {
                             @Override
                             public void onAnimationEnd(Animator animation) {
+                                container.endViewTransition(animatingView);
                                 animation.removeListener(this);
-                                if (fragment.mView != null) {
-                                    fragment.mView.setVisibility(View.GONE);
-                                }
+                                animatingView.setVisibility(View.GONE);
                             }
                         });
                     }
+                } else {
+                    fragment.mView.setVisibility(View.VISIBLE);
                 }
                 setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
                 anim.start();
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index 780a922..9a920d7 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -193,7 +193,7 @@
             View nonExistentView, ArrayMap<String, String> nameOverrides) {
         ViewGroup sceneRoot = null;
         if (fragmentManager.mContainer.onHasView()) {
-            sceneRoot = (ViewGroup) fragmentManager.mContainer.onFindViewById(containerId);
+            sceneRoot = fragmentManager.mContainer.onFindViewById(containerId);
         }
         if (sceneRoot == null) {
             return;
@@ -265,7 +265,7 @@
             View nonExistentView, ArrayMap<String, String> nameOverrides) {
         ViewGroup sceneRoot = null;
         if (fragmentManager.mContainer.onHasView()) {
-            sceneRoot = (ViewGroup) fragmentManager.mContainer.onFindViewById(containerId);
+            sceneRoot = fragmentManager.mContainer.onFindViewById(containerId);
         }
         if (sceneRoot == null) {
             return;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 595ad35..d270244 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -129,8 +129,7 @@
     void finishSubActivity(in IBinder token, in String resultWho, int requestCode);
     PendingIntent getRunningServiceControlPanel(in ComponentName service);
     ComponentName startService(in IApplicationThread caller, in Intent service,
-            in String resolvedType, int id, in Notification notification,
-            boolean requireForeground, in String callingPackage, int userId);
+            in String resolvedType, boolean requireForeground, in String callingPackage, int userId);
     int stopService(in IApplicationThread caller, in Intent service,
             in String resolvedType, int userId);
     int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
@@ -190,6 +189,8 @@
             int flags, in Bundle options, int userId);
     void cancelIntentSender(in IIntentSender sender);
     String getPackageForIntentSender(in IIntentSender sender);
+    void registerIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
+    void unregisterIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
     void enterSafeMode();
     boolean startNextMatchingActivity(in IBinder callingActivity,
             in Intent intent, in Bundle options);
@@ -630,6 +631,8 @@
      */
      void backgroundWhitelistUid(int uid);
 
+     long getActivityStartInitiatedTime(IBinder token);
+
     // WARNING: when these transactions are updated, check if they are any callers on the native
     // side. If so, make sure they are using the correct transaction ids and arguments.
     // If a transaction which will also be used on the native side is being inserted, add it
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index f4e8f3f..cd9c095 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -27,6 +27,7 @@
 import android.content.pm.ParceledListSlice;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.service.notification.Adjustment;
 import android.service.notification.Condition;
 import android.service.notification.IConditionListener;
@@ -101,9 +102,9 @@
     void setOnNotificationPostedTrimFromListener(in INotificationListener token, int trim);
     void setInterruptionFilter(String pkg, int interruptionFilter);
 
-    void updateNotificationChannelFromPrivilegedListener(in INotificationListener token, String pkg, in NotificationChannel channel);
-    ParceledListSlice getNotificationChannelsFromPrivilegedListener(in INotificationListener token, String pkg);
-    ParceledListSlice getNotificationChannelGroupsFromPrivilegedListener(in INotificationListener token, String pkg);
+    void updateNotificationChannelFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user, in NotificationChannel channel);
+    ParceledListSlice getNotificationChannelsFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user);
+    ParceledListSlice getNotificationChannelGroupsFromPrivilegedListener(in INotificationListener token, String pkg, in UserHandle user);
 
     void applyEnqueuedAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
     void applyAdjustmentFromAssistant(in INotificationListener token, in Adjustment adjustment);
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 620fca5..bb169c2 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1779,7 +1779,7 @@
      * {@hide}
      */
     public ActivityResult execStartActivity(
-            Context who, IBinder contextThread, IBinder token, Activity target,
+            Context who, IBinder contextThread, IBinder token, String resultWho,
             Intent intent, int requestCode, Bundle options, UserHandle user) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (mActivityMonitors != null) {
@@ -1810,7 +1810,7 @@
             int result = ActivityManager.getService()
                 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
                         intent.resolveTypeIfNeeded(who.getContentResolver()),
-                        token, target != null ? target.mEmbeddedID : null,
+                        token, resultWho,
                         requestCode, 0, null, options, user.getIdentifier());
             checkStartActivityResult(result, intent);
         } catch (RemoteException e) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7f26f4f..cab2114 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2339,7 +2339,9 @@
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
-        sb.append("Notification(pri=");
+        sb.append("Notification(channel=");
+        sb.append(getChannel());
+        sb.append(" pri=");
         sb.append(priority);
         sb.append(" contentView=");
         if (contentView != null) {
@@ -2729,21 +2731,6 @@
         }
 
         /**
-         * @removed
-         * Sets which icon to display as a badge for this notification.
-         *
-         * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
-         * {@link #BADGE_ICON_LARGE}.
-         *
-         * Note: This value might be ignored, for launchers that don't support badge icons.
-         */
-        @Deprecated
-        public Builder chooseBadgeIcon(int icon) {
-            mN.mBadgeIcon = icon;
-            return this;
-        }
-
-        /**
          * Sets which icon to display as a badge for this notification.
          *
          * Must be one of {@link #BADGE_ICON_NONE}, {@link #BADGE_ICON_SMALL},
@@ -3259,9 +3246,10 @@
          * This should only be used for high priority ongoing tasks like navigation, an ongoing
          * call, or other similarly high-priority events for the user.
          * <p>
-         * For most styles, the coloring will only be applied if the notification is ongoing.
+         * For most styles, the coloring will only be applied if the notification is for a
+         * foreground service notification.
          * However, for {@link MediaStyle} and {@link DecoratedMediaCustomViewStyle} notifications
-         * that have a media session attached there is no requirement for it to be ongoing.
+         * that have a media session attached there is no such requirement.
          *
          * @see Builder#setOngoing(boolean)
          * @see Builder#setColor(int)
@@ -4214,9 +4202,22 @@
          * @hide
          */
         public RemoteViews makePublicContentView() {
+            return makePublicView(false /* ambient */);
+        }
+
+        /**
+         * Construct a RemoteViews for the display in public contexts like on the lockscreen.
+         *
+         * @hide
+         */
+        public RemoteViews makePublicAmbientNotification() {
+            return makePublicView(true /* ambient */);
+        }
+
+        private RemoteViews makePublicView(boolean ambient) {
             if (mN.publicVersion != null) {
                 final Builder builder = recoverBuilder(mContext, mN.publicVersion);
-                return builder.createContentView();
+                return ambient ? builder.makeAmbientNotification() : builder.createContentView();
             }
             Bundle savedBundle = mN.extras;
             Style style = mStyle;
@@ -4233,14 +4234,15 @@
             publicExtras.putBoolean(EXTRA_CHRONOMETER_COUNT_DOWN,
                     savedBundle.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN));
             publicExtras.putCharSequence(EXTRA_TITLE,
-                    mContext.getString(R.string.notification_hidden_text));
+                    mContext.getString(com.android.internal.R.string.notification_hidden_text));
             mN.extras = publicExtras;
-            final RemoteViews publicView = applyStandardTemplate(getBaseLayoutResource());
+            final RemoteViews view = ambient ? makeAmbientNotification()
+                    : applyStandardTemplate(getBaseLayoutResource());
             mN.extras = savedBundle;
             mN.mLargeIcon = largeIcon;
             mN.largeIcon = largeIconLegacy;
             mStyle = style;
-            return publicView;
+            return view;
         }
 
         /**
@@ -4759,12 +4761,10 @@
     }
 
     /**
-     * @return whether this notification is ongoing and can't be dismissed by the user.
+     * @return whether this notification is a foreground service notification
      */
-    private boolean isOngoing() {
-        final int ongoingFlags = Notification.FLAG_FOREGROUND_SERVICE
-                | Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
-        return (flags & ongoingFlags) != 0;
+    private boolean isForegroundService() {
+        return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
     }
 
     /**
@@ -4789,8 +4789,7 @@
     }
 
     /**
-     * @return true if this notification is colorized. This also factors in whether the
-     * notification is ongoing.
+     * @return true if this notification is colorized.
      *
      * @hide
      */
@@ -4806,7 +4805,7 @@
                 return true;
             }
         }
-        return extras.getBoolean(EXTRA_COLORIZED) && isOngoing();
+        return extras.getBoolean(EXTRA_COLORIZED) && isForegroundService();
     }
 
     private boolean hasLargeIcon() {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 92216d1..e50bc13 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -26,6 +26,7 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.text.TextUtils;
 
@@ -139,7 +140,7 @@
     private int mImportance = DEFAULT_IMPORTANCE;
     private boolean mBypassDnd;
     private int mLockscreenVisibility = DEFAULT_VISIBILITY;
-    private Uri mSound;
+    private Uri mSound = Settings.System.DEFAULT_NOTIFICATION_URI;
     private boolean mLights;
     private int mLightColor = DEFAULT_LIGHT_COLOR;
     private long[] mVibration;
@@ -330,7 +331,8 @@
 
     /**
      * Sets the sound that should be played for notifications posted to this channel and its
-     * audio attributes.
+     * audio attributes. Notification channels with an {@link #getImportance() importance} of at
+     * least {@link NotificationManager#IMPORTANCE_DEFAULT} should have a sound.
      *
      * Only modifiable before the channel is submitted to
      * {@link NotificationManager#notify(String, int, Notification)}.
@@ -445,7 +447,7 @@
     }
 
     /**
-     * Returns the user specified importance {e.g. @link NotificationManager#IMPORTANCE_LOW} for
+     * Returns the user specified importance e.g. {@link NotificationManager#IMPORTANCE_LOW} for
      * notifications posted to this channel.
      */
     public int getImportance() {
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 72c5978..242d4a5 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1155,40 +1155,4 @@
         }
     }
 
-    /**
-     * Start a service directly into the "foreground service" state.  Unlike
-     * {@link android.content.Context#startService(Intent)}, this method
-     * can be used from within background operations like broadcast receivers
-     * or scheduled jobs.
-     *
-     * @param service Description of the service to be started.  The Intent must be either
-     *      fully explicit (supplying a component name) or specify a specific package
-     *      name it is targeted to.
-     * @param id The identifier for this notification as per
-     *      {@link #notify(int, Notification) NotificationManager.notify(int, Notification)};
-     *      must not be 0.
-     * @param notification The Notification to be displayed.
-     * @return If the service is being started or is already running, the
-     *      {@link ComponentName} of the actual service that was started is
-     *      returned; else if the service does not exist null is returned.
-     *
-     * @deprecated STOPSHIP transition away from this for O
-     */
-    @Nullable
-    @Deprecated
-    public ComponentName startServiceInForeground(Intent service,
-            int id, Notification notification) {
-        return mContext.startServiceInForeground(service, id, notification);
-    }
-
-    /**
-     * @hide like {@link #startServiceInForeground(Intent, int, Notification)}
-     * but for a specific user.
-     */
-    @Nullable
-    public ComponentName startServiceInForegroundAsUser(Intent service,
-            int id, Notification notification, UserHandle user) {
-        return mContext.startServiceInForegroundAsUser(service, id, notification, user);
-    }
-
 }
diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java
index 0ce5eeb..2fa6360 100644
--- a/core/java/android/app/PictureInPictureArgs.java
+++ b/core/java/android/app/PictureInPictureArgs.java
@@ -49,6 +49,13 @@
     @Nullable
     private Rect mSourceRectHint;
 
+    /**
+     * The content insets that are used with the source hint rect for the transition into PiP where
+     * the insets are removed at the beginning of the transition.
+     */
+    @Nullable
+    private Rect mSourceRectHintInsets;
+
     PictureInPictureArgs(Parcel in) {
         if (in.readInt() != 0) {
             mAspectRatio = in.readFloat();
@@ -60,6 +67,9 @@
         if (in.readInt() != 0) {
             mSourceRectHint = Rect.CREATOR.createFromParcel(in);
         }
+        if (in.readInt() != 0) {
+            mSourceRectHintInsets = Rect.CREATOR.createFromParcel(in);
+        }
     }
 
     /**
@@ -94,6 +104,9 @@
         if (otherArgs.hasSourceBoundsHint()) {
             mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
         }
+        if (otherArgs.hasSourceBoundsHintInsets()) {
+            mSourceRectHintInsets = new Rect(otherArgs.getSourceRectHintInsets());
+        }
     }
 
     /**
@@ -167,7 +180,19 @@
     }
 
     /**
-     * @return the launch bounds
+     * Sets the insets to be used with the source rect hint bounds.
+     * @hide
+     */
+    public void setSourceRectHintInsets(Rect insets) {
+        if (insets == null) {
+            mSourceRectHintInsets = null;
+        } else {
+            mSourceRectHintInsets = new Rect(insets);
+        }
+    }
+
+    /**
+     * @return the source rect hint
      * @hide
      */
     public Rect getSourceRectHint() {
@@ -175,6 +200,14 @@
     }
 
     /**
+     * @return the source rect hint insets.
+     * @hide
+     */
+    public Rect getSourceRectHintInsets() {
+        return mSourceRectHintInsets;
+    }
+
+    /**
      * @return whether there are launch bounds set
      * @hide
      */
@@ -182,12 +215,23 @@
         return mSourceRectHint != null && !mSourceRectHint.isEmpty();
     }
 
+    /**
+     * @return whether there are source rect hint insets set
+     * @hide
+     */
+    public boolean hasSourceBoundsHintInsets() {
+        return mSourceRectHintInsets != null;
+    }
+
     @Override
     public PictureInPictureArgs clone() {
         PictureInPictureArgs args = new PictureInPictureArgs(mAspectRatio, mUserActions);
         if (mSourceRectHint != null) {
             args.setSourceRectHint(mSourceRectHint);
         }
+        if (mSourceRectHintInsets != null) {
+            args.setSourceRectHintInsets(mSourceRectHintInsets);
+        }
         return args;
     }
 
@@ -216,6 +260,12 @@
         } else {
             out.writeInt(0);
         }
+        if (mSourceRectHintInsets != null) {
+            out.writeInt(1);
+            mSourceRectHintInsets.writeToParcel(out, 0);
+        } else {
+            out.writeInt(0);
+        }
     }
 
     public static final Creator<PictureInPictureArgs> CREATOR =
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 3191eec..6f326de 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -112,13 +112,6 @@
     private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>>
             mAdjustedDisplays = new ArrayMap<>();
 
-    /**
-     * A cache of DisplayId, Resources to Display. These display adjustments associated with these
-     * {@link Display}s will change as the resources change.
-     */
-    private final ArrayMap<Pair<Integer, ResourcesKey>, WeakReference<Display>> mResourceDisplays =
-        new ArrayMap<>();
-
     public static ResourcesManager getInstance() {
         synchronized (ResourcesManager.class) {
             if (sResourcesManager == null) {
@@ -251,51 +244,16 @@
      */
     public Display getAdjustedDisplay(final int displayId, Resources resources) {
         synchronized (this) {
-            // Note that the ResourcesKey might be {@code null} in the case that the
-            // {@link Resources} is actually from {@link Resources#getSystem}. In this case, it is
-            // not managed by {@link ResourcesManager}, but we still want to cache the display
-            // object.
-            final Pair<Integer, ResourcesKey> key = Pair.create(displayId,
-                    findKeyForResourceImplLocked(resources.getImpl()));
-
-            WeakReference<Display> wd = mResourceDisplays.get(key);
-            if (wd != null) {
-                final Display display = wd.get();
-                if (display != null) {
-                    return display;
-                }
-            }
             final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
             if (dm == null) {
                 // may be null early in system startup
                 return null;
             }
-            final Display display = dm.getCompatibleDisplay(displayId, resources);
-            if (display != null) {
-                mResourceDisplays.put(key, new WeakReference<>(display));
-            }
-            return display;
+            return dm.getCompatibleDisplay(displayId, resources);
         }
     }
 
     private void cleanupResourceImpl(ResourcesKey removedKey) {
-        // Remove any resource to display mapping based on this key.
-        final Iterator<Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>>> iter =
-                mResourceDisplays.entrySet().iterator();
-        while (iter.hasNext()) {
-            final Map.Entry<Pair<Integer, ResourcesKey>, WeakReference<Display>> entry =
-                    iter.next();
-            final ResourcesKey key = entry.getKey().second;
-
-            // Do not touch system resource displays (indicated by a {@code null} key) or
-            // non-matching keys.
-            if (key == null || !key.equals(removedKey)) {
-                continue;
-            }
-
-            iter.remove();
-        }
-
         // Remove resource key to resource impl mapping and flush cache
         final ResourcesImpl res = mResourceImpls.remove(removedKey).get();
 
@@ -887,7 +845,6 @@
             int changes = mResConfiguration.updateFrom(config);
             // Things might have changed in display manager, so clear the cached displays.
             mAdjustedDisplays.clear();
-            mResourceDisplays.clear();
 
             DisplayMetrics defaultDisplayMetrics = getDisplayMetrics();
 
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 9c18df8..4abca9a 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -165,7 +165,7 @@
         setContentView(com.android.internal.R.layout.search_bar);
 
         // get the view elements for local access
-        mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view);
+        mSearchView = findViewById(com.android.internal.R.id.search_view);
         mSearchView.setIconified(false);
         mSearchView.setOnCloseListener(mOnCloseListener);
         mSearchView.setOnQueryTextListener(mOnQueryChangeListener);
@@ -184,7 +184,7 @@
         mBadgeLabel = (TextView) mSearchView.findViewById(com.android.internal.R.id.search_badge);
         mSearchAutoComplete = (AutoCompleteTextView)
                 mSearchView.findViewById(com.android.internal.R.id.search_src_text);
-        mAppIcon = (ImageView) findViewById(com.android.internal.R.id.search_app_icon);
+        mAppIcon = findViewById(com.android.internal.R.id.search_app_icon);
         mSearchPlate = mSearchView.findViewById(com.android.internal.R.id.search_plate);
         mWorkingSpinner = getContext().getDrawable(com.android.internal.R.drawable.search_spinner);
         // TODO: Restore the spinner for slow suggestion lookups
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 49a4a76..527314c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -121,6 +121,8 @@
 import android.telephony.euicc.EuiccManager;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.IAutoFillManager;
+import android.service.oemlock.IOemLockService;
+import android.service.oemlock.OemLockManager;
 import android.service.persistentdata.IPersistentDataBlockService;
 import android.service.persistentdata.PersistentDataBlockManager;
 import android.service.vr.IVrManager;
@@ -760,6 +762,20 @@
                 }
             }});
 
+        registerService(Context.OEM_LOCK_SERVICE, OemLockManager.class,
+                new StaticServiceFetcher<OemLockManager>() {
+            @Override
+            public OemLockManager createService() throws ServiceNotFoundException {
+                IBinder b = ServiceManager.getServiceOrThrow(Context.OEM_LOCK_SERVICE);
+                IOemLockService oemLockService = IOemLockService.Stub.asInterface(b);
+                if (oemLockService != null) {
+                    return new OemLockManager(oemLockService);
+                } else {
+                    // not supported
+                    return null;
+                }
+            }});
+
         registerService(Context.MEDIA_PROJECTION_SERVICE, MediaProjectionManager.class,
                 new CachedServiceFetcher<MediaProjectionManager>() {
             @Override
diff --git a/core/java/android/app/TabActivity.java b/core/java/android/app/TabActivity.java
index 637c8c1..ad8b0db 100644
--- a/core/java/android/app/TabActivity.java
+++ b/core/java/android/app/TabActivity.java
@@ -108,7 +108,7 @@
     @Override
     public void onContentChanged() {
         super.onContentChanged();
-        mTabHost = (TabHost) findViewById(com.android.internal.R.id.tabhost);
+        mTabHost = findViewById(com.android.internal.R.id.tabhost);
 
         if (mTabHost == null) {
             throw new RuntimeException(
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
new file mode 100644
index 0000000..5ed66ca
--- /dev/null
+++ b/core/java/android/app/WallpaperColors.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app;
+
+import android.graphics.Color;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import android.util.Pair;
+
+import java.util.List;
+
+/**
+ * A class containing information about the colors of a wallpaper.
+ */
+public final class WallpaperColors implements Parcelable {
+
+    public WallpaperColors(Parcel parcel) {
+    }
+
+    /**
+     * Wallpaper color details containing a list of colors and their weights,
+     * as if it were an histogram.
+     * This list can be extracted from a bitmap by the Palette API.
+     *
+     * Dark text support will be calculated internally based on the histogram.
+     *
+     * @param colors list of pairs where each pair contains a color
+     *               and number of occurrences/influence.
+     */
+    public WallpaperColors(List<Pair<Color, Integer>> colors) {
+    }
+
+    /**
+     * Wallpaper color details containing a list of colors and their weights,
+     * as if it were an histogram.
+     * Explicit dark text support.
+     *
+     * @param colors list of pairs where each pair contains a color
+     *               and number of occurrences/influence.
+     * @param supportsDarkText can have dark text on top or not
+     */
+    public WallpaperColors(List<Pair<Color, Integer>> colors, boolean supportsDarkText) {
+    }
+
+    public static final Creator<WallpaperColors> CREATOR = new Creator<WallpaperColors>() {
+        @Override
+        public WallpaperColors createFromParcel(Parcel in) {
+            return new WallpaperColors(in);
+        }
+
+        @Override
+        public WallpaperColors[] newArray(int size) {
+            return new WallpaperColors[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+    }
+
+    /**
+     * List of colors with their occurrences. The bigger the int, the more relevant the color.
+     * @return list of colors paired with their weights.
+     */
+    public List<Pair<Color, Integer>> getColors() {
+        return null;
+    }
+
+    /**
+     * Whether or not dark text is legible on top of this wallpaper.
+     *
+     * @return true if dark text is supported
+     */
+    public boolean supportsDarkText() {
+        return false;
+    }
+}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index aa0eaae..0676bca 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -17,6 +17,8 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RawRes;
 import android.annotation.SystemApi;
 import android.content.ComponentName;
@@ -741,6 +743,43 @@
         return getWallpaperFile(which, mContext.getUserId());
     }
 
+
+    /**
+     * Registers a listener to get notified when the wallpaper colors change.
+     * Callback might be called from an arbitrary background thread.
+     *
+     * @param listener A listener to register
+     */
+    public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
+    }
+
+    /**
+     * Registers a listener to get notified when the wallpaper colors change
+     * @param listener A listener to register
+     * @param handler Where to call it from. Might be called from a background thread
+     *                if null.
+     */
+    public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
+            @Nullable Handler handler) {
+    }
+
+    /**
+     * Stop listening to color updates.
+     * @param callback A callback to unsubscribe
+     */
+    public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener callback) {
+    }
+
+    /**
+     * Get the primary colors of a wallpaper
+     * @param which wallpaper type. Must be either {@link #FLAG_SYSTEM} or
+     *     {@link #FLAG_LOCK}
+     * @return a list of colors ordered by priority
+     */
+    public @Nullable WallpaperColors getWallpaperColors(int which) {
+        return null;
+    }
+
     /**
      * Version of {@link #getWallpaperFile(int)} that can access the wallpaper data
      * for a given user.  The caller must hold the INTERACT_ACROSS_USERS_FULL
@@ -1732,4 +1771,19 @@
             mLatch.countDown();
         }
     }
+
+    /**
+     * Interface definition for a callback to be invoked when colors change on a wallpaper.
+     */
+    public interface OnColorsChangedListener {
+        /**
+         * Called when colors change.
+         * A {@link android.app.WallpaperColors} object containing a simplified
+         * color histogram will be given.
+         *
+         * @param colors Wallpaper color info
+         * @param which A combination of {@link #FLAG_LOCK} and {@link #FLAG_SYSTEM}
+         */
+        void onColorsChanged(WallpaperColors colors, int which);
+    }
 }
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 545aef5..9f911f5 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -964,6 +964,16 @@
          *
          * @return The hints for this view
          */
+        @Nullable public String[] getAutofillHints() {
+            return mAutofillHints;
+        }
+
+        /**
+         * @hide
+         * @deprecated use getAutofillHints() instead.
+         */
+        // TODO(b/33197203): remove once clients don't use it anymore...
+        @Deprecated
         @Nullable public String[] getAutoFillHints() {
             return mAutofillHints;
         }
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 412e445..23baa17 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -51,6 +51,8 @@
     public static final int NETWORK_TYPE_UNMETERED = 2;
     /** This job requires network connectivity that is not roaming. */
     public static final int NETWORK_TYPE_NOT_ROAMING = 3;
+    /** This job requires metered connectivity such as most cellular data networks. */
+    public static final int NETWORK_TYPE_METERED = 4;
 
     /**
      * Amount of backoff a job has initially by default, in milliseconds.
@@ -347,10 +349,13 @@
     }
 
     /**
-     * One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
+     * The kind of connectivity requirements that the job has.
+     *
+     * @return One of {@link android.app.job.JobInfo#NETWORK_TYPE_ANY},
      * {@link android.app.job.JobInfo#NETWORK_TYPE_NONE},
-     * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED}, or
-     * {@link android.app.job.JobInfo#NETWORK_TYPE_NOT_ROAMING}.
+     * {@link android.app.job.JobInfo#NETWORK_TYPE_UNMETERED},
+     * {@link android.app.job.JobInfo#NETWORK_TYPE_METERED}, or
+     * {@link android.app.job.JobInfo#NETWORK_TYPE_NOT_ROAMING},
      */
     public int getNetworkType() {
         return networkType;
diff --git a/core/java/android/app/job/JobParameters.java b/core/java/android/app/job/JobParameters.java
index 016a0fa..673d1b8 100644
--- a/core/java/android/app/job/JobParameters.java
+++ b/core/java/android/app/job/JobParameters.java
@@ -164,6 +164,20 @@
      * you should not call {@link JobService#jobFinished(JobParameters, boolean)} yourself
      * (otherwise you risk losing an upcoming JobWorkItem that is being enqueued at the same time).
      *
+     * <p>Once you are done with the {@link JobWorkItem} returned by this method, you must call
+     * {@link #completeWork(JobWorkItem)} with it to inform the system that you are done
+     * executing the work.  The job will not be finished until all dequeued work has been
+     * completed.  You do not, however, have to complete each returned work item before deqeueing
+     * the next one -- you can use {@link #dequeueWork()} multiple times before completing
+     * previous work if you want to process work in parallel, and you can complete the work
+     * in whatever order you want.</p>
+     *
+     * <p>If the job runs to the end of its available time period before all work has been
+     * completed, it will stop as normal.  You should return true from
+     * {@link JobService#onStopJob(JobParameters)} in order to have the job rescheduled, and by
+     * doing so any pending as well as remaining uncompleted work will be re-queued
+     * for the next time the job runs.</p>
+     *
      * @return Returns a new {@link JobWorkItem} if there is one pending, otherwise null.
      * If null is returned, the system will also stop the job if all work has also been completed.
      * (This means that for correct operation, you must always call dequeueWork() after you have
diff --git a/core/java/android/app/job/JobService.java b/core/java/android/app/job/JobService.java
index f4019ce..9096b47 100644
--- a/core/java/android/app/job/JobService.java
+++ b/core/java/android/app/job/JobService.java
@@ -60,161 +60,24 @@
     public static final String PERMISSION_BIND =
             "android.permission.BIND_JOB_SERVICE";
 
-    /**
-     * Identifier for a message that will result in a call to
-     * {@link #onStartJob(android.app.job.JobParameters)}.
-     */
-    private static final int MSG_EXECUTE_JOB = 0;
-    /**
-     * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
-     */
-    private static final int MSG_STOP_JOB = 1;
-    /**
-     * Message that the client has completed execution of this job.
-     */
-    private static final int MSG_JOB_FINISHED = 2;
-
-    /** Lock object for {@link #mHandler}. */
-    private final Object mHandlerLock = new Object();
-
-    /**
-     * Handler we post jobs to. Responsible for calling into the client logic, and handling the
-     * callback to the system.
-     */
-    @GuardedBy("mHandlerLock")
-    JobHandler mHandler;
-
-    static final class JobInterface extends IJobService.Stub {
-        final WeakReference<JobService> mService;
-
-        JobInterface(JobService service) {
-            mService = new WeakReference<>(service);
-        }
-
-        @Override
-        public void startJob(JobParameters jobParams) throws RemoteException {
-            JobService service = mService.get();
-            if (service != null) {
-                service.ensureHandler();
-                Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams);
-                m.sendToTarget();
-            }
-        }
-
-        @Override
-        public void stopJob(JobParameters jobParams) throws RemoteException {
-            JobService service = mService.get();
-            if (service != null) {
-                service.ensureHandler();
-                Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams);
-                m.sendToTarget();
-            }
-
-        }
-    }
-
-    IJobService mBinder;
-
-    /** @hide */
-    void ensureHandler() {
-        synchronized (mHandlerLock) {
-            if (mHandler == null) {
-                mHandler = new JobHandler(getMainLooper());
-            }
-        }
-    }
-
-    /**
-     * Runs on application's main thread - callbacks are meant to offboard work to some other
-     * (app-specified) mechanism.
-     * @hide
-     */
-    class JobHandler extends Handler {
-        JobHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            final JobParameters params = (JobParameters) msg.obj;
-            switch (msg.what) {
-                case MSG_EXECUTE_JOB:
-                    try {
-                        boolean workOngoing = JobService.this.onStartJob(params);
-                        ackStartMessage(params, workOngoing);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Error while executing job: " + params.getJobId());
-                        throw new RuntimeException(e);
-                    }
-                    break;
-                case MSG_STOP_JOB:
-                    try {
-                        boolean ret = JobService.this.onStopJob(params);
-                        ackStopMessage(params, ret);
-                    } catch (Exception e) {
-                        Log.e(TAG, "Application unable to handle onStopJob.", e);
-                        throw new RuntimeException(e);
-                    }
-                    break;
-                case MSG_JOB_FINISHED:
-                    final boolean needsReschedule = (msg.arg2 == 1);
-                    IJobCallback callback = params.getCallback();
-                    if (callback != null) {
-                        try {
-                            callback.jobFinished(params.getJobId(), needsReschedule);
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Error reporting job finish to system: binder has gone" +
-                                    "away.");
-                        }
-                    } else {
-                        Log.e(TAG, "finishJob() called for a nonexistent job id.");
-                    }
-                    break;
-                default:
-                    Log.e(TAG, "Unrecognised message received.");
-                    break;
-            }
-        }
-
-        private void ackStartMessage(JobParameters params, boolean workOngoing) {
-            final IJobCallback callback = params.getCallback();
-            final int jobId = params.getJobId();
-            if (callback != null) {
-                try {
-                     callback.acknowledgeStartMessage(jobId, workOngoing);
-                } catch(RemoteException e) {
-                    Log.e(TAG, "System unreachable for starting job.");
-                }
-            } else {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
-                }
-            }
-        }
-
-        private void ackStopMessage(JobParameters params, boolean reschedule) {
-            final IJobCallback callback = params.getCallback();
-            final int jobId = params.getJobId();
-            if (callback != null) {
-                try {
-                    callback.acknowledgeStopMessage(jobId, reschedule);
-                } catch(RemoteException e) {
-                    Log.e(TAG, "System unreachable for stopping job.");
-                }
-            } else {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
-                }
-            }
-        }
-    }
+    private JobServiceEngine mEngine;
 
     /** @hide */
     public final IBinder onBind(Intent intent) {
-        if (mBinder == null) {
-            mBinder = new JobInterface(this);
+        if (mEngine == null) {
+            mEngine = new JobServiceEngine(this) {
+                @Override
+                public boolean onStartJob(JobParameters params) {
+                    return JobService.this.onStartJob(params);
+                }
+
+                @Override
+                public boolean onStopJob(JobParameters params) {
+                    return JobService.this.onStopJob(params);
+                }
+            };
         }
-        return mBinder.asBinder();
+        return mEngine.getBinder();
     }
 
     /**
@@ -269,9 +132,6 @@
      *                        criteria specified at schedule-time. False otherwise.
      */
     public final void jobFinished(JobParameters params, boolean needsReschedule) {
-        ensureHandler();
-        Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
-        m.arg2 = needsReschedule ? 1 : 0;
-        m.sendToTarget();
+        mEngine.jobFinished(params, needsReschedule);
     }
 }
\ No newline at end of file
diff --git a/core/java/android/app/job/JobServiceEngine.java b/core/java/android/app/job/JobServiceEngine.java
new file mode 100644
index 0000000..a628619
--- /dev/null
+++ b/core/java/android/app/job/JobServiceEngine.java
@@ -0,0 +1,223 @@
+/*
+ * 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.app.job;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Helper for implementing a {@link android.app.Service} that interacts with
+ * {@link JobScheduler}.
+ */
+public abstract class JobServiceEngine {
+    private static final String TAG = "JobServiceEngine";
+
+    /**
+     * Identifier for a message that will result in a call to
+     * {@link #onStartJob(android.app.job.JobParameters)}.
+     */
+    private static final int MSG_EXECUTE_JOB = 0;
+    /**
+     * Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
+     */
+    private static final int MSG_STOP_JOB = 1;
+    /**
+     * Message that the client has completed execution of this job.
+     */
+    private static final int MSG_JOB_FINISHED = 2;
+
+    /**
+     * Context we are running in.
+     */
+    private final Service mService;
+
+    private final IJobService mBinder;
+
+    /** Lock object for {@link #mHandler}. */
+    private final Object mHandlerLock = new Object();
+
+    /**
+     * Handler we post jobs to. Responsible for calling into the client logic, and handling the
+     * callback to the system.
+     */
+    @GuardedBy("mHandlerLock")
+    JobHandler mHandler;
+
+    static final class JobInterface extends IJobService.Stub {
+        final WeakReference<JobServiceEngine> mService;
+
+        JobInterface(JobServiceEngine service) {
+            mService = new WeakReference<>(service);
+        }
+
+        @Override
+        public void startJob(JobParameters jobParams) throws RemoteException {
+            JobServiceEngine service = mService.get();
+            if (service != null) {
+                Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams);
+                m.sendToTarget();
+            }
+        }
+
+        @Override
+        public void stopJob(JobParameters jobParams) throws RemoteException {
+            JobServiceEngine service = mService.get();
+            if (service != null) {
+                Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams);
+                m.sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Runs on application's main thread - callbacks are meant to offboard work to some other
+     * (app-specified) mechanism.
+     * @hide
+     */
+    class JobHandler extends Handler {
+        JobHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            final JobParameters params = (JobParameters) msg.obj;
+            switch (msg.what) {
+                case MSG_EXECUTE_JOB:
+                    try {
+                        boolean workOngoing = JobServiceEngine.this.onStartJob(params);
+                        ackStartMessage(params, workOngoing);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Error while executing job: " + params.getJobId());
+                        throw new RuntimeException(e);
+                    }
+                    break;
+                case MSG_STOP_JOB:
+                    try {
+                        boolean ret = JobServiceEngine.this.onStopJob(params);
+                        ackStopMessage(params, ret);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Application unable to handle onStopJob.", e);
+                        throw new RuntimeException(e);
+                    }
+                    break;
+                case MSG_JOB_FINISHED:
+                    final boolean needsReschedule = (msg.arg2 == 1);
+                    IJobCallback callback = params.getCallback();
+                    if (callback != null) {
+                        try {
+                            callback.jobFinished(params.getJobId(), needsReschedule);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Error reporting job finish to system: binder has gone" +
+                                    "away.");
+                        }
+                    } else {
+                        Log.e(TAG, "finishJob() called for a nonexistent job id.");
+                    }
+                    break;
+                default:
+                    Log.e(TAG, "Unrecognised message received.");
+                    break;
+            }
+        }
+
+        private void ackStartMessage(JobParameters params, boolean workOngoing) {
+            final IJobCallback callback = params.getCallback();
+            final int jobId = params.getJobId();
+            if (callback != null) {
+                try {
+                    callback.acknowledgeStartMessage(jobId, workOngoing);
+                } catch(RemoteException e) {
+                    Log.e(TAG, "System unreachable for starting job.");
+                }
+            } else {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
+                }
+            }
+        }
+
+        private void ackStopMessage(JobParameters params, boolean reschedule) {
+            final IJobCallback callback = params.getCallback();
+            final int jobId = params.getJobId();
+            if (callback != null) {
+                try {
+                    callback.acknowledgeStopMessage(jobId, reschedule);
+                } catch(RemoteException e) {
+                    Log.e(TAG, "System unreachable for stopping job.");
+                }
+            } else {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "Attempting to ack a job that has already been processed.");
+                }
+            }
+        }
+    }
+
+    /**
+     * Create a new engine, ready for use.
+     *
+     * @param service The {@link Service} that is creating this engine and in which it will run.
+     */
+    public JobServiceEngine(Service service) {
+        mService = service;
+        mBinder = new JobInterface(this);
+        mHandler = new JobHandler(mService.getMainLooper());
+    }
+
+    /**
+     * Retrieve the engine's IPC interface that should be returned by
+     * {@link Service#onBind(Intent)}.
+     */
+    public final IBinder getBinder() {
+        return mBinder.asBinder();
+    }
+
+    /**
+     * Engine's report that a job has started.  See
+     * {@link JobService#onStartJob(JobParameters) JobService.onStartJob} for more information.
+     */
+    public abstract boolean onStartJob(JobParameters params);
+
+    /**
+     * Engine's report that a job has stopped.  See
+     * {@link JobService#onStopJob(JobParameters) JobService.onStopJob} for more information.
+     */
+    public abstract boolean onStopJob(JobParameters params);
+
+    /**
+     * Call in to engine to report that a job has finished executing.  See
+     * {@link JobService#jobFinished(JobParameters, boolean)}  JobService.jobFinished} for more
+     * information.
+     */
+    public final void jobFinished(JobParameters params, boolean needsReschedule) {
+        Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
+        m.arg2 = needsReschedule ? 1 : 0;
+        m.sendToTarget();
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/app/job/JobWorkItem.java b/core/java/android/app/job/JobWorkItem.java
index 4bb057e..05687ee 100644
--- a/core/java/android/app/job/JobWorkItem.java
+++ b/core/java/android/app/job/JobWorkItem.java
@@ -27,6 +27,7 @@
 final public class JobWorkItem implements Parcelable {
     final Intent mIntent;
     int mWorkId;
+    Object mGrants;
 
     /**
      * Create a new piece of work.
@@ -57,6 +58,20 @@
         return mWorkId;
     }
 
+    /**
+     * @hide
+     */
+    public void setGrants(Object grants) {
+        mGrants = grants;
+    }
+
+    /**
+     * @hide
+     */
+    public Object getGrants() {
+        return mGrants;
+    }
+
     public String toString() {
         return "JobWorkItem{id=" + mWorkId + " intent=" + mIntent + "}";
     }
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index 6fc4f5c..4b6479a 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -16,17 +16,25 @@
 
 package android.app.usage;
 
+import static android.os.storage.StorageManager.convert;
+
+import android.annotation.NonNull;
 import android.annotation.TestApi;
 import android.annotation.WorkerThread;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.ParcelableException;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 
 import com.android.internal.util.Preconditions;
 
 import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
 
 /**
  * Provides access to detailed storage statistics.
@@ -50,36 +58,49 @@
 
     /** {@hide} */
     @TestApi
-    public boolean isQuotaSupported(String volumeUuid) {
+    public boolean isQuotaSupported(@NonNull UUID storageUuid) {
         try {
-            return mService.isQuotaSupported(volumeUuid, mContext.getOpPackageName());
+            return mService.isQuotaSupported(convert(storageUuid), mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public boolean isQuotaSupported(String uuid) {
+        return isQuotaSupported(convert(uuid));
+    }
+
     /**
-     * Return the total space on the requested storage volume.
+     * Return the total size of the media hosting this storage volume.
      * <p>
-     * To reduce end user confusion, this value is the total storage size
+     * To reduce end user confusion, this value matches the total storage size
      * advertised in a retail environment, which is typically larger than the
-     * actual writable partition total size.
-     * <p>
-     * This method may take several seconds to calculate the requested values,
-     * so it should only be called from a worker thread.
+     * actual usable partition space.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
+     * @throws IOException when the storage device isn't present.
      */
     @WorkerThread
-    public long getTotalBytes(String volumeUuid) {
+    public long getTotalBytes(@NonNull UUID storageUuid) throws IOException {
         try {
-            return mService.getTotalBytes(volumeUuid, mContext.getOpPackageName());
+            return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public long getTotalBytes(String uuid) throws IOException {
+        return getTotalBytes(convert(uuid));
+    }
+
     /**
      * Return the free space on the requested storage volume.
      * <p>
@@ -90,18 +111,28 @@
      * This method may take several seconds to calculate the requested values,
      * so it should only be called from a worker thread.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
+     * @throws IOException when the storage device isn't present.
      */
     @WorkerThread
-    public long getFreeBytes(String volumeUuid) {
+    public long getFreeBytes(@NonNull UUID storageUuid) throws IOException {
         try {
-            return mService.getFreeBytes(volumeUuid, mContext.getOpPackageName());
+            return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public long getFreeBytes(String uuid) throws IOException {
+        return getFreeBytes(convert(uuid));
+    }
+
     /**
      * Return storage statistics for a specific package on the requested storage
      * volume.
@@ -112,27 +143,41 @@
      * Note: if the requested package uses the {@code android:sharedUserId}
      * manifest feature, this call will be forced into a slower manual
      * calculation path. If possible, consider always using
-     * {@link #queryStatsForUid(String, int)}, which is typically faster.
+     * {@link #queryStatsForUid(UUID, int)}, which is typically faster.
      * </p>
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
      * @param packageName the package name you're interested in.
      * @param user the user you're interested in.
-     * @see ApplicationInfo#volumeUuid
+     * @throws PackageManager.NameNotFoundException when the requested package
+     *             name isn't installed for the requested user.
+     * @throws IOException when the storage device isn't present.
+     * @see ApplicationInfo#storageUuid
      * @see PackageInfo#packageName
      */
     @WorkerThread
-    public StorageStats queryStatsForPackage(String volumeUuid, String packageName,
-            UserHandle user) {
+    public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, String packageName,
+            UserHandle user) throws PackageManager.NameNotFoundException, IOException {
         try {
-            return mService.queryStatsForPackage(volumeUuid, packageName, user.getIdentifier(),
-                    mContext.getOpPackageName());
+            return mService.queryStatsForPackage(convert(storageUuid), packageName,
+                    user.getIdentifier(), mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(PackageManager.NameNotFoundException.class);
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public StorageStats queryStatsForPackage(String uuid, String packageName,
+            UserHandle user) throws PackageManager.NameNotFoundException, IOException {
+        return queryStatsForPackage(convert(uuid), packageName, user);
+    }
+
     /**
      * Return storage statistics for a specific UID on the requested storage
      * volume.
@@ -140,21 +185,32 @@
      * This method may take several seconds to calculate the requested values,
      * so it should only be called from a worker thread.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
      * @param uid the UID you're interested in.
-     * @see ApplicationInfo#volumeUuid
+     * @throws IOException when the storage device isn't present.
+     * @see ApplicationInfo#storageUuid
      * @see ApplicationInfo#uid
      */
     @WorkerThread
-    public StorageStats queryStatsForUid(String volumeUuid, int uid) {
+    public StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) throws IOException {
         try {
-            return mService.queryStatsForUid(volumeUuid, uid, mContext.getOpPackageName());
+            return mService.queryStatsForUid(convert(storageUuid), uid,
+                    mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public StorageStats queryStatsForUid(String uuid, int uid) throws IOException {
+        return queryStatsForUid(convert(uuid), uid);
+    }
+
     /**
      * Return storage statistics for a specific {@link UserHandle} on the
      * requested storage volume.
@@ -162,21 +218,32 @@
      * This method may take several seconds to calculate the requested values,
      * so it should only be called from a worker thread.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
      * @param user the user you're interested in.
+     * @throws IOException when the storage device isn't present.
      * @see android.os.Process#myUserHandle()
      */
     @WorkerThread
-    public StorageStats queryStatsForUser(String volumeUuid, UserHandle user) {
+    public StorageStats queryStatsForUser(@NonNull UUID storageUuid, UserHandle user)
+            throws IOException {
         try {
-            return mService.queryStatsForUser(volumeUuid, user.getIdentifier(),
+            return mService.queryStatsForUser(convert(storageUuid), user.getIdentifier(),
                     mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public StorageStats queryStatsForUser(String uuid, UserHandle user) throws IOException {
+        return queryStatsForUser(convert(uuid), user);
+    }
+
     /**
      * Return shared/external storage statistics for a specific
      * {@link UserHandle} on the requested storage volume.
@@ -184,20 +251,32 @@
      * This method may take several seconds to calculate the requested values,
      * so it should only be called from a worker thread.
      *
-     * @param volumeUuid the UUID of the storage volume you're interested in, or
-     *            {@code null} to specify the default internal storage.
+     * @param storageUuid the UUID of the storage volume you're interested in,
+     *            such as {@link StorageManager#UUID_DEFAULT}.
+     * @throws IOException when the storage device isn't present.
      * @see android.os.Process#myUserHandle()
      */
     @WorkerThread
-    public ExternalStorageStats queryExternalStatsForUser(String volumeUuid, UserHandle user) {
+    public ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid,
+            UserHandle user) throws IOException {
         try {
-            return mService.queryExternalStatsForUser(volumeUuid, user.getIdentifier(),
+            return mService.queryExternalStatsForUser(convert(storageUuid), user.getIdentifier(),
                     mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public ExternalStorageStats queryExternalStatsForUser(String uuid, UserHandle user)
+            throws IOException {
+        return queryExternalStatsForUser(convert(uuid), user);
+    }
+
     /** {@hide} */
     public long getCacheQuotaBytes(String volumeUuid, int uid) {
         try {
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 6ba52b7..c1ff580 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -276,8 +276,6 @@
 
     /**
      * Gets a list of all the appWidgetIds that are bound to the current host
-     *
-     * @hide
      */
     public int[] getAppWidgetIds() {
         try {
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index ef3b1c5..624ec87 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -498,8 +498,13 @@
     private void updateContentDescription(AppWidgetProviderInfo info) {
         if (info != null) {
             LauncherApps launcherApps = getContext().getSystemService(LauncherApps.class);
-            ApplicationInfo appInfo = launcherApps.getApplicationInfo(
-                    info.provider.getPackageName(), 0, info.getProfile());
+            ApplicationInfo appInfo = null;
+            try {
+                appInfo = launcherApps.getApplicationInfo(
+                        info.provider.getPackageName(), 0, info.getProfile());
+            } catch (NameNotFoundException e) {
+                // ignore -- use null.
+            }
             if (appInfo != null &&
                     (appInfo.flags & ApplicationInfo.FLAG_SUSPENDED) != 0) {
                 setContentDescription(
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 4aaf6bd..d4afcbe 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -947,6 +947,41 @@
     }
 
     /**
+     * Reads the characteristic using its UUID from the associated remote device.
+     *
+     * <p>This is an asynchronous operation. The result of the read operation
+     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
+     * callback.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @param uuid UUID of characteristic to read from the remote device
+     * @return true, if the read operation was initiated successfully
+     * @hide
+     */
+    public boolean readUsingCharacteristicUuid(UUID uuid, int startHandle, int endHandle) {
+        if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - uuid: " + uuid);
+        if (mService == null || mClientIf == 0) return false;
+
+        synchronized(mDeviceBusy) {
+            if (mDeviceBusy) return false;
+            mDeviceBusy = true;
+        }
+
+        try {
+            mService.readUsingCharacteristicUuid(mClientIf, mDevice.getAddress(),
+                new ParcelUuid(uuid), startHandle, endHandle, AUTHENTICATION_NONE);
+        } catch (RemoteException e) {
+            Log.e(TAG,"",e);
+            mDeviceBusy = false;
+            return false;
+        }
+
+        return true;
+    }
+
+
+    /**
      * Writes a given characteristic and its values to the associated remote device.
      *
      * <p>Once the write operation has been completed, the
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 334e88b..77d1178 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothGattService;
 import android.bluetooth.le.AdvertiseSettings;
@@ -47,6 +48,9 @@
     void unregisterScanner(in int scannerId);
     void startScan(in int scannerId, in ScanSettings settings, in List<ScanFilter> filters,
                    in WorkSource workSource, in List scanStorages, in String callingPackage);
+    void startScanForIntent(in PendingIntent intent, in ScanSettings settings, in List<ScanFilter> filters,
+                            in String callingPackage);
+    void stopScanForIntent(in PendingIntent intent, in String callingPackage);
     void stopScan(in int scannerId);
     void flushPendingBatchResults(in int scannerId);
 
@@ -77,6 +81,8 @@
     void refreshDevice(in int clientIf, in String address);
     void discoverServices(in int clientIf, in String address);
     void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
+    void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid,
+                           in int startHandle, in int endHandle, in int authReq);
     void writeCharacteristic(in int clientIf, in String address, in int handle,
                             in int writeType, in int authReq, in byte[] value);
     void readDescriptor(in int clientIf, in String address, in int handle, in int authReq);
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index b63c614..b65a7ad 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -17,17 +17,18 @@
 package android.bluetooth.le;
 
 import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
+import android.app.PendingIntent;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothGatt;
 import android.bluetooth.IBluetoothGatt;
 import android.bluetooth.IBluetoothManager;
-import android.bluetooth.le.IScannerCallback;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.util.Log;
@@ -36,7 +37,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 
 /**
  * This class provides methods to perform scan related operations for Bluetooth LE devices. An
@@ -57,6 +57,27 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
+    /**
+     * Extra containing a list of ScanResults. It can have one or more results if there was no
+     * error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this
+     * extra will not be available.
+     */
+    public static final String EXTRA_LIST_SCAN_RESULT
+            = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
+
+    /**
+     * Optional extra indicating the error code, if any. The error code will be one of the
+     * SCAN_FAILED_* codes in {@link ScanCallback}.
+     */
+    public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
+
+    /**
+     * Optional extra indicating the callback type, which will be one of
+     * ScanSettings.CALLBACK_TYPE_*.
+     * @see ScanCallback#onScanResult(int, ScanResult)
+     */
+    public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
+
     private final IBluetoothManager mBluetoothManager;
     private final Handler mHandler;
     private BluetoothAdapter mBluetoothAdapter;
@@ -110,7 +131,27 @@
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public void startScan(List<ScanFilter> filters, ScanSettings settings,
             final ScanCallback callback) {
-        startScan(filters, settings, null, callback, null);
+        startScan(filters, settings, null, callback, /*callbackIntent=*/ null, null);
+    }
+
+    /**
+     * Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via
+     * the PendingIntent. Use this method of scanning if your process is not always running and it
+     * should be started when scan results are available.
+     *
+     * @param filters Optional list of ScanFilters for finding exact BLE devices.
+     * @param settings Optional settings for the scan.
+     * @param callbackIntent The PendingIntent to deliver the result to.
+     * @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request
+     * could not be sent.
+     * @see #stopScan(PendingIntent)
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings,
+            @NonNull PendingIntent callbackIntent) {
+        return startScan(filters,
+                settings != null ? settings : new ScanSettings.Builder().build(),
+                null, null, callbackIntent, null);
     }
 
     /**
@@ -145,23 +186,23 @@
             Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
     public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
                                     final WorkSource workSource, final ScanCallback callback) {
-        startScan(filters, settings, workSource, callback, null);
+        startScan(filters, settings, workSource, callback, null, null);
     }
 
-    private void startScan(List<ScanFilter> filters, ScanSettings settings,
+    private int startScan(List<ScanFilter> filters, ScanSettings settings,
                            final WorkSource workSource, final ScanCallback callback,
+                           final PendingIntent callbackIntent,
                            List<List<ResultStorageDescriptor>> resultStorages) {
         BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
-        if (callback == null) {
+        if (callback == null && callbackIntent == null) {
             throw new IllegalArgumentException("callback is null");
         }
         if (settings == null) {
             throw new IllegalArgumentException("settings is null");
         }
         synchronized (mLeScanClients) {
-            if (mLeScanClients.containsKey(callback)) {
+            if (callback != null && mLeScanClients.containsKey(callback)) {
                 postCallbackError(callback, ScanCallback.SCAN_FAILED_ALREADY_STARTED);
-                return;
             }
             IBluetoothGatt gatt;
             try {
@@ -170,28 +211,34 @@
                 gatt = null;
             }
             if (gatt == null) {
-                postCallbackError(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
-                return;
+                return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
             }
             if (!isSettingsConfigAllowedForScan(settings)) {
-                postCallbackError(callback,
-                        ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
-                return;
+                return postCallbackErrorOrReturn(callback,
+                            ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
             }
             if (!isHardwareResourcesAvailableForScan(settings)) {
-                postCallbackError(callback,
-                        ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
-                return;
+                return postCallbackErrorOrReturn(callback,
+                            ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
             }
             if (!isSettingsAndFilterComboAllowed(settings, filters)) {
-                postCallbackError(callback,
+                return postCallbackErrorOrReturn(callback,
                         ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
-                return;
             }
-            BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
-                    settings, workSource, callback, resultStorages);
-            wrapper.startRegisteration();
+            if (callback != null) {
+                BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
+                        settings, workSource, callback, resultStorages);
+                wrapper.startRegistration();
+            } else {
+                try {
+                    gatt.startScanForIntent(callbackIntent, settings, filters,
+                            ActivityThread.currentOpPackageName());
+                } catch (RemoteException e) {
+                    return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
+                }
+            }
         }
+        return ScanCallback.NO_ERROR;
     }
 
     /**
@@ -215,6 +262,25 @@
     }
 
     /**
+     * Stops an ongoing Bluetooth LE scan started using a PendingIntent.
+     * <p>
+     * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
+     *
+     * @param callbackIntent The PendingIntent that was used to start the scan.
+     * @see #startScan(List, ScanSettings, PendingIntent)
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public void stopScan(PendingIntent callbackIntent) {
+        BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
+        IBluetoothGatt gatt;
+        try {
+            gatt = mBluetoothManager.getBluetoothGatt();
+            gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName());
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth
      * LE scan results batched on bluetooth controller. Returns immediately, batch scan results data
      * will be delivered through the {@code callback}.
@@ -252,7 +318,7 @@
             scanFilters.add(filter.getFilter());
             scanStorages.add(filter.getStorageDescriptors());
         }
-        startScan(scanFilters, settings, null, callback, scanStorages);
+        startScan(scanFilters, settings, null, callback, null, scanStorages);
     }
 
     /**
@@ -295,7 +361,7 @@
             mResultStorages = resultStorages;
         }
 
-        public void startRegisteration() {
+        public void startRegistration() {
             synchronized (this) {
                 // Scan stopped.
                 if (mScannerId == -1) return;
@@ -399,7 +465,6 @@
                     mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
                 }
             });
-
         }
 
         @Override
@@ -453,6 +518,15 @@
         }
     }
 
+    private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) {
+        if (callback == null) {
+            return errorCode;
+        } else {
+            postCallbackError(callback, errorCode);
+            return ScanCallback.NO_ERROR;
+        }
+    }
+
     private void postCallbackError(final ScanCallback callback, final int errorCode) {
         mHandler.post(new Runnable() {
             @Override
diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java
index 61b2e78..aff2e90 100644
--- a/core/java/android/bluetooth/le/ScanCallback.java
+++ b/core/java/android/bluetooth/le/ScanCallback.java
@@ -50,6 +50,8 @@
      */
     public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5;
 
+    static final int NO_ERROR = 0;
+
     /**
      * Callback when a BLE advertisement has been found.
      *
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 4d788e7..e50b2a9 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -22,11 +22,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.IntentSender;
 import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.service.notification.NotificationListenerService;
 import android.util.Log;
 
 import java.util.Collections;
@@ -195,22 +197,47 @@
         }
     }
 
-    /** @hide */
-    public void requestNotificationAccess() {
+    /**
+     * Request notification access for the given component.
+     *
+     * The given component must follow the protocol specified in {@link NotificationListenerService}
+     *
+     * Only components from the same {@link ComponentName#getPackageName package} as the calling app
+     * are allowed.
+     *
+     * Your app must have an association with a device before calling this API
+     */
+    public void requestNotificationAccess(ComponentName component) {
         if (!checkFeaturePresent()) {
             return;
         }
-        //TODO implement
-        throw new UnsupportedOperationException("Not yet implemented");
+        try {
+            mService.requestNotificationAccess(component).send();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (PendingIntent.CanceledException e) {
+            throw new RuntimeException(e);
+        }
     }
 
-    /** @hide */
-    public boolean haveNotificationAccess() {
+    /**
+     * Check whether the given component can access the notifications via a
+     * {@link NotificationListenerService}
+     *
+     * Your app must have an association with a device before calling this API
+     *
+     * @param component the name of the component
+     * @return whether the given component has the notification listener permission
+     */
+    public boolean hasNotificationAccess(ComponentName component) {
         if (!checkFeaturePresent()) {
             return false;
         }
-        //TODO implement
-        throw new UnsupportedOperationException("Not yet implemented");
+        try {
+            return mService.hasNotificationAccess(component);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     private boolean checkFeaturePresent() {
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 7798406..d395208 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -16,8 +16,10 @@
 
 package android.companion;
 
+import android.app.PendingIntent;
 import android.companion.IFindDeviceCallback;
 import android.companion.AssociationRequest;
+import android.content.ComponentName;
 
 /**
  * Interface for communication with the core companion device manager service.
@@ -32,7 +34,6 @@
     List<String> getAssociations(String callingPackage, int userId);
     void disassociate(String deviceMacAddress, String callingPackage);
 
-    //TODO add these
-//    boolean haveNotificationAccess(String packageName);
-//    oneway void requestNotificationAccess(String packageName);
+    boolean hasNotificationAccess(in ComponentName component);
+    PendingIntent requestNotificationAccess(in ComponentName component);
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9e1332f..6bb8a67 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2647,18 +2647,6 @@
     public abstract ComponentName startForegroundServiceAsUser(Intent service, UserHandle user);
 
     /**
-     * Start a service directly into the "foreground service" state.  Unlike {@link #startService},
-     * this method can be used from within background operations like broadcast receivers
-     * or scheduled jobs.  The API entry point for this is in NotificationManager in order to
-     * preserve appropriate public package layering.
-     * @hide
-     * @deprecated STOPSHIP remove in favor of two-step startForegroundService() + startForeground()
-     */
-    @Nullable
-    public abstract ComponentName startServiceInForeground(Intent service,
-            int id, Notification notification);
-
-    /**
      * Request that a given application service be stopped.  If the service is
      * not running, nothing happens.  Otherwise it is stopped.  Note that calls
      * to startService() are not counted -- this stops the service no matter
@@ -2696,16 +2684,6 @@
     public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
 
     /**
-     * @hide like {@link #startServiceInForeground(Intent, int, Notification)}
-     * but for a specific user.
-     * @deprecated STOPSHIP remove when trial API is turned off
-     */
-    @Deprecated
-    @Nullable
-    public abstract ComponentName startServiceInForegroundAsUser(Intent service,
-            int id, Notification notification, UserHandle user);
-
-    /**
      * @hide like {@link #stopService(Intent)} but for a specific user.
      */
     public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
@@ -2745,7 +2723,8 @@
      *          {@link #BIND_WAIVE_PRIORITY}.
      * @return If you have successfully bound to the service, {@code true} is returned;
      *         {@code false} is returned if the connection is not made so you will not
-     *         receive the service object.
+     *         receive the service object. However, you should still call
+     *         {@link #unbindService} to release the connection.
      *
      * @throws SecurityException If the caller does not have permission to access the service
      * or the service can not be found.
@@ -2896,6 +2875,7 @@
             BATTERY_SERVICE,
             JOB_SCHEDULER_SERVICE,
             //@hide: PERSISTENT_DATA_BLOCK_SERVICE,
+            //@hide: OEM_LOCK_SERVICE,
             MEDIA_PROJECTION_SERVICE,
             MIDI_SERVICE,
             RADIO_SERVICE,
@@ -3829,6 +3809,17 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
+     * android.service.oemlock.OemLockManager} instance for managing the OEM lock.
+     *
+     * @see #getSystemService
+     * @see android.service.oemlock.OemLockManager
+     * @hide
+     */
+    @SystemApi
+    public static final String OEM_LOCK_SERVICE = "oem_lock";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a {@link
      * android.media.projection.MediaProjectionManager} instance for managing
      * media projection sessions.
      * @see #getSystemService
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 53b021c..b59fc3dd 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -649,13 +649,6 @@
         return mBase.startForegroundService(service);
     }
 
-    /** @hide STOPSHIP remove when trial API is turned down */
-    @Override
-    public ComponentName startServiceInForeground(Intent service,
-            int id, Notification notification) {
-        return mBase.startServiceInForeground(service, id, notification);
-    }
-
     @Override
     public boolean stopService(Intent name) {
         return mBase.stopService(name);
@@ -673,13 +666,6 @@
         return mBase.startForegroundServiceAsUser(service, user);
     }
 
-    /** @hide STOPSHIP removed when trial API is turned down */
-    @Override
-    public ComponentName startServiceInForegroundAsUser(Intent service,
-            int id, Notification notification, UserHandle user) {
-        return mBase.startServiceInForegroundAsUser(service, id, notification, user);
-    }
-
     /** @hide */
     @Override
     public boolean stopServiceAsUser(Intent name, UserHandle user) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a4b5ffd..c39624e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -657,6 +657,16 @@
     public static final String ACTION_VIEW = "android.intent.action.VIEW";
 
     /**
+     * Extra that can be included on activity intents coming from the storage UI
+     * when it launches sub-activities to manage various types of storage.  For example,
+     * it may use {@link #ACTION_VIEW} with a "image/*" MIME type to have an app show
+     * the images on the device, and in that case also include this extra to tell the
+     * app it is coming from the storage UI so should help the user manage storage of
+     * this type.
+     */
+    public static final String EXTRA_FROM_STORAGE = "android.intent.extra.FROM_STORAGE";
+
+    /**
      * A synonym for {@link #ACTION_VIEW}, the "standard" action that is
      * performed on a piece of data.
      */
@@ -2062,13 +2072,13 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL";
     /**
-     * Broadcast Action: A new application package has been installed on the
+     * Broadcast Action: An application package has been installed or updated on the
      * device. The data contains the name of the package.  Note that the
      * newly installed package does <em>not</em> receive this broadcast.
      * <p>May include the following extras:
      * <ul>
-     * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
-     * <li> {@link #EXTRA_REPLACING} is set to true if this is following
+     * <li> {@link #EXTRA_UID} containing the integer uid assigned to this package.
+     * <li> {@link #EXTRA_REPLACING} is set to {@code true} if this is following
      * an {@link #ACTION_PACKAGE_REMOVED} broadcast for the same package.
      * </ul>
      *
@@ -2078,6 +2088,22 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PACKAGE_ADDED = "android.intent.action.PACKAGE_ADDED";
     /**
+     * Broadcast Action: A new application package has been installed on the
+     * device. The data contains the name of the package.  Note that the
+     * newly installed package does <em>not</em> receive this broadcast.
+     * <p class="note">Unlike {@link #ACTION_PACKAGE_ADDED}, this broadcast is delivered
+     * to manifest receivers as well as those registered at runtime.
+     * <p>May include the following extras:
+     * <ul>
+     * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
+     * </ul>
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PACKAGE_FIRST_ADDED = "android.intent.action.PACKAGE_FIRST_ADDED";
+    /**
      * Broadcast Action: A new version of an application package has been
      * installed, replacing an existing version that was previously installed.
      * The data contains the name of the package.
@@ -3397,11 +3423,11 @@
     public static final String EXTRA_SUBSCRIPTION_INDEX = "android.intent.extra.SUBSCRIPTION_INDEX";
 
     /**
-     * Deprecated - use {@link #ACTION_FACTORY_RESET} instead.
-     *
-     * {@hide}
+     * Deprecated - use ACTION_FACTORY_RESET instead.
+     * @hide
      */
     @Deprecated
+    @SystemApi
     public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";
 
     /**
@@ -4761,10 +4787,21 @@
     /** {@hide} */
     public static final String EXTRA_REASON = "android.intent.extra.REASON";
 
-    /** {@hide} */
+    /**
+     * {@hide}
+     * This extra will be send together with {@link #ACTION_FACTORY_RESET}
+     */
     public static final String EXTRA_WIPE_EXTERNAL_STORAGE = "android.intent.extra.WIPE_EXTERNAL_STORAGE";
 
     /**
+     * {@hide}
+     * This extra will be set to true when the user choose to wipe the data on eSIM during factory
+     * reset for the device with eSIM. This extra will be sent together with
+     * {@link #ACTION_FACTORY_RESET}
+     */
+    public static final String EXTRA_WIPE_ESIMS = "com.android.internal.intent.extra.WIPE_ESIMS";
+
+    /**
      * Optional {@link android.app.PendingIntent} extra used to deliver the result of the SIM
      * activation request.
      * TODO: Add information about the structure and response data used with the pending intent.
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 23e54ba..d64f018 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1787,7 +1787,7 @@
                     sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes);
             du.println(sb.toString());
         }
-        {
+        if (getAutoVerify()) {
             sb.setLength(0);
             sb.append(prefix); sb.append("AutoVerify="); sb.append(getAutoVerify());
             du.println(sb.toString());
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 5f53e27..8b2809a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -29,6 +29,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.Printer;
 import android.util.SparseArray;
@@ -41,6 +42,7 @@
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Objects;
+import java.util.UUID;
 
 /**
  * Information you can retrieve about a particular application.  This
@@ -621,12 +623,17 @@
      */
     public float maxAspectRatio;
 
+    /** @removed */
+    @Deprecated
+    public String volumeUuid;
+
     /**
      * UUID of the storage volume on which this application is being hosted. For
      * apps hosted on the default internal storage at
-     * {@link Environment#getDataDirectory()}, the UUID value is {@code null}.
+     * {@link Environment#getDataDirectory()}, the UUID value is
+     * {@link StorageManager#UUID_DEFAULT}.
      */
-    public String volumeUuid;
+    public UUID storageUuid;
 
     /** {@hide} */
     public String scanSourceDir;
@@ -1134,6 +1141,7 @@
         compatibleWidthLimitDp = orig.compatibleWidthLimitDp;
         largestWidthLimitDp = orig.largestWidthLimitDp;
         volumeUuid = orig.volumeUuid;
+        storageUuid = orig.storageUuid;
         scanSourceDir = orig.scanSourceDir;
         scanPublicSourceDir = orig.scanPublicSourceDir;
         sourceDir = orig.sourceDir;
@@ -1195,7 +1203,7 @@
         dest.writeInt(requiresSmallestWidthDp);
         dest.writeInt(compatibleWidthLimitDp);
         dest.writeInt(largestWidthLimitDp);
-        dest.writeString(volumeUuid);
+        dest.writeUuid(storageUuid);
         dest.writeString(scanSourceDir);
         dest.writeString(scanPublicSourceDir);
         dest.writeString(sourceDir);
@@ -1257,7 +1265,8 @@
         requiresSmallestWidthDp = source.readInt();
         compatibleWidthLimitDp = source.readInt();
         largestWidthLimitDp = source.readInt();
-        volumeUuid = source.readString();
+        storageUuid = source.readUuid();
+        volumeUuid = StorageManager.convert(storageUuid);
         scanSourceDir = source.readString();
         scanPublicSourceDir = source.readString();
         sourceDir = source.readString();
diff --git a/core/java/android/content/pm/ChangedPackages.java b/core/java/android/content/pm/ChangedPackages.java
index 94b8a5d..78c057d 100644
--- a/core/java/android/content/pm/ChangedPackages.java
+++ b/core/java/android/content/pm/ChangedPackages.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.Intent;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -26,6 +27,7 @@
 /**
  * Packages that have been changed since the last time they
  * were requested.
+ * @see PackageManager#getChangedPackages(int)
  */
 public final class ChangedPackages implements Parcelable {
     /** The last known sequence number for these changes */
@@ -33,6 +35,7 @@
     /** The names of the packages that have changed */
     private final List<String> mPackageNames;
 
+    @TestApi
     public ChangedPackages(int sequenceNumber, @NonNull List<String> packageNames) {
         this.mSequenceNumber = sequenceNumber;
         this.mPackageNames = packageNames;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 147df76..bbc942a 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -632,4 +632,6 @@
     void deletePreloadsFileCache();
 
     ComponentName getInstantAppResolverSettingsComponent();
+
+    ComponentName getInstantAppInstallerComponent();
 }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 4d76755..8ead0ec 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -22,6 +22,8 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.TestApi;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -52,6 +54,8 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 
+import com.android.internal.util.Preconditions;
+
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -275,10 +279,6 @@
         @Deprecated
         public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
 
-        /** @deprecated punted, don't use. */
-        @Deprecated
-        public static final int FLAG_MATCH_CHOOSER = 1 << 4;
-
         /**
          * Does not retrieve CHOOSER only shortcuts.
          * TODO: Add another flag for MATCH_ALL_PINNED
@@ -375,12 +375,6 @@
             return this;
         }
 
-        /** @deprecated punted, don't use. */
-        @Deprecated
-        public ShortcutQuery setIntent(@Nullable Intent intent) {
-            return this;
-        }
-
         /**
          * Set query options.  At least one of the {@code MATCH} flags should be set.  Otherwise,
          * no shortcuts will be returned.
@@ -622,11 +616,20 @@
      *         null if the package isn't installed for the given user, or the target user
      *         is not enabled.
      */
-    public ApplicationInfo getApplicationInfo(String packageName, @ApplicationInfoFlags int flags,
-            UserHandle user) {
+    public ApplicationInfo getApplicationInfo(@NonNull String packageName,
+            @ApplicationInfoFlags int flags, @NonNull UserHandle user)
+            throws PackageManager.NameNotFoundException {
+        Preconditions.checkNotNull(packageName, "packageName");
+        Preconditions.checkNotNull(packageName, "user");
         logErrorForInvalidProfileAccess(user);
         try {
-            return mService.getApplicationInfo(mContext.getPackageName(), packageName, flags, user);
+            final ApplicationInfo ai = mService
+                    .getApplicationInfo(mContext.getPackageName(), packageName, flags, user);
+            if (ai == null) {
+                throw new NameNotFoundException("Package " + packageName + " not found for user "
+                        + user.getIdentifier());
+            }
+            return ai;
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -1278,15 +1281,34 @@
      * an {@link #ACTION_CONFIRM_PIN_SHORTCUT} or {@link #ACTION_CONFIRM_PIN_APPWIDGET} intent
      * respectively to the default launcher app.
      *
-     * <p>Note the launcher may receive a request to pin a shortcut that is already pinned, because
-     * the user may actually want to have multiple icons of the same shortcut on the launcher.
-     * The launcher can tell this case by calling {@link ShortcutInfo#isPinned()} on the shortcut
-     * returned by {@link #getShortcutInfo()}.  In this case, calling {@link #accept()} is optional;
-     * even if the launcher does not call it, the shortcut is already pinned.  Also in this case,
-     * the {@code options} argument to {@link #accept(Bundle)} will be ignored.
+     * <h3>Request of the {@link #REQUEST_TYPE_SHORTCUT} type.
      *
-     * <p>For AppWidget pin requests launcher should send back the appwidget id as an extra for
-     * {@link #accept(Bundle)} as {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}.
+     * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
+     * {@link ShortcutInfo}.  If the launcher accepts a request, call {@link #accept()},
+     * or {@link #accept(Bundle)} with a null or empty Bundle.  No options are defined for
+     * pin-shortcuts requests.
+     *
+     * <p>{@link #getShortcutInfo()} always returns a non-null {@link ShortcutInfo} for this type.
+     *
+     * <p>The launcher may receive a request with a {@link ShortcutInfo} that is already pinned, in
+     * which case {@link ShortcutInfo#isPinned()} returns true.  This means the user wants to create
+     * another pinned shortcut for a shortcut that's already pinned.  If the launcher accepts it,
+     * {@link #accept()} must still be called even though the shortcut is already pinned, and
+     * create a new pinned shortcut icon for it.
+     *
+     * <p>See also {@link ShortcutManager} for more details.
+     *
+     * <h3>Request of the {@link #REQUEST_TYPE_APPWIDGET} type.
+     *
+     * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
+     * an AppWidget.  If the launcher accepts a request, call {@link #accept(Bundle)} with
+     * the appwidget integer ID set to the
+     * {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID} extra.
+     *
+     * <p>{@link #getAppWidgetProviderInfo(Context)} always returns a non-null
+     * {@link AppWidgetProviderInfo} for this type.
+     *
+     * <p>See also {@link AppWidgetManager} for more details.
      *
      * @see #EXTRA_PIN_ITEM_REQUEST
      * @see #getPinItemRequest(Intent)
@@ -1316,8 +1338,9 @@
         }
 
         /**
-         * Represents the type of a request.  For now {@link #REQUEST_TYPE_SHORTCUT} is the only
-         * valid type.
+         * Represents the type of a request, which is one of the {@code REQUEST_TYPE_} constants.
+         *
+         * @return one of the {@code REQUEST_TYPE_} constants.
          */
         @RequestType
         public int getRequestType() {
@@ -1325,8 +1348,12 @@
         }
 
         /**
-         * {@link ShortcutInfo} sent by the requesting app.  Always non-null for a
-         * {@link #REQUEST_TYPE_SHORTCUT} request.
+         * {@link ShortcutInfo} sent by the requesting app.
+         * Always non-null for a {@link #REQUEST_TYPE_SHORTCUT} request, and always null for a
+         * different request type.
+         *
+         * @return requested {@link ShortcutInfo} when a request is of the
+         * {@link #REQUEST_TYPE_SHORTCUT} type.  Null otherwise.
          */
         @Nullable
         public ShortcutInfo getShortcutInfo() {
@@ -1338,8 +1365,12 @@
         }
 
         /**
-         * {@link AppWidgetProviderInfo} sent by the requesting app.  Always non-null for a
-         * {@link #REQUEST_TYPE_APPWIDGET} request.
+         * {@link AppWidgetProviderInfo} sent by the requesting app.
+         * Always non-null for a {@link #REQUEST_TYPE_APPWIDGET} request, and always null for a
+         * different request type.
+         *
+         * @return requested {@link AppWidgetProviderInfo} when a request is of the
+         * {@link #REQUEST_TYPE_APPWIDGET} type.  Null otherwise.
          */
         @Nullable
         public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
@@ -1357,6 +1388,11 @@
 
         /**
          * Any extras sent by the requesting app.
+         *
+         * @return For a shortcut request, this method always return null.  For an AppWidget
+         * request, this method returns the extras passed to the
+         * {@link android.appwidget.AppWidgetManager#requestPinAppWidget(
+         * ComponentName, Bundle, PendingIntent)} API.  See {@link AppWidgetManager} for details.
          */
         @Nullable
         public Bundle getExtras() {
@@ -1368,8 +1404,9 @@
         }
 
         /**
-         * Return {@code TRUE} if a request is valid -- i.e. {@link #accept(Bundle)} has not been
-         * called yet.
+         * Return whether a request is still valid.
+         *
+         * @return {@code TRUE} if a request is valid and {@link #accept(Bundle)} may be called.
          */
         public boolean isValid() {
             try {
@@ -1381,6 +1418,12 @@
 
         /**
          * Called by the receiving launcher app when the user accepts the request.
+         *
+         * @param options must be set for a {@link #REQUEST_TYPE_APPWIDGET} request.
+         *
+         * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
+         * {@code FALSE} if the item hasn't been pinned, for example, because the request had
+         * already been canceled, in which case the launcher must not pin the requested item.
          */
         public boolean accept(@Nullable Bundle options) {
             try {
@@ -1391,7 +1434,11 @@
         }
 
         /**
-         * Same as as {@link #accept(Bundle)} with no options.
+         * Called by the receiving launcher app when the user accepts the request, with no options.
+         *
+         * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
+         * {@code FALSE} if the item hasn't been pinned, for example, because the request had
+         * already been canceled, in which case the launcher must not pin the requested item.
          */
         public boolean accept() {
             return accept(/* options= */ null);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 5c1e90d..08cd6e6 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -54,6 +54,7 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
+import android.provider.Settings;
 import android.util.AndroidException;
 import android.util.Log;
 
@@ -1763,6 +1764,17 @@
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports any
+     * one of the {@link #FEATURE_NFC}, {@link #FEATURE_NFC_HOST_CARD_EMULATION},
+     * or {@link #FEATURE_NFC_HOST_CARD_EMULATION_NFCF} features.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_NFC_ANY = "android.hardware.nfc.any";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports the OpenGL ES
      * <a href="http://www.khronos.org/registry/gles/extensions/ANDROID/ANDROID_extension_pack_es31a.txt">
      * Android Extension Pack</a>.
@@ -3989,6 +4001,8 @@
      * <p>If no packages have been changed, returns <code>null</code>.
      * <p>The sequence number starts at <code>0</code> and is
      * reset every boot.
+     * @param sequenceNumber The first sequence number for which to retrieve package changes.
+     * @see Settings.Global#BOOT_COUNT
      */
     public abstract @Nullable ChangedPackages getChangedPackages(
             @IntRange(from=0) int sequenceNumber);
@@ -6262,18 +6276,18 @@
 
     /**
      * Checks whether the calling package is allowed to request package installs through package
-     * installer. Apps are encouraged to call this api before launching the package installer via
+     * installer. Apps are encouraged to call this API before launching the package installer via
      * intent {@link android.content.Intent#ACTION_INSTALL_PACKAGE}. Starting from Android O, the
      * user can explicitly choose what external sources they trust to install apps on the device.
-     * If this api returns false, the install request will be blocked by the package installer and
+     * If this API returns false, the install request will be blocked by the package installer and
      * a dialog will be shown to the user with an option to launch settings to change their
      * preference. An application must target Android O or higher and declare permission
-     * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES} in order to use this api.
+     * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES} in order to use this API.
      *
      * @return true if the calling package is trusted by the user to request install packages on
      * the device, false otherwise.
-     * @see {@link android.content.Intent#ACTION_INSTALL_PACKAGE}
-     * @see {@link android.provider.Settings#ACTION_MANAGE_UNKNOWN_APP_SOURCES}
+     * @see android.content.Intent#ACTION_INSTALL_PACKAGE
+     * @see android.provider.Settings#ACTION_MANAGE_UNKNOWN_APP_SOURCES
      */
     public abstract boolean canRequestPackageInstalls();
 
@@ -6281,9 +6295,19 @@
      * Return the {@link ComponentName} of the activity providing Settings for the Instant App
      * resolver.
      *
-     * @see {@link android.content.intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
+     * @see {@link android.content.Intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS}
      * @hide
      */
     @SystemApi
     public abstract ComponentName getInstantAppResolverSettingsComponent();
+
+    /**
+     * Return the {@link ComponentName} of the activity responsible for installing instant
+     * applications.
+     *
+     * @see {@link android.content.Intent#ACTION_INSTALL_INSTANT_APP_PACKAGE}
+     * @hide
+     */
+    @SystemApi
+    public abstract ComponentName getInstantAppInstallerComponent();
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e64b2a5..1f78bff 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -64,8 +64,10 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.system.ErrnoException;
 import android.system.OsConstants;
 import android.system.StructStat;
@@ -116,6 +118,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.ZipEntry;
 
@@ -2111,6 +2114,12 @@
                 pkg.mIsStaticOverlay = sa.getBoolean(
                         com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
                         false);
+                final String propName = sa.getString(
+                        com.android.internal.R.styleable
+                        .AndroidManifestResourceOverlay_requiredSystemPropertyName);
+                final String propValue = sa.getString(
+                        com.android.internal.R.styleable
+                        .AndroidManifestResourceOverlay_requiredSystemPropertyValue);
                 sa.recycle();
 
                 if (pkg.mOverlayTarget == null) {
@@ -2118,15 +2127,22 @@
                     mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                     return null;
                 }
+
                 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
                     outError[0] = "<overlay> priority must be between 0 and 9999";
                     mParseError =
                         PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
                     return null;
                 }
-                if (pkg.mIsStaticOverlay) {
-                    // TODO(b/35742444): Need to support selection method based on a package name.
+
+                // check to see if overlay should be excluded based on system property condition
+                if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
+                    Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
+                        + pkg.baseCodePath+ ": overlay ignored due to required system property: "
+                        + propName + " with value: " + propValue);
+                    return null;
                 }
+
                 XmlUtils.skipCurrentTag(parser);
 
             } else if (tagName.equals(TAG_KEY_SETS)) {
@@ -2531,6 +2547,25 @@
         return pkg;
     }
 
+    private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
+
+        if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
+            if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
+                // malformed condition - incomplete
+                Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
+                    + "=" + propValue + "' - require both requiredSystemPropertyName"
+                    + " AND requiredSystemPropertyValue to be specified.");
+                return false;
+            }
+            // no valid condition set - so no exclusion criteria, overlay will be included.
+            return true;
+        }
+
+        // check property value - make sure it is both set and equal to expected value
+        final String currValue = SystemProperties.get(propName);
+        return (currValue != null && currValue.equals(propValue));
+    }
+
     /**
      * This is a pre-density application which will get scaled - instead of being pixel perfect.
      * This type of application is not resizable.
@@ -3363,7 +3398,12 @@
             if (sa.getBoolean(
                     com.android.internal.R.styleable.AndroidManifestApplication_persistent,
                     false)) {
-                ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
+                // Check if persistence is based on a feature being present
+                final String requiredFeature = sa.getNonResourceString(
+                    com.android.internal.R.styleable.AndroidManifestApplication_persistentFeature);
+                if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
+                    ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
+                }
             }
         }
 
@@ -4268,7 +4308,7 @@
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                intent.setVisibleToInstantApp(visibleToEphemeral || isWebBrowsableIntent(intent));
+                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
                 if (intent.isVisibleToInstantApp()) {
                     a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
@@ -4301,7 +4341,7 @@
                     owner.preferredActivityFilters.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                intent.setVisibleToInstantApp(visibleToEphemeral || isWebBrowsableIntent(intent));
+                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
                 if (intent.isVisibleToInstantApp()) {
                     a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
@@ -4629,7 +4669,7 @@
                             + parser.getPositionDescription());
                 } else {
                     intent.setVisibleToInstantApp(
-                            visibleToEphemeral || isWebBrowsableIntent(intent));
+                            visibleToEphemeral || isImplicitlyExposedIntent(intent));
                     a.intents.add(intent);
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
@@ -4831,7 +4871,7 @@
                 }
                 outInfo.intents.add(intent);
                 // adjust provider flags when we implicitly expose it via a browsable filter
-                intent.setVisibleToInstantApp(visibleToEphemeral || isWebBrowsableIntent(intent));
+                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
                 if (intent.isVisibleToInstantApp()) {
                     outInfo.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
@@ -5136,7 +5176,7 @@
                     return null;
                 }
                 // adjust activity flags when we implicitly expose it via a browsable filter
-                intent.setVisibleToInstantApp(visibleToEphemeral || isWebBrowsableIntent(intent));
+                intent.setVisibleToInstantApp(visibleToEphemeral || isImplicitlyExposedIntent(intent));
                 if (intent.isVisibleToInstantApp()) {
                     s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
                 }
@@ -5177,8 +5217,11 @@
         return s;
     }
 
-    private boolean isWebBrowsableIntent(IntentInfo intent) {
-        return intent.hasCategory(Intent.CATEGORY_BROWSABLE);
+    private boolean isImplicitlyExposedIntent(IntentInfo intent) {
+        return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
+                || intent.hasAction(Intent.ACTION_SEND)
+                || intent.hasAction(Intent.ACTION_SENDTO)
+                || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
     }
 
     private boolean parseAllMetaData(Resources res, XmlResourceParser parser, String tag,
@@ -5733,11 +5776,14 @@
         }
 
         public void setApplicationVolumeUuid(String volumeUuid) {
+            final UUID storageUuid = StorageManager.convert(volumeUuid);
             this.applicationInfo.volumeUuid = volumeUuid;
+            this.applicationInfo.storageUuid = storageUuid;
             if (childPackages != null) {
                 final int packageCount = childPackages.size();
                 for (int i = 0; i < packageCount; i++) {
                     childPackages.get(i).applicationInfo.volumeUuid = volumeUuid;
+                    childPackages.get(i).applicationInfo.storageUuid = storageUuid;
                 }
             }
         }
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index d79deb2..0ad4874 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -16,11 +16,14 @@
 
 package android.content.pm;
 
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
 import java.util.List;
 
@@ -31,28 +34,37 @@
  * static - updatable non backwards-compatible emulating static linking.
  */
 public final class SharedLibraryInfo implements Parcelable {
+
+    /** @hide */
+    @IntDef(
+        flag = true,
+        value = {
+                TYPE_BUILTIN,
+                TYPE_DYNAMIC,
+                TYPE_STATIC,
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface Type{}
+
     /**
      * Shared library type: this library is a part of the OS
      * and cannot be updated or uninstalled.
-     * @hide
      */
-    public static final int TYPE_BUILTIN = 0x1<<0;
+    public static final int TYPE_BUILTIN = 0;
 
     /**
      * Shared library type: this library is backwards-compatible, can
      * be updated, and updates can be uninstalled. Clients link against
      * the latest version of the library.
-     * @hide
      */
-    public static final int TYPE_DYNAMIC = 0x1<<1;
+    public static final int TYPE_DYNAMIC = 1;
 
     /**
      * Shared library type: this library is <strong>not</strong> backwards
      * -compatible, can be updated and updates can be uninstalled. Clients
      * link against a specific version of the library.
-     * @hide
      */
-    public static final int TYPE_STATIC = 0x1<<2;
+    public static final int TYPE_STATIC = 2;
 
     /**
      * Constant for referring to an undefined version.
@@ -60,8 +72,10 @@
     public static final int VERSION_UNDEFINED = -1;
 
     private final String mName;
+
+    // TODO: Make long when we change the paltform to use longs
     private final int mVersion;
-    private final int mType;
+    private final @Type int mType;
     private final VersionedPackage mDeclaringPackage;
     private final List<VersionedPackage> mDependentPackages;
 
@@ -90,13 +104,18 @@
                 parcel.readParcelable(null), parcel.readArrayList(null));
     }
 
-    /** @hide */
-    public int getType() {
+    /**
+     * Gets the type of this library.
+     *
+     * @return The library type.
+     */
+    public @Type int getType() {
         return mType;
     }
 
     /**
-     * Gets the library name.
+     * Gets the library name an app defines in its manifest
+     * to depend on the library.
      *
      * @return The name.
      */
@@ -105,40 +124,36 @@
     }
 
     /**
-     * Gets the version of the library. For {@link #isStatic()}  static} libraries
-     * this is the declared version and for {@link #isDynamic()} dynamic} and
-     * {@link #isBuiltin()} builtin} it is {@link #VERSION_UNDEFINED} as these
+     * Gets the version of the library. For {@link #TYPE_STATIC static} libraries
+     * this is the declared version and for {@link #TYPE_DYNAMIC dynamic} and
+     * {@link #TYPE_BUILTIN builtin} it is {@link #VERSION_UNDEFINED} as these
      * are not versioned.
      *
      * @return The version.
      */
-    public @IntRange(from = -1) int getVersion() {
+    public @IntRange(from = -1) long getVersion() {
         return mVersion;
     }
 
     /**
-     * @return whether this library is builtin which means that it
-     * is a part of the OS and cannot be updated or uninstalled.
+     * @hide
+     * @removed
      */
     public boolean isBuiltin() {
         return mType == TYPE_BUILTIN;
     }
 
     /**
-     * @return whether this library is dynamic which means that it
-     * is backwards-compatible, can be updated, and updates can be
-     * uninstalled. Clients link against the latest version of the
-     * library.
+     * @hide
+     * @removed
      */
     public boolean isDynamic() {
         return mType == TYPE_DYNAMIC;
     }
 
     /**
-     * @return whether this library is dynamic which means that it
-     * is <strong>not</strong> backwards-compatible, can be updated
-     * and updates can be uninstalled. Clients link against a specific
-     * version of the library.
+     * @hide
+     * @removed
      */
     public boolean isStatic() {
         return mType == TYPE_STATIC;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 3f4a090..2b76ae2 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -1032,20 +1032,6 @@
             return this;
         }
 
-        /** @deprecated punted, don't use. */
-        @Deprecated
-        @NonNull
-        public Builder setChooserExtras(@NonNull PersistableBundle extras) {
-            return this;
-        }
-
-        /** @deprecated punted, don't use. */
-        @Deprecated
-        public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
-                @NonNull ComponentName name) {
-            return this;
-        }
-
         /**
          * Creates a {@link ShortcutInfo} instance.
          */
@@ -1246,27 +1232,6 @@
         return mIntentPersistableExtrases;
     }
 
-    /** @deprecated punted, don't use. */
-    @Deprecated
-    @NonNull
-    public PersistableBundle getChooserExtras() {
-        return new PersistableBundle();
-    }
-
-    /** @deprecated punted, don't use. */
-    @Deprecated
-    @NonNull
-    public IntentFilter[] getChooserIntentFilters() {
-        return new IntentFilter[0];
-    }
-
-    /** @deprecated punted, don't use. */
-    @Deprecated
-    @NonNull
-    public ComponentName[] getChooserComponentNames() {
-        return new ComponentName[0];
-    }
-
     /**
      * "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
      * {@link #getActivity} for each of the two types of shortcuts (static and dynamic).
@@ -1388,12 +1353,6 @@
         return hasFlags(FLAG_PINNED);
     }
 
-    /** @deprecated punted, don't use. */
-    @Deprecated
-    public boolean isChooser() {
-        return false;
-    }
-
     /**
      * Return whether a shortcut is static; that is, whether a shortcut is
      * published from AndroidManifest.xml.  If {@code true}, the shortcut is
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index c8353c9..88c1627 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -127,7 +127,7 @@
      */
     public static final int COLOR_MODE_WIDE_COLOR_GAMUT_YES = 0x2;
 
-    /** Constant for {@link #colorMode}: bits that encode whether the dynamic range of the screen. */
+    /** Constant for {@link #colorMode}: bits that encode the dynamic range of the screen. */
     public static final int COLOR_MODE_HDR_MASK = 0xc;
     /** Constant for {@link #colorMode}: bits shift to get the screen dynamic range. */
     public static final int COLOR_MODE_HDR_SHIFT = 2;
@@ -155,7 +155,7 @@
             COLOR_MODE_HDR_UNDEFINED;
 
     /**
-     * Bit mask of for color capabilities of the screen. Currently there are two fields:
+     * Bit mask of color capabilities of the screen. Currently there are two fields:
      * <p>The {@link #COLOR_MODE_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
      * the screen. They may be one of
      * {@link #COLOR_MODE_WIDE_COLOR_GAMUT_NO} or {@link #COLOR_MODE_WIDE_COLOR_GAMUT_YES}.</p>
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 3693bce9..408bee8 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1450,7 +1450,8 @@
          * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
          * with the array.
          * 
-         * @param attrs The desired attributes.
+         * @param attrs The desired attributes. These attribute IDs must be sorted in ascending
+         *              order.
          *
          * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
          * 
@@ -1474,7 +1475,8 @@
          * with the array.
          * 
          * @param resId The desired style resource.
-         * @param attrs The desired attributes in the style.
+         * @param attrs The desired attributes in the style. These attribute IDs must be sorted in
+         *              ascending order.
          * 
          * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
          * 
@@ -1521,7 +1523,8 @@
          * the styles.
          * 
          * @param set The base set of attribute values.  May be null.
-         * @param attrs The desired attributes to be retrieved.
+         * @param attrs The desired attributes to be retrieved. These attribute IDs must be sorted
+         *              in ascending order.
          * @param defStyleAttr An attribute in the current theme that contains a
          *                     reference to a style resource that supplies
          *                     defaults values for the TypedArray.  Can be
@@ -1552,7 +1555,8 @@
          * @param values The base set of attribute values, must be equal in
          *               length to {@code attrs}. All values must be of type
          *               {@link TypedValue#TYPE_ATTRIBUTE}.
-         * @param attrs The desired attributes to be retrieved.
+         * @param attrs The desired attributes to be retrieved. These attribute IDs must be sorted
+         *              in ascending order.
          * @return Returns a TypedArray holding an array of the attribute
          *         values. Be sure to call {@link TypedArray#recycle()}
          *         when done with it.
@@ -1791,14 +1795,15 @@
      * performing styling of them using a theme and/or style resources.
      *
      * @param set The current attribute values to retrieve.
-     * @param attrs The specific attributes to be retrieved.
+     * @param attrs The specific attributes to be retrieved. These attribute IDs must be sorted in
+     *              ascending order.
      * @return Returns a TypedArray holding an array of the attribute values.
      * Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
      * when done with it.
      * 
      * @see Theme#obtainStyledAttributes(AttributeSet, int[], int, int)
      */
-    public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
+    public TypedArray obtainAttributes(AttributeSet set, @StyleableRes int[] attrs) {
         int len = attrs.length;
         TypedArray array = TypedArray.obtain(this, len);
 
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index f48afb5..88bb1a4 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -56,12 +56,13 @@
         // Reset the assets, which may have changed due to configuration changes
         // or further resource loading.
         attrs.mAssets = res.getAssets();
+        attrs.mMetrics = res.getDisplayMetrics();
         attrs.resize(len);
         return attrs;
     }
 
     private final Resources mResources;
-    private final DisplayMetrics mMetrics;
+    private DisplayMetrics mMetrics;
     private AssetManager mAssets;
 
     private boolean mRecycled;
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 0218cb5..a895f82 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -836,16 +836,16 @@
     }
 
     /**
-     * Test if sensor support direct channel backed by a specific type of shared memory.
+     * Test if a sensor supports a specified direct channel type.
      *
      * @param sharedMemType type of shared memory used by direct channel.
-     * @return <code>true</code> if the shared memory type is supported.
-     * @see SensorDirectChannel#TYPE_ASHMEM
+     * @return <code>true</code> if the specified shared memory type is supported.
+     * @see SensorDirectChannel#TYPE_MEMORY_FILE
      * @see SensorDirectChannel#TYPE_HARDWARE_BUFFER
      */
     public boolean isDirectChannelTypeSupported(@SensorDirectChannel.MemoryType int sharedMemType) {
         switch (sharedMemType) {
-            case SensorDirectChannel.TYPE_ASHMEM:
+            case SensorDirectChannel.TYPE_MEMORY_FILE:
                 return (mFlags & (1 << DIRECT_CHANNEL_SHIFT)) > 0;
             case SensorDirectChannel.TYPE_HARDWARE_BUFFER:
                 return (mFlags & (1 << DIRECT_CHANNEL_SHIFT + 1)) > 0;
diff --git a/core/java/android/hardware/SensorDirectChannel.java b/core/java/android/hardware/SensorDirectChannel.java
index 2c499b0..36607c9 100644
--- a/core/java/android/hardware/SensorDirectChannel.java
+++ b/core/java/android/hardware/SensorDirectChannel.java
@@ -23,26 +23,31 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.nio.channels.Channel;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * Class representing a sensor direct channel. Use {@link
- * SensorManager#createDirectChannel(android.os.MemoryFile)} to obtain object.
+ * Class representing a sensor direct channel. Use
+ * {@link SensorManager#createDirectChannel(android.os.MemoryFile)} or
+ * {@link SensorManager#createDirectChannel(android.hardware.HardwareBuffer)}
+ * to obtain an object. The channel object can be then configured
+ * (see {@link #configure(Sensor, int)})
+ * to start delivery of sensor events into shared memory buffer.
  */
-public final class SensorDirectChannel implements AutoCloseable {
+public final class SensorDirectChannel implements Channel {
 
     // shared memory types
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = {TYPE_ASHMEM, TYPE_HARDWARE_BUFFER})
+    @IntDef(flag = true, value = {TYPE_MEMORY_FILE, TYPE_HARDWARE_BUFFER})
     public @interface MemoryType {};
     /**
      * Shared memory type ashmem, wrapped in MemoryFile object.
      *
      * @see SensorManager#createDirectChannel(MemoryFile)
      */
-    public static final int TYPE_ASHMEM = 1;
+    public static final int TYPE_MEMORY_FILE = 1;
 
     /**
      * Shared memory type wrapped by HardwareBuffer object.
@@ -61,7 +66,7 @@
     /**
      * Sensor stopped (no event output).
      *
-     * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+     * @see #configure(Sensor, int)
      */
     public static final int RATE_STOP = 0;
     /**
@@ -70,7 +75,7 @@
      * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 27.5Hz to
      * 110Hz.
      *
-     * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+     * @see #configure(Sensor, int)
      */
     public static final int RATE_NORMAL = 1; //50Hz
     /**
@@ -79,7 +84,7 @@
      * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 110Hz to
      * 440Hz.
      *
-     * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+     * @see #configure(Sensor, int)
      */
     public static final int RATE_FAST = 2; // ~200Hz
     /**
@@ -88,7 +93,7 @@
      * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 440Hz to
      * 1760Hz.
      *
-     * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+     * @see #configure(Sensor, int)
      */
     public static final int RATE_VERY_FAST = 3; // ~800Hz
 
@@ -98,10 +103,17 @@
      *
      * @return <code>true</code> if channel is valid.
      */
-    public boolean isValid() {
+    @Override
+    public boolean isOpen() {
         return !mClosed.get();
     }
 
+    /** @removed */
+    @Deprecated
+    public boolean isValid() {
+        return isOpen();
+    }
+
     /**
      * Close sensor direct channel.
      *
@@ -113,13 +125,61 @@
      */
     @Override
     public void close() {
-        mCloseGuard.close();
         if (mClosed.compareAndSet(false, true)) {
+            mCloseGuard.close();
             // actual close action
             mManager.destroyDirectChannel(this);
         }
     }
 
+    /**
+     * Configure sensor rate or stop sensor report.
+     *
+     * To start event report of a sensor, or change rate of existing report, call this function with
+     * rateLevel other than {@link android.hardware.SensorDirectChannel#RATE_STOP}. Sensor events
+     * will be added into a queue formed by the shared memory used in creation of direction channel.
+     * Each element of the queue has size of 104 bytes and represents a sensor event. Data
+     * structure of an element (all fields in little-endian):
+     *
+     * <pre>
+     *   offset   type                    name
+     * ------------------------------------------------------------------------
+     *   0x0000   int32_t                 size (always 104)
+     *   0x0004   int32_t                 sensor report token
+     *   0x0008   int32_t                 type (see SensorType)
+     *   0x000C   uint32_t                atomic counter
+     *   0x0010   int64_t                 timestamp (see Event)
+     *   0x0018   float[16]/int64_t[8]    data (data type depends on sensor type)
+     *   0x0058   int32_t[4]              reserved (set to zero)
+     * </pre>
+     *
+     * There are no head or tail pointers. The sequence and frontier of new sensor events is
+     * determined by the atomic counter, which counts from 1 after creation of direct channel and
+     * increments 1 for each new event. Atomic counter will wrap back to 1 after it reaches
+     * UINT32_MAX, skipping value 0 to avoid confusion with uninitialized memory. The writer in
+     * sensor system will wrap around from the start of shared memory region when it reaches the
+     * end. If size of memory region is not a multiple of size of element (104 bytes), the residual
+     * is not used at the end.  Function returns a positive sensor report token on success. This
+     * token can be used to differentiate sensor events from multiple sensor of the same type. For
+     * example, if there are two accelerometers in the system A and B, it is guaranteed different
+     * report tokens will be returned when starting sensor A and B.
+     *
+     * To stop a sensor, call this function with rateLevel equal {@link
+     * android.hardware.SensorDirectChannel#RATE_STOP}. If the sensor parameter is left to be null,
+     * this will stop all active sensor report associated with the direct channel specified.
+     * Function return 1 on success or 0 on failure.
+     *
+     * @param sensor A {@link android.hardware.Sensor} object to denote sensor to be operated.
+     * @param rateLevel rate level defined in {@link android.hardware.SensorDirectChannel}.
+     * @return * starting report or changing rate: positive sensor report token on success,
+     *                                             0 on failure;
+     *         * stopping report: 1 on success, 0 on failure.
+     * @throws NullPointerException when channel is null.
+     */
+    public int configure(Sensor sensor, @RateLevel int rateLevel) {
+        return mManager.configureDirectChannelImpl(this, sensor, rateLevel);
+    }
+
     /** @hide */
     SensorDirectChannel(SensorManager manager, int id, int type, long size) {
         mManager = manager;
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 1dc6478..ed56391 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -882,7 +882,12 @@
 
 
     /**
-     * Create a sensor direct channel backed by shared memory wrapped by MemoryFile object.
+     * Create a sensor direct channel backed by shared memory wrapped in MemoryFile object.
+     *
+     * The resulting channel can be used for delivering sensor events to native code, other
+     * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
+     * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
+     * and cares about sensor event latency.
      *
      * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
      * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
@@ -890,7 +895,7 @@
      *
      * @param mem A {@link android.os.MemoryFile} shared memory object.
      * @return A {@link android.hardware.SensorDirectChannel} object if successful, null otherwise.
-     * @throws IllegalArgumentException when mem is null.
+     * @throws NullPointerException when mem is null.
      * @see SensorDirectChannel#close()
      * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
      */
@@ -899,7 +904,12 @@
     }
 
     /**
-     * Create a sensor direct channel backed by shared memory wrapped by HardwareBuffer object.
+     * Create a sensor direct channel backed by shared memory wrapped in HardwareBuffer object.
+     *
+     * The resulting channel can be used for delivering sensor events to native code, other
+     * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
+     * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
+     * and cares about sensor event latency.
      *
      * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
      * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
@@ -908,7 +918,7 @@
      * @param mem A {@link android.hardware.HardwareBuffer} shared memory object.
      * @return A {@link android.hardware.SensorDirectChannel} object if successful,
      *         null otherwise.
-     * @throws IllegalArgumentException when mem is null.
+     * @throws NullPointerException when mem is null.
      * @see SensorDirectChannel#close()
      * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
      */
@@ -928,50 +938,9 @@
     /** @hide */
     protected abstract void destroyDirectChannelImpl(SensorDirectChannel channel);
 
-    /**
-     * Configure sensor rate or stop sensor report on a direct report channel specified.
-     *
-     * To start event report of a sensor, or change rate of existing report, call this function with
-     * rateLevel other than {@link android.hardware.SensorDirectChannel#RATE_STOP}. Sensor events
-     * will be added into a queue formed by the shared memory used in creation of direction channel.
-     * Each element of the queue has size of 104 bytes and represents a sensor event. Data
-     * structure of an element (all fields in little-endian):
-     *
-     *   offset   type                    name
-     *-  ---------------------------------------------
-     *   0x0000   int32_t                 size (always 104)
-     *   0x0004   int32_t                 sensor report token
-     *   0x0008   int32_t                 type (see SensorType)
-     *   0x000C   uint32_t                atomic counter
-     *   0x0010   int64_t                 timestamp (see Event)
-     *   0x0018   float[16]/int64_t[8]    data (data type depends on sensor type)
-     *   0x0058   int32_t[4]              reserved (set to zero)
-     *
-     * There is no head or tail pointers. The sequence and frontier of new sensor events is
-     * determined by the atomic counter, which counts from 1 after creation of direct channel and
-     * increments 1 for each new event. The writer in sensor system will wrap around from to
-     * start of shared memory region when it reaches the end. If size of memory region is not
-     * a multiple of size of element (104 bytes), the residual is not used at the end.
-     * Function returns a positive sensor report token on success. This token can be used for
-     * differentiate sensor events from multiple sensor of the same type. For example, if there are
-     * two accelerometer in the system A and B, it is guaranteed different report tokens will be
-     * returned when starting sensor A and B.
-     *
-     * To stop a sensor, call this function with rateLevel equal {@link
-     * android.hardware.SensorDirectChannel#RATE_STOP}. If the sensor parameter is left to be null,
-     * this will stop all active sensor report associated with the direct channel specified.
-     * Function return 1 on success or 0 on failure.
-     *
-     * @param channel A {@link android.hardware.SensorDirectChannel} object representing direct
-     *                channel to be configured.
-     * @param sensor A {@link android.hardware.Sensor} object to denote sensor to be operated.
-     * @param rateLevel rate level defined in {@link android.hardware.SensorDirectChannel}.
-     * @return starting report or changing rate: positive sensor report token on success, 0 on failure;
-     *         stopping report: 1 on success, 0 on failure.
-     * @throws IllegalArgumentException when SensorDirectChannel is null.
-     */
-    public int configureDirectChannel(SensorDirectChannel channel, Sensor sensor,
-            @SensorDirectChannel.RateLevel int rateLevel) {
+    /** @removed */
+    @Deprecated
+    public int configureDirectChannel(SensorDirectChannel channel, Sensor sensor, int rateLevel) {
         return configureDirectChannelImpl(channel, sensor, rateLevel);
     }
 
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 0677179..10c4cb3 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -35,6 +35,7 @@
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -500,10 +501,8 @@
     /** @hide */
     protected int configureDirectChannelImpl(
             SensorDirectChannel channel, Sensor sensor, int rate) {
-        if (channel == null) throw new IllegalArgumentException("channel cannot be null");
-
-        if (!channel.isValid()) {
-            throw new IllegalStateException("channel is invalid");
+        if (!channel.isOpen()) {
+            throw new IllegalStateException("channel is closed");
         }
 
         if (rate < SensorDirectChannel.RATE_STOP
@@ -532,7 +531,8 @@
     /** @hide */
     protected SensorDirectChannel createDirectChannelImpl(
             MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
-        SensorDirectChannel ch = null;
+        int id;
+        int type;
         long size;
         if (memoryFile != null) {
             int fd;
@@ -549,11 +549,13 @@
             }
 
             size = memoryFile.length();
-            int id = nativeCreateDirectChannel(
-                    mNativeInstance, size, SensorDirectChannel.TYPE_ASHMEM, fd, null);
-            if (id > 0) {
-                ch = new SensorDirectChannel(this, id, SensorDirectChannel.TYPE_ASHMEM, size);
+            id = nativeCreateDirectChannel(
+                    mNativeInstance, size, SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
+            if (id <= 0) {
+                throw new UncheckedIOException(
+                        new IOException("create MemoryFile direct channel failed " + id));
             }
+            type = SensorDirectChannel.TYPE_MEMORY_FILE;
         } else if (hardwareBuffer != null) {
             if (hardwareBuffer.getFormat() != HardwareBuffer.BLOB) {
                 throw new IllegalArgumentException("Format of HardwareBuffer must be BLOB");
@@ -571,18 +573,18 @@
                         "HardwareBuffer must set usage flag USAGE0_SENSOR_DIRECT_DATA");
             }
             size = hardwareBuffer.getWidth();
-            int id = nativeCreateDirectChannel(
+            id = nativeCreateDirectChannel(
                     mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
                     -1, hardwareBuffer);
-            if (id > 0) {
-                ch = new SensorDirectChannel(
-                        this, id, SensorDirectChannel.TYPE_HARDWARE_BUFFER, size);
+            if (id <= 0) {
+                throw new UncheckedIOException(
+                        new IOException("create HardwareBuffer direct channel failed " + id));
             }
+            type = SensorDirectChannel.TYPE_HARDWARE_BUFFER;
         } else {
-            throw new IllegalArgumentException("Invalid parameter");
+            throw new NullPointerException("shared memory object cannot be null");
         }
-
-        return ch;
+        return new SensorDirectChannel(this, id, type, size);
     }
 
     /** @hide */
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index e8e989f..f61032e 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -290,7 +290,8 @@
                         cameraId,
                         callback,
                         handler,
-                        characteristics);
+                        characteristics,
+                        mContext.getApplicationInfo().targetSdkVersion);
 
             ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
 
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index e75b375..ab87f15 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -36,6 +36,7 @@
 import android.hardware.camera2.utils.SubmitInfo;
 import android.hardware.camera2.utils.SurfaceUtils;
 import android.hardware.ICameraService;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -118,6 +119,8 @@
     private CameraCaptureSessionCore mCurrentSession;
     private int mNextSessionId = 0;
 
+    private final int mAppTargetSdkVersion;
+
     // Runnables for all state transitions, except error, which needs the
     // error code argument
 
@@ -234,7 +237,7 @@
     };
 
     public CameraDeviceImpl(String cameraId, StateCallback callback, Handler handler,
-                        CameraCharacteristics characteristics) {
+                        CameraCharacteristics characteristics, int appTargetSdkVersion) {
         if (cameraId == null || callback == null || handler == null || characteristics == null) {
             throw new IllegalArgumentException("Null argument given");
         }
@@ -242,6 +245,7 @@
         mDeviceCallback = callback;
         mDeviceHandler = handler;
         mCharacteristics = characteristics;
+        mAppTargetSdkVersion = appTargetSdkVersion;
 
         final int MAX_TAG_LEN = 23;
         String tag = String.format("CameraDevice-JV-%s", mCameraId);
@@ -671,6 +675,16 @@
         }
     }
 
+    private void overrideEnableZsl(CameraMetadataNative request, boolean newValue) {
+        Boolean enableZsl = request.get(CaptureRequest.CONTROL_ENABLE_ZSL);
+        if (enableZsl == null) {
+            // If enableZsl is not available, don't override.
+            return;
+        }
+
+        request.set(CaptureRequest.CONTROL_ENABLE_ZSL, newValue);
+    }
+
     @Override
     public CaptureRequest.Builder createCaptureRequest(int templateType)
             throws CameraAccessException {
@@ -681,6 +695,13 @@
 
             templatedRequest = mRemoteDevice.createDefaultRequest(templateType);
 
+            // If app target SDK is older than O, or it's not a still capture template, enableZsl
+            // must be false in the default request.
+            if (mAppTargetSdkVersion < Build.VERSION_CODES.O ||
+                    templateType != TEMPLATE_STILL_CAPTURE) {
+                overrideEnableZsl(templatedRequest, false);
+            }
+
             CaptureRequest.Builder builder = new CaptureRequest.Builder(
                     templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
 
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index a529c2f..3267172 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -247,6 +247,7 @@
      * </p>
      *
      * @see #createVirtualDisplay
+     * @hide
      */
     public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
 
diff --git a/core/java/android/hardware/radio/IRadioService.aidl b/core/java/android/hardware/radio/IRadioService.aidl
index 3c83114..90bb746 100644
--- a/core/java/android/hardware/radio/IRadioService.aidl
+++ b/core/java/android/hardware/radio/IRadioService.aidl
@@ -24,5 +24,5 @@
  * {@hide}
  */
 interface IRadioService {
-    ITuner openTuner();
+    ITuner openTuner(boolean withAudio);
 }
diff --git a/core/java/android/hardware/radio/ITuner.aidl b/core/java/android/hardware/radio/ITuner.aidl
index 73f6dc2..68257ff 100644
--- a/core/java/android/hardware/radio/ITuner.aidl
+++ b/core/java/android/hardware/radio/ITuner.aidl
@@ -20,5 +20,7 @@
 
 /** {@hide} */
 interface ITuner {
+    void close();
+
     int getProgramInformation(out RadioManager.ProgramInfo[] infoOut);
 }
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index 99412de..0ca868a 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -1448,10 +1448,14 @@
         if (mService != null) {
             ITuner tuner;
             try {
-                tuner = mService.openTuner();
+                tuner = mService.openTuner(withAudio);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
+            if (tuner == null) {
+                Log.e(TAG, "Failed to open tuner");
+                return null;
+            }
             return new TunerAdapter(tuner);
         }
 
diff --git a/core/java/android/hardware/radio/TunerAdapter.java b/core/java/android/hardware/radio/TunerAdapter.java
index 1822e07b..10bbf9f 100644
--- a/core/java/android/hardware/radio/TunerAdapter.java
+++ b/core/java/android/hardware/radio/TunerAdapter.java
@@ -31,6 +31,7 @@
     private static final String TAG = "radio.TunerAdapter";
 
     @NonNull private final ITuner mTuner;
+    private boolean mIsClosed = false;
 
     TunerAdapter(ITuner tuner) {
         if (tuner == null) {
@@ -41,8 +42,18 @@
 
     @Override
     public void close() {
-        // TODO(b/36863239): forward to mTuner
-        Log.w(TAG, "Close call not implemented");
+        synchronized (mTuner) {
+            if (mIsClosed) {
+                Log.d(TAG, "Tuner is already closed");
+                return;
+            }
+            mIsClosed = true;
+        }
+        try {
+            mTuner.close();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception trying to close tuner", e);
+        }
     }
 
     @Override
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 425a89d..1e98301 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -37,7 +37,7 @@
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about communicating with USB hardware, read the
- * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB</a> developer guide.</p>
  * </div>
  */
 public class UsbDevice implements Parcelable {
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
index 37ca4b4..af69f0f 100644
--- a/core/java/android/inputmethodservice/ExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -41,6 +41,6 @@
     @Override
     public void onFinishInflate() {
         super.onFinishInflate();
-        mExtractActionButton = (Button) findViewById(com.android.internal.R.id.inputExtractAction);
+        mExtractActionButton = findViewById(com.android.internal.R.id.inputExtractAction);
     }
 }
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index 0448221..3c6baa7 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -54,7 +54,11 @@
 
     /* Deserialize from the eventlog */
     public LogMaker(Object[] items) {
-      deserialize(items);
+        if (items != null) {
+            deserialize(items);
+        } else {
+            setCategory(MetricsEvent.VIEW_UNKNOWN);
+        }
     }
 
     /** @param category to replace the existing setting. */
@@ -94,6 +98,16 @@
     }
 
     /**
+     * Set event latency.
+     *
+     * @hide // TODO Expose in the future?  Too late for O.
+     */
+    public LogMaker setLatency(long milliseconds) {
+        entries.put(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, milliseconds);
+        return this;
+    }
+
+    /**
      * This will be set by the system when the log is persisted.
      * Client-supplied values will be ignored.
      *
@@ -363,13 +377,13 @@
      */
     public void deserialize(Object[] items) {
         int i = 0;
-        while (i < items.length) {
+        while (items != null && i < items.length) {
             Object key = items[i++];
             Object value = i < items.length ? items[i++] : null;
             if (key instanceof Integer) {
                 entries.put((Integer) key, value);
             } else {
-                Log.i(TAG, "Invalid key " + key.toString());
+                Log.i(TAG, "Invalid key " + (key == null ? "null" : key.toString()));
             }
         }
     }
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index d8768e7..5be977a 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -27,6 +27,7 @@
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Queue;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Read platform logs.
@@ -80,7 +81,7 @@
         mPendingQueue.clear();
         mSeenQueue.clear();
         for (Event event : nativeEvents) {
-            final long eventTimestampMs = event.getTimeNanos() / 1000000;
+            final long eventTimestampMs = event.getTimeMillis();
             Object data = event.getData();
             Object[] objects;
             if (data instanceof Object[]) {
@@ -152,24 +153,25 @@
      */
     @VisibleForTesting
     public static class Event {
-        long mTimeNanos;
+        long mTimeMillis;
         int mPid;
         Object mData;
 
-        public Event(long timeNanos, int pid, Object data) {
-            mTimeNanos = timeNanos;
+        public Event(long timeMillis, int pid, Object data) {
+            mTimeMillis = timeMillis;
             mPid = pid;
             mData = data;
         }
 
         Event(EventLog.Event nativeEvent) {
-            mTimeNanos = nativeEvent.getTimeNanos();
+            mTimeMillis = TimeUnit.MILLISECONDS.convert(
+                    nativeEvent.getTimeNanos(), TimeUnit.NANOSECONDS);
             mPid = nativeEvent.getProcessId();
             mData = nativeEvent.getData();
         }
 
-        public long getTimeNanos() {
-            return mTimeNanos;
+        public long getTimeMillis() {
+            return mTimeMillis;
         }
 
         public int getProcessId() {
@@ -196,7 +198,8 @@
                 throws IOException {
             // Testing in Android: the Static Final Class Strikes Back!
             ArrayList<EventLog.Event> nativeEvents = new ArrayList<>();
-            EventLog.readEventsOnWrapping(tags, horizonMs, nativeEvents);
+            long horizonNs = TimeUnit.NANOSECONDS.convert(horizonMs, TimeUnit.MILLISECONDS);
+            EventLog.readEventsOnWrapping(tags, horizonNs, nativeEvents);
             for (EventLog.Event nativeEvent : nativeEvents) {
                 Event event = new Event(nativeEvent);
                 events.add(event);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 111c50a..c93b933 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -15,8 +15,6 @@
  */
 package android.net;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
@@ -50,16 +48,18 @@
 
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.Protocol;
-import com.android.internal.util.MessageUtils;
 
 import libcore.net.event.NetworkEventDispatcher;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.net.InetAddress;
+import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Class that answers queries about the state of network connectivity. It also
@@ -1561,8 +1561,8 @@
         }
 
         private PacketKeepalive(Network network, PacketKeepaliveCallback callback) {
-            checkNotNull(network, "network cannot be null");
-            checkNotNull(callback, "callback cannot be null");
+            Preconditions.checkNotNull(network, "network cannot be null");
+            Preconditions.checkNotNull(callback, "callback cannot be null");
             mNetwork = network;
             mCallback = callback;
             HandlerThread thread = new HandlerThread(TAG);
@@ -1853,8 +1853,8 @@
      * {@hide}
      */
     public ConnectivityManager(Context context, IConnectivityManager service) {
-        mContext = checkNotNull(context, "missing context");
-        mService = checkNotNull(service, "missing IConnectivityManager");
+        mContext = Preconditions.checkNotNull(context, "missing context");
+        mService = Preconditions.checkNotNull(service, "missing IConnectivityManager");
         sInstance = this;
     }
 
@@ -2119,7 +2119,7 @@
     @SystemApi
     public void startTethering(int type, boolean showProvisioningUi,
             final OnStartTetheringCallback callback, Handler handler) {
-        checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
+        Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
 
         ResultReceiver wrappedCallback = new ResultReceiver(handler) {
             @Override
@@ -2581,8 +2581,16 @@
     }
 
     /**
-     * Base class for NetworkRequest callbacks.  Used for notifications about network
-     * changes.  Should be extended by applications wanting notifications.
+     * Base class for {@code NetworkRequest} callbacks. Used for notifications about network
+     * changes. Should be extended by applications wanting notifications.
+     *
+     * A {@code NetworkCallback} is registered by calling
+     * {@link #requestNetwork(NetworkRequest, NetworkCallback)},
+     * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)},
+     * or {@link #registerDefaultNetworkCallback(NetworkCallback). A {@code NetworkCallback} is
+     * unregistered by calling {@link #unregisterNetworkCallback(NetworkCallback)}.
+     * A {@code NetworkCallback} should be registered at most once at any time.
+     * A {@code NetworkCallback} that has been unregistered can be registered again.
      */
     public static class NetworkCallback {
         /**
@@ -2685,6 +2693,10 @@
         public void onNetworkResumed(Network network) {}
 
         private NetworkRequest networkRequest;
+
+        private boolean isRegistered() {
+            return (networkRequest != null) && (networkRequest.requestId != REQUEST_ID_UNSET);
+        }
     }
 
     private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER;
@@ -2702,6 +2714,7 @@
     public static final int CALLBACK_CAP_CHANGED         = BASE + 6;
     /** @hide */
     public static final int CALLBACK_IP_CHANGED          = BASE + 7;
+    // TODO: consider deleting CALLBACK_RELEASED and shifting following enum codes down by 1.
     /** @hide */
     public static final int CALLBACK_RELEASED            = BASE + 8;
     // TODO: consider deleting CALLBACK_EXIT and shifting following enum codes down by 1.
@@ -2751,46 +2764,46 @@
             NetworkRequest request = getObject(message, NetworkRequest.class);
             Network network = getObject(message, Network.class);
             if (DBG) {
-                Log.d(TAG, whatToString(message.what) + " for network " + network);
+                Log.d(TAG, getCallbackName(message.what) + " for network " + network);
             }
             switch (message.what) {
                 case CALLBACK_PRECHECK: {
-                    NetworkCallback callback = getCallback(request, "PRECHECK");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         callback.onPreCheck(network);
                     }
                     break;
                 }
                 case CALLBACK_AVAILABLE: {
-                    NetworkCallback callback = getCallback(request, "AVAILABLE");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         callback.onAvailable(network);
                     }
                     break;
                 }
                 case CALLBACK_LOSING: {
-                    NetworkCallback callback = getCallback(request, "LOSING");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         callback.onLosing(network, message.arg1);
                     }
                     break;
                 }
                 case CALLBACK_LOST: {
-                    NetworkCallback callback = getCallback(request, "LOST");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         callback.onLost(network);
                     }
                     break;
                 }
                 case CALLBACK_UNAVAIL: {
-                    NetworkCallback callback = getCallback(request, "UNAVAIL");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         callback.onUnavailable();
                     }
                     break;
                 }
                 case CALLBACK_CAP_CHANGED: {
-                    NetworkCallback callback = getCallback(request, "CAP_CHANGED");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
                         callback.onCapabilitiesChanged(network, cap);
@@ -2798,7 +2811,7 @@
                     break;
                 }
                 case CALLBACK_IP_CHANGED: {
-                    NetworkCallback callback = getCallback(request, "IP_CHANGED");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         LinkProperties lp = getObject(message, LinkProperties.class);
                         callback.onLinkPropertiesChanged(network, lp);
@@ -2806,27 +2819,20 @@
                     break;
                 }
                 case CALLBACK_SUSPENDED: {
-                    NetworkCallback callback = getCallback(request, "SUSPENDED");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         callback.onNetworkSuspended(network);
                     }
                     break;
                 }
                 case CALLBACK_RESUMED: {
-                    NetworkCallback callback = getCallback(request, "RESUMED");
+                    NetworkCallback callback = getCallback(message);
                     if (callback != null) {
                         callback.onNetworkResumed(network);
                     }
                     break;
                 }
                 case CALLBACK_RELEASED: {
-                    final NetworkCallback callback;
-                    synchronized(sCallbacks) {
-                        callback = sCallbacks.remove(request);
-                    }
-                    if (callback == null) {
-                        Log.e(TAG, "callback not found for RELEASED message");
-                    }
                     break;
                 }
                 case CALLBACK_EXIT: {
@@ -2843,13 +2849,14 @@
             return (T) msg.getData().getParcelable(c.getSimpleName());
         }
 
-        private NetworkCallback getCallback(NetworkRequest req, String name) {
-            NetworkCallback callback;
+        private NetworkCallback getCallback(Message msg) {
+            final NetworkRequest req = getObject(msg, NetworkRequest.class);
+            final NetworkCallback callback;
             synchronized(sCallbacks) {
                 callback = sCallbacks.get(req);
             }
             if (callback == null) {
-                Log.e(TAG, "callback not found for " + name + " message");
+                Log.w(TAG, "callback not found for " + getCallbackName(msg.what) + " message");
             }
             return callback;
         }
@@ -2872,17 +2879,16 @@
 
     private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
             int timeoutMs, int action, int legacyType, CallbackHandler handler) {
-        if (callback == null) {
-            throw new IllegalArgumentException("null NetworkCallback");
-        }
-        if (need == null && action != REQUEST) {
-            throw new IllegalArgumentException("null NetworkCapabilities");
-        }
-        // TODO: throw an exception if callback.networkRequest is not null.
-        // http://b/20701525
+        Preconditions.checkArgument(callback != null, "null NetworkCallback");
+        Preconditions.checkArgument(action == REQUEST || need != null, "null NetworkCapabilities");
         final NetworkRequest request;
         try {
             synchronized(sCallbacks) {
+                if (callback.isRegistered()) {
+                    // TODO: throw exception instead and enforce 1:1 mapping of callbacks
+                    // and requests (http://b/20701525).
+                    Log.e(TAG, "NetworkCallback was already registered");
+                }
                 Messenger messenger = new Messenger(handler);
                 Binder binder = new Binder();
                 if (action == LISTEN) {
@@ -3347,25 +3353,42 @@
     }
 
     /**
-     * Unregisters callbacks about and possibly releases networks originating from
+     * Unregisters a {@code NetworkCallback} and possibly releases networks originating from
      * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and
      * {@link #registerNetworkCallback(NetworkRequest, NetworkCallback)} calls.
      * If the given {@code NetworkCallback} had previously been used with
      * {@code #requestNetwork}, any networks that had been connected to only to satisfy that request
      * will be disconnected.
      *
+     * Notifications that would have triggered that {@code NetworkCallback} will immediately stop
+     * triggering it as soon as this call returns.
+     *
      * @param networkCallback The {@link NetworkCallback} used when making the request.
      */
     public void unregisterNetworkCallback(NetworkCallback networkCallback) {
-        if (networkCallback == null || networkCallback.networkRequest == null ||
-                networkCallback.networkRequest.requestId == REQUEST_ID_UNSET) {
-            throw new IllegalArgumentException("Invalid NetworkCallback");
-        }
-        try {
-            // CallbackHandler will release callback when receiving CALLBACK_RELEASED.
-            mService.releaseNetworkRequest(networkCallback.networkRequest);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        Preconditions.checkArgument(networkCallback != null, "null NetworkCallback");
+        final List<NetworkRequest> reqs = new ArrayList<>();
+        // Find all requests associated to this callback and stop callback triggers immediately.
+        // Callback is reusable immediately. http://b/20701525, http://b/35921499.
+        synchronized (sCallbacks) {
+            Preconditions.checkArgument(
+                    networkCallback.isRegistered(), "NetworkCallback was not registered");
+            for (Map.Entry<NetworkRequest, NetworkCallback> e : sCallbacks.entrySet()) {
+                if (e.getValue() == networkCallback) {
+                    reqs.add(e.getKey());
+                }
+            }
+            // TODO: throw exception if callback was registered more than once (http://b/20701525).
+            for (NetworkRequest r : reqs) {
+                try {
+                    mService.releaseNetworkRequest(r);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
+                }
+                // Only remove mapping if rpc was successful.
+                sCallbacks.remove(r);
+            }
+            networkCallback.networkRequest = null;
         }
     }
 
@@ -3723,32 +3746,4 @@
             throw e.rethrowFromSystemServer();
         }
     }
-
-    /**
-     * A holder class for debug info (mapping CALLBACK values to field names). This is stored
-     * in a holder for two reasons:
-     * 1) The reflection necessary to establish the map can't be run at compile-time. Thus, this
-     *    code will make the enclosing class not compile-time initializeable, deferring its
-     *    initialization to zygote startup. This leads to dirty (but shared) memory.
-     *    As this is debug info, use a holder that isn't initialized by default. This way the map
-     *    will be created on demand, while ConnectivityManager can be compile-time initialized.
-     * 2) Static initialization is still preferred for its strong thread safety guarantees without
-     *    requiring a lock.
-     */
-    private static class NoPreloadHolder {
-        public static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
-                new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"});
-    }
-
-    static {
-        // When debug is enabled, aggressively initialize the holder by touching the field (which
-        // will guarantee static initialization).
-        if (CallbackHandler.DBG) {
-            Object dummy = NoPreloadHolder.sMagicDecoderRing;
-        }
-    }
-
-    private static final String whatToString(int what) {
-        return NoPreloadHolder.sMagicDecoderRing.get(what, Integer.toString(what));
-    }
 }
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index 63ccaae..46bb346 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import com.android.internal.util.BitUtils;
 
 /**
  * Represents a core networking event defined in package android.net.metrics.
@@ -78,13 +79,15 @@
     public String toString() {
         StringBuilder buffer = new StringBuilder("ConnectivityMetricsEvent(");
         buffer.append(String.format("%tT.%tL", timestamp, timestamp));
-        // TODO: add transports
         if (netId != 0) {
             buffer.append(", ").append(netId);
         }
         if (ifname != null) {
             buffer.append(", ").append(ifname);
         }
+        for (int t : BitUtils.unpackBits(transports)) {
+            buffer.append(", ").append(NetworkCapabilities.transportNameOf(t));
+        }
         buffer.append("): ").append(data.toString());
         return buffer.toString();
     }
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index f8702e2..375b7ee 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -245,6 +245,7 @@
      *
      * @param socket a stream socket
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+     * @hide
      */
     public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
             throws IOException {
@@ -262,6 +263,7 @@
      *
      * @param socket a datagram socket
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+     * @hide
      */
     public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
             throws IOException {
@@ -284,7 +286,7 @@
      * address associated with that transform will throw an IOException. In addition, if the
      * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
      * send() or receive() until the transform is removed from the socket by calling {@link
-     * #removeTransportModeTransform(Socket, IpSecTransform)};
+     * #removeTransportModeTransform(FileDescriptor, IpSecTransform)};
      *
      * @param socket a socket file descriptor
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
@@ -316,8 +318,10 @@
      *
      * @param socket a socket that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
+     * @hide
      */
-    public void removeTransportModeTransform(Socket socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
     }
 
@@ -330,8 +334,10 @@
      *
      * @param socket a socket that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
+     * @hide
      */
-    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
     }
 
@@ -345,7 +351,8 @@
      * @param socket a socket file descriptor that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
      */
-    public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(new ParcelFileDescriptor(socket), transform);
     }
 
@@ -419,7 +426,7 @@
          *
          * @param fd a file descriptor previously returned as a UDP Encapsulation socket.
          */
-        public void close() {
+        public void close() throws IOException {
             // TODO: Go close the socket
             mCloseGuard.close();
         }
diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java
index 4409d0a..b4ef695 100644
--- a/core/java/android/net/NetworkBadging.java
+++ b/core/java/android/net/NetworkBadging.java
@@ -56,7 +56,7 @@
      *
      * @param signalLevel The level returned by {@link WifiManager#calculateSignalLevel(int, int)}
      *                    for a network. Must be between 0 and {@link WifiManager#RSSI_LEVELS}-1.
-     * @param badging  {@see ScoredNetwork#Badging}, retrieved from
+     * @param badging  {@see NetworkBadging#Badging}, retrieved from
      *                 {@link ScoredNetwork#calculateBadge(int)}.
      * @param theme The theme for the current application, may be null.
      * @return Drawable for the given icon
@@ -140,7 +140,7 @@
      * <p>This badge should be displayed with the badge signal resource retrieved from
      * {@link #getBadgedWifiSignalResource(int)}.
      *
-     * @param badging {@see ScoredNetwork#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
+     * @param badging {@see NetworkBadging#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
      * @return the @DrawableRes for the icon or {@link View#NO_ID} for
      *         {@link NetworkBadging#BADGING_NONE}
      * @throws IllegalArgumentException for an invalid badging value.
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index e0eac3d..bf7207c 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -18,7 +18,9 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.BitUtils;
 
 import java.util.Objects;
 
@@ -229,7 +231,8 @@
      * Capabilities that suggest that a network is restricted.
      * {@see #maybeMarkCapabilitiesRestricted}.
      */
-    private static final long RESTRICTED_CAPABILITIES =
+    @VisibleForTesting
+    /* package */ static final long RESTRICTED_CAPABILITIES =
             (1 << NET_CAPABILITY_CBS) |
             (1 << NET_CAPABILITY_DUN) |
             (1 << NET_CAPABILITY_EIMS) |
@@ -240,6 +243,17 @@
             (1 << NET_CAPABILITY_XCAP);
 
     /**
+     * Capabilities that suggest that a network is unrestricted.
+     * {@see #maybeMarkCapabilitiesRestricted}.
+     */
+    @VisibleForTesting
+    /* package */ static final long UNRESTRICTED_CAPABILITIES =
+            (1 << NET_CAPABILITY_INTERNET) |
+            (1 << NET_CAPABILITY_MMS) |
+            (1 << NET_CAPABILITY_SUPL) |
+            (1 << NET_CAPABILITY_WIFI_P2P);
+
+    /**
      * Adds the given capability to this {@code NetworkCapability} instance.
      * Multiple capabilities may be applied sequentially.  Note that when searching
      * for a network to satisfy a request, all capabilities requested must be satisfied.
@@ -279,7 +293,7 @@
      * @hide
      */
     public int[] getCapabilities() {
-        return enumerateBits(mNetworkCapabilities);
+        return BitUtils.unpackBits(mNetworkCapabilities);
     }
 
     /**
@@ -295,19 +309,6 @@
         return ((mNetworkCapabilities & (1 << capability)) != 0);
     }
 
-    private int[] enumerateBits(long val) {
-        int size = Long.bitCount(val);
-        int[] result = new int[size];
-        int index = 0;
-        int resource = 0;
-        while (val > 0) {
-            if ((val & 1) == 1) result[index++] = resource;
-            val = val >> 1;
-            resource++;
-        }
-        return result;
-    }
-
     private void combineNetCapabilities(NetworkCapabilities nc) {
         this.mNetworkCapabilities |= nc.mNetworkCapabilities;
     }
@@ -365,12 +366,16 @@
      * @hide
      */
     public void maybeMarkCapabilitiesRestricted() {
-        // If all the capabilities are typically provided by restricted networks, conclude that this
-        // network is restricted.
-        if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0 &&
-                // Must have at least some restricted capabilities, otherwise a request for an
-                // internet-less network will get marked restricted.
-                (mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0) {
+        // Verify there aren't any unrestricted capabilities.  If there are we say
+        // the whole thing is unrestricted.
+        final boolean hasUnrestrictedCapabilities =
+                ((mNetworkCapabilities & UNRESTRICTED_CAPABILITIES) != 0);
+
+        // Must have at least some restricted capabilities.
+        final boolean hasRestrictedCapabilities =
+                ((mNetworkCapabilities & RESTRICTED_CAPABILITIES) != 0);
+
+        if (hasRestrictedCapabilities && !hasUnrestrictedCapabilities) {
             removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
         }
     }
@@ -418,6 +423,15 @@
     /** @hide */
     public static final int MAX_TRANSPORT = TRANSPORT_WIFI_AWARE;
 
+    private static final String[] TRANSPORT_NAMES = {
+        "CELLULAR",
+        "WIFI",
+        "BLUETOOTH",
+        "ETHERNET",
+        "VPN",
+        "WIFI_AWARE"
+    };
+
     /**
      * Adds the given transport type to this {@code NetworkCapability} instance.
      * Multiple transports may be applied sequentially.  Note that when searching
@@ -464,18 +478,7 @@
      * @hide
      */
     public int[] getTransportTypes() {
-        return enumerateBits(mTransportTypes);
-    }
-
-    /**
-     * Gets all the transports set on this {@code NetworkCapability} instance.
-     *
-     * @return a bit field composed of up bits at indexes defined by
-     * {@code NetworkCapabilities.TRANSPORT_*} values for this instance.
-     * @hide
-     */
-    public long getTransports() {
-        return mTransportTypes;
+        return BitUtils.unpackBits(mTransportTypes);
     }
 
     /**
@@ -882,18 +885,23 @@
      * @hide
      */
     public static String transportNamesOf(int[] types) {
-        String transports = "";
-        for (int i = 0; i < types.length;) {
-            switch (types[i]) {
-                case TRANSPORT_CELLULAR:    transports += "CELLULAR"; break;
-                case TRANSPORT_WIFI:        transports += "WIFI"; break;
-                case TRANSPORT_BLUETOOTH:   transports += "BLUETOOTH"; break;
-                case TRANSPORT_ETHERNET:    transports += "ETHERNET"; break;
-                case TRANSPORT_VPN:         transports += "VPN"; break;
-                case TRANSPORT_WIFI_AWARE:  transports += "WIFI_AWARE"; break;
-            }
-            if (++i < types.length) transports += "|";
+        if (types == null || types.length == 0) {
+            return "";
         }
-        return transports;
+        StringBuilder transports = new StringBuilder();
+        for (int t : types) {
+            transports.append("|").append(transportNameOf(t));
+        }
+        return transports.substring(1);
+    }
+
+    /**
+     * @hide
+     */
+    public static String transportNameOf(int transport) {
+        if (transport < 0 || TRANSPORT_NAMES.length <= transport) {
+            return "UNKNOWN";
+        }
+        return TRANSPORT_NAMES[transport];
     }
 }
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index 271b0a7..af0459d 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -20,6 +20,19 @@
 
 /**
  * The base class for implementing a network recommendation provider.
+ * <p>
+ * A network recommendation provider is any application which:
+ * <ul>
+ * <li>Is granted the {@link permission#SCORE_NETWORKS} permission.
+ * <li>Includes a Service for the {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS} intent
+ *     which is protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE} permission.
+ * </ul>
+ * <p>
+ * Implementations are required to implement the abstract methods in this class and return the
+ * result of {@link #getBinder()} from the <code>onBind()</code> method in their Service.
+ * <p>
+ * The default network recommendation provider is controlled via the
+ * <code>config_defaultNetworkRecommendationProviderPackage</code> config key.
  * @hide
  */
 @SystemApi
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index a664a8b..666da0a 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -73,29 +73,6 @@
     /** A {@link NetworkKey} uniquely identifying this network. */
     public final NetworkKey networkKey;
 
-    // TODO(b/35323372): Delete these once external references are switched.
-    /** @deprecated Use {@link NetworkBadging#Badging} instead. */
-    @Deprecated
-    @IntDef({BADGING_NONE, BADGING_SD, BADGING_HD, BADGING_4K})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Badging {}
-
-    /** @deprecated Use {@link NetworkBadging#BADGING_NONE} instead. */
-    @Deprecated
-    public static final int BADGING_NONE = 0;
-
-    /** @deprecated Use {@link NetworkBadging#BADGING_SD} instead. */
-    @Deprecated
-    public static final int BADGING_SD = 10;
-
-    /** @deprecated Use {@link NetworkBadging#BADGING_HD} instead. */
-    @Deprecated
-    public static final int BADGING_HD = 20;
-
-    /** @deprecated Use {@link NetworkBadging#BADGING_4K} instead. */
-    @Deprecated
-    public static final int BADGING_4K = 30;
-
     /**
      * The {@link RssiCurve} representing the scores for this network based on the RSSI.
      *
diff --git a/core/java/android/net/metrics/ConnectStats.java b/core/java/android/net/metrics/ConnectStats.java
index 214edee..30b2656 100644
--- a/core/java/android/net/metrics/ConnectStats.java
+++ b/core/java/android/net/metrics/ConnectStats.java
@@ -16,53 +16,47 @@
 
 package android.net.metrics;
 
+import android.net.NetworkCapabilities;
 import android.system.OsConstants;
 import android.util.IntArray;
 import android.util.SparseIntArray;
+import com.android.internal.util.BitUtils;
 import com.android.internal.util.TokenBucket;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.ConnectStatistics;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.Pair;
 
 /**
- * A class that aggregates connect() statistics and helps build
- * IpConnectivityLogClass.ConnectStatistics instances.
- *
+ * A class that aggregates connect() statistics.
  * {@hide}
  */
 public class ConnectStats {
     private final static int EALREADY     = OsConstants.EALREADY;
     private final static int EINPROGRESS  = OsConstants.EINPROGRESS;
 
+    /** Network id of the network associated with the event, or 0 if unspecified. */
+    public final int netId;
+    /** Transports of the network associated with the event, as defined in NetworkCapabilities. */
+    public final long transports;
     /** How many events resulted in a given errno. */
-    private final SparseIntArray mErrnos = new SparseIntArray();
-    /** Latencies of blocking connects. TODO: add non-blocking connects latencies. */
-    private final IntArray mLatencies = new IntArray();
+    public final SparseIntArray errnos = new SparseIntArray();
+    /** Latencies of successful blocking connects. TODO: add non-blocking connects latencies. */
+    public final IntArray latencies = new IntArray();
     /** TokenBucket for rate limiting latency recording. */
-    private final TokenBucket mLatencyTb;
+    public final TokenBucket mLatencyTb;
     /** Maximum number of latency values recorded. */
-    private final int mMaxLatencyRecords;
+    public final int mMaxLatencyRecords;
     /** Total count of successful connects. */
-    private int mConnectCount = 0;
+    public int connectCount = 0;
     /** Total count of successful connects done in blocking mode. */
-    private int mConnectBlockingCount = 0;
+    public int connectBlockingCount = 0;
     /** Total count of successful connects with IPv6 socket address. */
-    private int mIpv6ConnectCount = 0;
+    public int ipv6ConnectCount = 0;
 
-    public ConnectStats(TokenBucket tb, int maxLatencyRecords) {
+    public ConnectStats(int netId, long transports, TokenBucket tb, int maxLatencyRecords) {
+        this.netId = netId;
+        this.transports = transports;
         mLatencyTb = tb;
         mMaxLatencyRecords = maxLatencyRecords;
     }
 
-    public ConnectStatistics toProto() {
-        ConnectStatistics stats = new ConnectStatistics();
-        stats.connectCount = mConnectCount;
-        stats.connectBlockingCount = mConnectBlockingCount;
-        stats.ipv6AddrCount = mIpv6ConnectCount;
-        stats.latenciesMs = mLatencies.toArray();
-        stats.errnosCounters = toPairArrays(mErrnos);
-        return stats;
-    }
-
     public void addEvent(int errno, int latencyMs, String ipAddr) {
         if (isSuccess(errno)) {
             countConnect(errno, ipAddr);
@@ -73,12 +67,12 @@
     }
 
     private void countConnect(int errno, String ipAddr) {
-        mConnectCount++;
+        connectCount++;
         if (!isNonBlocking(errno)) {
-            mConnectBlockingCount++;
+            connectBlockingCount++;
         }
         if (isIPv6(ipAddr)) {
-            mIpv6ConnectCount++;
+            ipv6ConnectCount++;
         }
     }
 
@@ -91,16 +85,16 @@
             // Rate limited
             return;
         }
-        if (mLatencies.size() >= mMaxLatencyRecords) {
+        if (latencies.size() >= mMaxLatencyRecords) {
             // Hard limit the total number of latency measurements.
             return;
         }
-        mLatencies.add(ms);
+        latencies.add(ms);
     }
 
     private void countError(int errno) {
-        final int newcount = mErrnos.get(errno, 0) + 1;
-        mErrnos.put(errno, newcount);
+        final int newcount = errnos.get(errno, 0) + 1;
+        errnos.put(errno, newcount);
     }
 
     private static boolean isSuccess(int errno) {
@@ -117,27 +111,18 @@
         return ipAddr.contains(":");
     }
 
-    private static Pair[] toPairArrays(SparseIntArray counts) {
-        final int s = counts.size();
-        Pair[] pairs = new Pair[s];
-        for (int i = 0; i < s; i++) {
-            Pair p = new Pair();
-            p.key = counts.keyAt(i);
-            p.value = counts.valueAt(i);
-            pairs[i] = p;
-        }
-        return pairs;
-    }
-
     @Override
     public String toString() {
-        StringBuilder builder = new StringBuilder("ConnectStats(")
-                .append(String.format("%d success, ", mConnectCount))
-                .append(String.format("%d blocking, ", mConnectBlockingCount))
-                .append(String.format("%d IPv6 dst", mIpv6ConnectCount));
-        for (int i = 0; i < mErrnos.size(); i++) {
-            String errno = OsConstants.errnoName(mErrnos.keyAt(i));
-            int count = mErrnos.valueAt(i);
+        StringBuilder builder = new StringBuilder("ConnectStats(").append(netId).append(", ");
+        for (int t : BitUtils.unpackBits(transports)) {
+            builder.append(NetworkCapabilities.transportNameOf(t)).append(", ");
+        }
+        builder.append(String.format("%d success, ", connectCount));
+        builder.append(String.format("%d blocking, ", connectBlockingCount));
+        builder.append(String.format("%d IPv6 dst", ipv6ConnectCount));
+        for (int i = 0; i < errnos.size(); i++) {
+            String errno = OsConstants.errnoName(errnos.keyAt(i));
+            int count = errnos.valueAt(i);
             builder.append(String.format(", %s: %d", errno, count));
         }
         return builder.append(")").toString();
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index 89ae1c2..a4970e4 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -16,67 +16,70 @@
 
 package android.net.metrics;
 
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.net.NetworkCapabilities;
+import java.util.Arrays;
+import com.android.internal.util.BitUtils;
 
 /**
  * A DNS event recorded by NetdEventListenerService.
  * {@hide}
  */
-final public class DnsEvent implements Parcelable {
-    public final int netId;
+final public class DnsEvent {
 
-    // The event type is currently only 1 or 2, so we store it as a byte.
-    public final byte[] eventTypes;
+    private static final int SIZE_LIMIT = 20000;
+
+    // Network id of the network associated with the event, or 0 if unspecified.
+    public final int netId;
+    // Transports of the network associated with the event, as defined in NetworkCapabilities.
+    // It is the caller responsability to ensure the value of transports does not change between
+    // calls to addResult.
+    public final long transports;
+    // The number of DNS queries recorded. Queries are stored in the structure-of-array style where
+    // the eventTypes, returnCodes, and latenciesMs arrays have the same length and the i-th event
+    // is spread across the three array at position i.
+    public int eventCount;
+    // The types of DNS queries as defined in INetdEventListener.
+    public byte[] eventTypes;
     // Current getaddrinfo codes go from 1 to EAI_MAX = 15. gethostbyname returns errno, but there
     // are fewer than 255 errno values. So we store the result code in a byte as well.
-    public final byte[] returnCodes;
-    // The latency is an integer because a) short arrays aren't parcelable and b) a short can only
-    // store a maximum latency of 32757 or 65535 ms, which is too short for pathologically slow
-    // queries.
-    public final int[] latenciesMs;
+    public byte[] returnCodes;
+    // Latencies in milliseconds of queries, stored as ints.
+    public int[] latenciesMs;
 
-    public DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
+    public DnsEvent(int netId, long transports, int initialCapacity) {
         this.netId = netId;
-        this.eventTypes = eventTypes;
-        this.returnCodes = returnCodes;
-        this.latenciesMs = latenciesMs;
+        this.transports = transports;
+        eventTypes = new byte[initialCapacity];
+        returnCodes = new byte[initialCapacity];
+        latenciesMs = new int[initialCapacity];
     }
 
-    private DnsEvent(Parcel in) {
-        this.netId = in.readInt();
-        this.eventTypes = in.createByteArray();
-        this.returnCodes = in.createByteArray();
-        this.latenciesMs = in.createIntArray();
+    public void addResult(byte eventType, byte returnCode, int latencyMs) {
+        if (eventCount >= SIZE_LIMIT) {
+            // TODO: implement better rate limiting that does not biases metrics.
+            return;
+        }
+        if (eventCount == eventTypes.length) {
+            resize((int) (1.4 * eventCount));
+        }
+        eventTypes[eventCount] = eventType;
+        returnCodes[eventCount] = returnCode;
+        latenciesMs[eventCount] = latencyMs;
+        eventCount++;
     }
 
-    @Override
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(netId);
-        out.writeByteArray(eventTypes);
-        out.writeByteArray(returnCodes);
-        out.writeIntArray(latenciesMs);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
+    public void resize(int newLength) {
+        eventTypes = Arrays.copyOf(eventTypes, newLength);
+        returnCodes = Arrays.copyOf(returnCodes, newLength);
+        latenciesMs = Arrays.copyOf(latenciesMs, newLength);
     }
 
     @Override
     public String toString() {
-        return String.format("DnsEvent(%d, %d events)", netId, eventTypes.length);
+        StringBuilder builder = new StringBuilder("DnsEvent(").append(netId).append(", ");
+        for (int t : BitUtils.unpackBits(transports)) {
+            builder.append(NetworkCapabilities.transportNameOf(t)).append(", ");
+        }
+        return builder.append(eventCount).append(" events)").toString();
     }
-
-    public static final Parcelable.Creator<DnsEvent> CREATOR = new Parcelable.Creator<DnsEvent>() {
-        @Override
-        public DnsEvent createFromParcel(Parcel in) {
-            return new DnsEvent(in);
-        }
-
-        @Override
-        public DnsEvent[] newArray(int size) {
-            return new DnsEvent[size];
-        }
-    };
 }
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index ac727ca..4e57efa 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -23,6 +23,7 @@
 import android.os.ServiceManager;
 import android.util.Log;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.BitUtils;
 
 /**
  * Class for logging IpConnectvity events with IpConnectivityMetrics
@@ -117,10 +118,10 @@
      * @param data is a Parcelable instance representing the event.
      * @return true if the event was successfully logged.
      */
-    public boolean log(int netid, long transports, Parcelable data) {
+    public boolean log(int netid, int[] transports, Parcelable data) {
         ConnectivityMetricsEvent ev = makeEv(data);
         ev.netId = netid;
-        ev.transports = transports;
+        ev.transports = BitUtils.packBits(transports);
         return log(ev);
     }
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4c6d22a..832031e 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -182,7 +182,7 @@
      * New in version 19:
      *   - Wakelock data (wl) gets current and max times.
      * New in version 20:
-     *   - Background timers and counters for: Sensor, BluetoothScan, WifiScan, Jobs.
+     *   - Background timers and counters for: Sensor, BluetoothScan, WifiScan, Jobs, Syncs.
      */
     static final String CHECKIN_VERSION = "20";
 
@@ -594,11 +594,6 @@
         public abstract long getSystemCpuTimeUs(int which);
 
         /**
-         * Get the total cpu power consumed (in milli-ampere-microseconds).
-         */
-        public abstract long getCpuPowerMaUs(int which);
-
-        /**
          * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed for a
          * given CPU cluster.
          * @param cluster the index of the CPU cluster.
@@ -3392,9 +3387,13 @@
                 // Convert from microseconds to milliseconds with rounding
                 final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 final int count = timer.getCountLocked(which);
+                final Timer bgTimer = timer.getSubTimer();
+                final long bgTime = bgTimer != null ?
+                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, SYNC_DATA, "\"" + syncs.keyAt(isy) + "\"",
-                            totalTime, count);
+                            totalTime, count, bgTime, bgCount);
                 }
             }
 
@@ -3467,10 +3466,9 @@
 
             final long userCpuTimeUs = u.getUserCpuTimeUs(which);
             final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
-            final long powerCpuMaUs = u.getCpuPowerMaUs(which);
-            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
+            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
                 dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000,
-                        powerCpuMaUs / 1000);
+                        0 /* old cpu power, keep for compatibility */);
             }
 
             final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
@@ -4608,6 +4606,10 @@
                 // Convert from microseconds to milliseconds with rounding
                 final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 final int count = timer.getCountLocked(which);
+                final Timer bgTimer = timer.getSubTimer();
+                final long bgTime = bgTimer != null ?
+                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 sb.setLength(0);
                 sb.append(prefix);
                 sb.append("    Sync ");
@@ -4618,6 +4620,13 @@
                     sb.append("realtime (");
                     sb.append(count);
                     sb.append(" times)");
+                    if (bgTime > 0) {
+                        sb.append(", ");
+                        formatTimeMs(sb, bgTime);
+                        sb.append("background (");
+                        sb.append(bgCount);
+                        sb.append(" times)");
+                    }
                 } else {
                     sb.append("(not used)");
                 }
@@ -4758,17 +4767,13 @@
 
             final long userCpuTimeUs = u.getUserCpuTimeUs(which);
             final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
-            final long powerCpuMaUs = u.getCpuPowerMaUs(which);
-            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
+            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
                 sb.setLength(0);
                 sb.append(prefix);
                 sb.append("    Total cpu time: u=");
                 formatTimeMs(sb, userCpuTimeUs / 1000);
                 sb.append("s=");
                 formatTimeMs(sb, systemCpuTimeUs / 1000);
-                sb.append("p=");
-                printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0));
-                sb.append("mAh");
                 pw.println(sb.toString());
             }
 
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 15bd175..ff0bc69 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -16,9 +16,15 @@
 
 package android.os;
 
+import android.util.ExceptionUtils;
 import android.util.Log;
 import android.util.Slog;
+
 import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.FunctionalUtils;
+import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
+import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
+
 import libcore.io.IoUtils;
 
 import java.io.FileDescriptor;
@@ -26,7 +32,6 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Modifier;
-import java.util.function.Supplier;
 
 /**
  * Base class for a remotable object, the core part of a lightweight
@@ -251,14 +256,23 @@
      * Convenience method for running the provided action enclosed in
      * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity}
      *
+     * Any exception thrown by the given action will be caught and rethrown after the call to
+     * {@link #restoreCallingIdentity}
+     *
      * @hide
      */
-    public static final void withCleanCallingIdentity(Runnable action) {
+    public static final void withCleanCallingIdentity(ThrowingRunnable action) {
         long callingIdentity = clearCallingIdentity();
+        Throwable throwableToPropagate = null;
         try {
             action.run();
+        } catch (Throwable throwable) {
+            throwableToPropagate = throwable;
         } finally {
             restoreCallingIdentity(callingIdentity);
+            if (throwableToPropagate != null) {
+                throw ExceptionUtils.propagate(throwableToPropagate);
+            }
         }
     }
 
@@ -266,14 +280,24 @@
      * Convenience method for running the provided action enclosed in
      * {@link #clearCallingIdentity}/{@link #restoreCallingIdentity} returning the result
      *
+     * Any exception thrown by the given action will be caught and rethrown after the call to
+     * {@link #restoreCallingIdentity}
+     *
      * @hide
      */
-    public static final <T> T withCleanCallingIdentity(Supplier<T> action) {
+    public static final <T> T withCleanCallingIdentity(ThrowingSupplier<T> action) {
         long callingIdentity = clearCallingIdentity();
+        Throwable throwableToPropagate = null;
         try {
             return action.get();
+        } catch (Throwable throwable) {
+            throwableToPropagate = throwable;
+            return null; // overridden by throwing in finally block
         } finally {
             restoreCallingIdentity(callingIdentity);
+            if (throwableToPropagate != null) {
+                throw ExceptionUtils.propagate(throwableToPropagate);
+            }
         }
     }
 
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 9b5ff29..167c46d 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -25,6 +25,7 @@
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.UUID;
 
 /**
  * A mapping from String keys to various {@link Parcelable} values.
@@ -476,6 +477,18 @@
     }
 
     /**
+     * Inserts a UUID value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a UUID object, or null
+     */
+    public void putUuid(@Nullable String key, @Nullable UUID value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
      * Inserts an array of Parcelable values into the mapping of this Bundle,
      * replacing any existing value for the given key.  Either key or value may
      * be null.
@@ -858,6 +871,26 @@
      * value is explicitly associated with the key.
      *
      * @param key a String, or null
+     * @return a UUID value, or null
+     */
+    @Nullable
+    public UUID getUuid(@Nullable String key) {
+        unparcel();
+        final Object o = mMap.get(key);
+        try {
+            return (UUID) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "UUID", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
      * @return a Bundle value, or null
      */
     @Nullable
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index c3836a3..c1647c7 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -16,8 +16,6 @@
 
 package android.os;
 
-import android.annotation.IntegerRes;
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -29,6 +27,9 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
+import dalvik.annotation.optimization.FastNative;
+import dalvik.system.VMRuntime;
+
 import libcore.util.SneakyThrow;
 
 import java.io.ByteArrayInputStream;
@@ -49,9 +50,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
-import dalvik.annotation.optimization.FastNative;
-import dalvik.system.VMRuntime;
+import java.util.UUID;
 
 /**
  * Container for a message (data and object references) that can
@@ -243,6 +242,7 @@
     private static final int VAL_SIZE = 26;
     private static final int VAL_SIZEF = 27;
     private static final int VAL_DOUBLEARRAY = 28;
+    private static final int VAL_UUID = 29;
 
     // The initial int32 in a Binder call's reply Parcel header:
     // Keep these in sync with libbinder's binder/Status.h.
@@ -831,6 +831,15 @@
     }
 
     /**
+     * Flatten a UUID into the parcel at the current dataPosition(),
+     * growing dataCapacity() if needed.
+     */
+    public final void writeUuid(UUID val) {
+        writeLong(val.getMostSignificantBits());
+        writeLong(val.getLeastSignificantBits());
+    }
+
+    /**
      * Flatten a List into the parcel at the current dataPosition(), growing
      * dataCapacity() if needed.  The List values are written using
      * {@link #writeValue} and must follow the specification there.
@@ -1678,6 +1687,9 @@
         } else if (v instanceof double[]) {
             writeInt(VAL_DOUBLEARRAY);
             writeDoubleArray((double[]) v);
+        } else if (v instanceof UUID) {
+            writeInt(VAL_UUID);
+            writeUuid((UUID) v);
         } else {
             Class<?> clazz = v.getClass();
             if (clazz.isArray() && clazz.getComponentType() == Object.class) {
@@ -2182,6 +2194,13 @@
     }
 
     /**
+     * Read a UUID from the parcel at the current dataPosition().
+     */
+    public final UUID readUuid() {
+        return new UUID(readLong(), readLong());
+    }
+
+    /**
      * Read and return a byte[] object from the parcel.
      */
     public final byte[] createByteArray() {
@@ -2731,6 +2750,9 @@
         case VAL_DOUBLEARRAY:
             return createDoubleArray();
 
+        case VAL_UUID:
+            return readUuid();
+
         default:
             int off = dataPosition() - 4;
             throw new RuntimeException(
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 5f66abd..447f280 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import android.annotation.SystemApi;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -24,9 +26,12 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import libcore.io.Streams;
+
 import java.io.ByteArrayInputStream;
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.FileWriter;
@@ -39,6 +44,7 @@
 import java.security.SignatureException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -46,6 +52,7 @@
 import java.util.Locale;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
 
 import com.android.internal.logging.MetricsLogger;
 
@@ -317,6 +324,70 @@
         } finally {
             raf.close();
         }
+
+        // Additionally verify the package compatibility.
+        if (!readAndVerifyPackageCompatibilityEntry(packageFile)) {
+            throw new SignatureException("package compatibility verification failed");
+        }
+    }
+
+    /**
+     * Verifies the compatibility entry from an {@link InputStream}.
+     *
+     * @return the verification result.
+     */
+    private static boolean verifyPackageCompatibility(InputStream inputStream) throws IOException {
+        ArrayList<String> list = new ArrayList<>();
+        ZipInputStream zis = new ZipInputStream(inputStream);
+        ZipEntry entry;
+        while ((entry = zis.getNextEntry()) != null) {
+            long entrySize = entry.getSize();
+            if (entrySize > Integer.MAX_VALUE || entrySize < 0) {
+                throw new IOException(
+                        "invalid entry size (" + entrySize + ") in the compatibility file");
+            }
+            byte[] bytes = new byte[(int) entrySize];
+            Streams.readFully(zis, bytes);
+            list.add(new String(bytes, UTF_8));
+        }
+        if (list.isEmpty()) {
+            throw new IOException("no entries found in the compatibility file");
+        }
+        return (VintfObject.verify(list.toArray(new String[list.size()])) == 0);
+    }
+
+    /**
+     * Reads and verifies the compatibility entry in an OTA zip package. The compatibility entry is
+     * a zip file (inside the OTA package zip).
+     *
+     * @return {@code true} if the entry doesn't exist or verification passes.
+     */
+    private static boolean readAndVerifyPackageCompatibilityEntry(File packageFile)
+            throws IOException {
+        try (ZipFile zip = new ZipFile(packageFile)) {
+            ZipEntry entry = zip.getEntry("compatibility.zip");
+            if (entry == null) {
+                return true;
+            }
+            InputStream inputStream = zip.getInputStream(entry);
+            return verifyPackageCompatibility(inputStream);
+        }
+    }
+
+    /**
+     * Verifies the package compatibility info against the current system.
+     *
+     * @param compatibilityFile the {@link File} that contains the package compatibility info.
+     * @throws IOException if there were any errors reading the compatibility file.
+     * @return the compatibility verification result.
+     *
+     * {@hide}
+     */
+    @SystemApi
+    public static boolean verifyPackageCompatibility(File compatibilityFile) throws IOException {
+        try (InputStream inputStream = new FileInputStream(compatibilityFile)) {
+            return verifyPackageCompatibility(inputStream);
+        }
     }
 
     /**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 526c2ce..b5382d9 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -699,8 +699,10 @@
      * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
      * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
      * @see #getUserRestrictions()
+     * @deprecated use {@link OemLockManager#setOemUnlockAllowedByCarrier(boolean, byte[])} instead.
      * @hide
      */
+    @Deprecated
     @SystemApi
     public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
 
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
new file mode 100644
index 0000000..1ef3916
--- /dev/null
+++ b/core/java/android/os/VintfObject.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.util.ArrayList;
+
+import android.util.Log;
+
+/** @hide */
+public class VintfObject {
+
+    private static final String LOG_TAG = "VintfObject";
+
+    /**
+     * Slurps all device information (both manifests)
+     * and report it.
+     * If any error in getting one of the manifests, it is not included in
+     * the list.
+     */
+    public static String[] report() {
+        ArrayList<String> ret = new ArrayList<>();
+        put(ret, getDeviceManifest(), "device manifest");
+        put(ret, getFrameworkManifest(), "framework manifest");
+        return ret.toArray(new String[0]);
+    }
+
+    /**
+     * Verify that the given metadata for an OTA package is compatible with
+     * this device.
+     *
+     * @param packageInfo a list of serialized form of HalMaanifest's /
+     * CompatibilityMatri'ces (XML).
+     * @return = 0 if success (compatible)
+     *         > 0 if incompatible
+     *         < 0 if any error (mount partition fails, illformed XML, etc.)
+     */
+    public static native int verify(String[] packageInfo);
+
+    // return null if any error, otherwise XML string.
+    private static native String getDeviceManifest();
+    private static native String getFrameworkManifest();
+
+    private static void put(ArrayList<String> list, String content, String message) {
+        if (content == null || content.length() == 0) {
+            Log.e(LOG_TAG, "Cannot get;" + message + "; check native logs for details.");
+            return;
+        }
+        list.add(content);
+    }
+}
diff --git a/core/java/android/os/health/UidHealthStats.java b/core/java/android/os/health/UidHealthStats.java
index a702cdb..afc9d78 100644
--- a/core/java/android/os/health/UidHealthStats.java
+++ b/core/java/android/os/health/UidHealthStats.java
@@ -445,7 +445,10 @@
 
     /**
      * An estimate of the number of milliamp-microsends used by this uid.
+     *
+     * @deprecated this measurement is vendor-dependent and not reliable.
      */
+    @Deprecated
     @HealthKeys.Constant(type=HealthKeys.TYPE_MEASUREMENT)
     public static final int MEASUREMENT_CPU_POWER_MAMS = HealthKeys.BASE_UID + 64;
 
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index b5af766..3942531 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -66,6 +66,7 @@
 
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -77,6 +78,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
+import java.util.UUID;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -117,19 +119,66 @@
     public static final String UUID_PRIVATE_INTERNAL = null;
     /** {@hide} */
     public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
+    /** {@hide} */
+    public static final String UUID_SYSTEM = "system";
 
+    // NOTE: UUID constants below are namespaced
+    // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad default
+    // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad primary_physical
+    // uuid -v5 ad99aa3d-308e-4191-a200-ebcab371c0ad system
 
     /**
-     * Activity Action: Allows the user to manage their storage. This activity provides the ability
-     * to free up space on the device by deleting data such as apps.
+     * UUID representing the default internal storage of this device which
+     * provides {@link Environment#getDataDirectory()}.
      * <p>
-     * Input: Nothing.
+     * This value is constant across all devices and it will never change, and
+     * thus it cannot be used to uniquely identify a particular physical device.
+     *
+     * @see #getUuidForPath(File)
+     */
+    public static final UUID UUID_DEFAULT = UUID
+            .fromString("41217664-9172-527a-b3d5-edabb50a7d69");
+
+    /** {@hide} */
+    public static final UUID UUID_PRIMARY_PHYSICAL_ = UUID
+            .fromString("0f95a519-dae7-5abf-9519-fbd6209e05fd");
+
+    /** {@hide} */
+    public static final UUID UUID_SYSTEM_ = UUID
+            .fromString("5d258386-e60d-59e3-826d-0089cdd42cc0");
+
+    /**
+     * Activity Action: Allows the user to manage their storage. This activity
+     * provides the ability to free up space on the device by deleting data such
+     * as apps.
      * <p>
-     * Output: Nothing.
+     * If the sending application has a specific storage device or allocation
+     * size in mind, they can optionally define {@link #EXTRA_UUID} or
+     * {@link #EXTRA_REQUESTED_BYTES}, respectively.
      */
     @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_MANAGE_STORAGE
-            = "android.os.storage.action.MANAGE_STORAGE";
+    public static final String ACTION_MANAGE_STORAGE = "android.os.storage.action.MANAGE_STORAGE";
+
+    /**
+     * Extra {@link UUID} used to indicate the storage volume where an
+     * application is interested in allocating or managing disk space.
+     *
+     * @see #ACTION_MANAGE_STORAGE
+     * @see #UUID_DEFAULT
+     * @see #getUuidForPath(File)
+     */
+    public static final String EXTRA_UUID = "android.os.storage.extra.UUID";
+
+    /**
+     * Extra used to indicate the total size (in bytes) that an application is
+     * interested in allocating.
+     * <p>
+     * When defined, the management UI will help guide the user to free up
+     * enough disk space to reach this requested value.
+     *
+     * @see #ACTION_MANAGE_STORAGE
+     */
+    public static final String EXTRA_REQUESTED_BYTES = "android.os.storage.extra.REQUESTED_BYTES";
 
     /** {@hide} */
     public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
@@ -668,34 +717,44 @@
         }
     }
 
-    /** {@hide} */
-    public @Nullable String findUuidForPath(File path) {
+    /**
+     * Return a UUID identifying the storage volume that hosts the given
+     * filesystem path.
+     * <p>
+     * If this path is hosted by the default internal storage of the device at
+     * {@link Environment#getDataDirectory()}, the returned value will be
+     * {@link #UUID_DEFAULT}.
+     *
+     * @throws IOException when the storage device at the given path isn't
+     *             present, or when it doesn't have a valid UUID.
+     */
+    public @NonNull UUID getUuidForPath(@NonNull File path) throws IOException {
         Preconditions.checkNotNull(path);
         final String pathString = path.getAbsolutePath();
         if (FileUtils.contains(Environment.getDataDirectory().getAbsolutePath(), pathString)) {
-            return StorageManager.UUID_PRIVATE_INTERNAL;
+            return UUID_DEFAULT;
         }
         try {
             for (VolumeInfo vol : mStorageManager.getVolumes(0)) {
                 if (vol.path != null && FileUtils.contains(vol.path, pathString)) {
                     // TODO: verify that emulated adopted devices have UUID of
                     // underlying volume
-                    return vol.fsUuid;
+                    return convert(vol.fsUuid);
                 }
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-        throw new IllegalStateException("Failed to find a storage device for " + path);
+        throw new FileNotFoundException("Failed to find a storage device for " + path);
     }
 
     /** {@hide} */
-    public @Nullable File findPathForUuid(String volumeUuid) {
+    public @NonNull File findPathForUuid(String volumeUuid) throws FileNotFoundException {
         final VolumeInfo vol = findVolumeByQualifiedUuid(volumeUuid);
         if (vol != null) {
             return vol.getPath();
         }
-        throw new IllegalStateException("Failed to find a storage device for " + volumeUuid);
+        throw new FileNotFoundException("Failed to find a storage device for " + volumeUuid);
     }
 
     /** {@hide} */
@@ -1451,7 +1510,7 @@
 
     /**
      * Return quota size in bytes for all cached data belonging to the calling
-     * app on the filesystem that hosts the given path.
+     * app on the given storage volume.
      * <p>
      * If your app goes above this quota, your cached files will be some of the
      * first to be deleted when additional disk space is needed. Conversely, if
@@ -1466,21 +1525,34 @@
      * as a single unit.
      * </p>
      *
-     * @see #getCacheSizeBytes(File)
+     * @param storageUuid the UUID of the storage volume that you're interested
+     *            in. The UUID for a specific path can be obtained using
+     *            {@link #getUuidForPath(File)}.
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support cache quotas.
+     * @see #getCacheSizeBytes(UUID)
      */
-    public long getCacheQuotaBytes(File path) {
+    public long getCacheQuotaBytes(@NonNull UUID storageUuid) throws IOException {
         try {
-            final String volumeUuid = findUuidForPath(path);
             final ApplicationInfo app = mContext.getApplicationInfo();
-            return mStorageManager.getCacheQuotaBytes(volumeUuid, app.uid);
+            return mStorageManager.getCacheQuotaBytes(convert(storageUuid), app.uid);
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public long getCacheQuotaBytes(@NonNull File path) throws IOException {
+        return getCacheQuotaBytes(getUuidForPath(path));
+    }
+
     /**
      * Return total size in bytes of all cached data belonging to the calling
-     * app on the filesystem that hosts the given path.
+     * app on the given storage volume.
      * <p>
      * Cached data tracked by this method always includes
      * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and
@@ -1493,13 +1565,20 @@
      * as a single unit.
      * </p>
      *
-     * @see #getCacheQuotaBytes()
+     * @param storageUuid the UUID of the storage volume that you're interested
+     *            in. The UUID for a specific path can be obtained using
+     *            {@link #getUuidForPath(File)}.
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support cache quotas.
+     * @see #getCacheQuotaBytes(UUID)
      */
-    public long getCacheSizeBytes(File path) {
+    public long getCacheSizeBytes(@NonNull UUID storageUuid) throws IOException {
         try {
-            final String volumeUuid = findUuidForPath(path);
             final ApplicationInfo app = mContext.getApplicationInfo();
-            return mStorageManager.getCacheSizeBytes(volumeUuid, app.uid);
+            return mStorageManager.getCacheSizeBytes(convert(storageUuid), app.uid);
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1507,25 +1586,31 @@
 
     /** @removed */
     @Deprecated
-    public long getCacheQuotaBytes() {
+    public long getCacheSizeBytes(@NonNull File path) throws IOException {
+        return getCacheSizeBytes(getUuidForPath(path));
+    }
+
+    /** @removed */
+    @Deprecated
+    public long getCacheQuotaBytes() throws IOException {
         return getCacheQuotaBytes(mContext.getCacheDir());
     }
 
     /** @removed */
     @Deprecated
-    public long getCacheSizeBytes() {
+    public long getCacheSizeBytes() throws IOException {
         return getCacheSizeBytes(mContext.getCacheDir());
     }
 
     /** @removed */
     @Deprecated
-    public long getExternalCacheQuotaBytes() {
+    public long getExternalCacheQuotaBytes() throws IOException {
         return getCacheQuotaBytes(mContext.getExternalCacheDir());
     }
 
     /** @removed */
     @Deprecated
-    public long getExternalCacheSizeBytes() {
+    public long getExternalCacheSizeBytes() throws IOException {
         return getCacheSizeBytes(mContext.getExternalCacheDir());
     }
 
@@ -1542,8 +1627,8 @@
      * this flag to take effect.
      * </p>
      *
-     * @see #getAllocatableBytes(File, int)
-     * @see #allocateBytes(File, long, int)
+     * @see #getAllocatableBytes(UUID, int)
+     * @see #allocateBytes(UUID, long, int)
      * @see #allocateBytes(FileDescriptor, long, int)
      */
     @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
@@ -1558,32 +1643,43 @@
 
     /**
      * Return the maximum number of new bytes that your app can allocate for
-     * itself using {@link #allocateBytes(File, long, int)} at the given path.
-     * This value is typically larger than {@link File#getUsableSpace()}, since
-     * the system may be willing to delete cached files to satisfy an allocation
-     * request.
+     * itself on the given storage volume. This value is typically larger than
+     * {@link File#getUsableSpace()}, since the system may be willing to delete
+     * cached files to satisfy an allocation request. You can then allocate
+     * space for yourself using {@link #allocateBytes(UUID, long, int)} or
+     * {@link #allocateBytes(FileDescriptor, long, int)}.
      * <p>
      * This method is best used as a pre-flight check, such as deciding if there
      * is enough space to store an entire music album before you allocate space
      * for each audio file in the album. Attempts to allocate disk space beyond
      * the returned value will fail.
+     * <p>
+     * If the returned value is not large enough for the data you'd like to
+     * store, you can launch {@link #ACTION_MANAGE_STORAGE} with the
+     * {@link #EXTRA_UUID} and {@link #EXTRA_REQUESTED_BYTES} options to help
+     * involve the user in freeing up disk space.
      * <p class="note">
      * Note: if your app uses the {@code android:sharedUserId} manifest feature,
      * then allocatable space for all packages in your shared UID is tracked
      * together as a single unit.
      * </p>
      *
-     * @param path the path where you're considering allocating disk space,
-     *            since allocatable space can vary widely depending on the
-     *            underlying storage device.
+     * @param storageUuid the UUID of the storage volume where you're
+     *            considering allocating disk space, since allocatable space can
+     *            vary widely depending on the underlying storage device. The
+     *            UUID for a specific path can be obtained using
+     *            {@link #getUuidForPath(File)}.
      * @param flags to apply to the request.
      * @return the maximum number of new bytes that the calling app can allocate
-     *         using {@link #allocateBytes(File, long, int)}.
+     *         using {@link #allocateBytes(UUID, long, int)} or
+     *         {@link #allocateBytes(FileDescriptor, long, int)}.
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support allocating space.
      */
-    public long getAllocatableBytes(File path, @AllocateFlags int flags) throws IOException {
+    public long getAllocatableBytes(@NonNull UUID storageUuid, @AllocateFlags int flags)
+            throws IOException {
         try {
-            final String volumeUuid = findUuidForPath(path);
-            return mStorageManager.getAllocatableBytes(volumeUuid, flags);
+            return mStorageManager.getAllocatableBytes(convert(storageUuid), flags);
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
             throw new RuntimeException(e);
@@ -1592,28 +1688,40 @@
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public long getAllocatableBytes(@NonNull File path, @AllocateFlags int flags)
+            throws IOException {
+        return getAllocatableBytes(getUuidForPath(path), flags);
+    }
+
     /**
-     * Allocate the requested number of bytes for your application to use at the
-     * given path. This will cause the system to delete any cached files
-     * necessary to satisfy your request.
+     * Allocate the requested number of bytes for your application to use on the
+     * given storage volume. This will cause the system to delete any cached
+     * files necessary to satisfy your request.
      * <p>
      * Attempts to allocate disk space beyond the value returned by
-     * {@link #getAllocatableBytes(File, int)} will fail.
+     * {@link #getAllocatableBytes(UUID, int)} will fail.
      * <p>
      * Since multiple apps can be running simultaneously, this method may be
      * subject to race conditions. If possible, consider using
      * {@link #allocateBytes(FileDescriptor, long, int)} which will guarantee
      * that bytes are allocated to an opened file.
      *
-     * @param path the path where you'd like to allocate disk space.
+     * @param storageUuid the UUID of the storage volume where you'd like to
+     *            allocate disk space. The UUID for a specific path can be
+     *            obtained using {@link #getUuidForPath(File)}.
      * @param bytes the number of bytes to allocate.
      * @param flags to apply to the request.
-     * @see #getAllocatableBytes(File, int)
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support allocating space, or if the device had
+     *             trouble allocating the requested space.
+     * @see #getAllocatableBytes(UUID, int)
      */
-    public void allocateBytes(File path, long bytes, @AllocateFlags int flags) throws IOException {
+    public void allocateBytes(@NonNull UUID storageUuid, long bytes, @AllocateFlags int flags)
+            throws IOException {
         try {
-            final String volumeUuid = findUuidForPath(path);
-            mStorageManager.allocateBytes(volumeUuid, bytes, flags);
+            mStorageManager.allocateBytes(convert(storageUuid), bytes, flags);
         } catch (ParcelableException e) {
             e.maybeRethrow(IOException.class);
         } catch (RemoteException e) {
@@ -1621,13 +1729,20 @@
         }
     }
 
+    /** @removed */
+    @Deprecated
+    public void allocateBytes(@NonNull File path, long bytes, @AllocateFlags int flags)
+            throws IOException {
+        allocateBytes(getUuidForPath(path), bytes, flags);
+    }
+
     /**
      * Allocate the requested number of bytes for your application to use in the
      * given open file. This will cause the system to delete any cached files
      * necessary to satisfy your request.
      * <p>
      * Attempts to allocate disk space beyond the value returned by
-     * {@link #getAllocatableBytes(File, int)} will fail.
+     * {@link #getAllocatableBytes(UUID, int)} will fail.
      * <p>
      * This method guarantees that bytes have been allocated to the opened file,
      * otherwise it will throw if fast allocation is not possible. Fast
@@ -1636,9 +1751,15 @@
      *
      * @param fd the open file that you'd like to allocate disk space for.
      * @param bytes the number of bytes to allocate. This is the desired final
-     *            size of the open file.
+     *            size of the open file. If the open file is smaller than this
+     *            requested size, it will be extended without modifying any
+     *            existing contents. If the open file is larger than this
+     *            requested size, it will be truncated.
      * @param flags to apply to the request.
-     * @see #getAllocatableBytes(File, int)
+     * @throws IOException when the storage device isn't present, or when it
+     *             doesn't support allocating space, or if the device had
+     *             trouble allocating the requested space.
+     * @see #getAllocatableBytes(UUID, int)
      * @see Environment#isExternalStorageEmulated(File)
      */
     public void allocateBytes(FileDescriptor fd, long bytes, @AllocateFlags int flags)
@@ -1777,6 +1898,32 @@
         return isCacheBehavior(path, XATTR_CACHE_TOMBSTONE);
     }
 
+    /** {@hide} */
+    public static UUID convert(String uuid) {
+        if (Objects.equals(uuid, UUID_PRIVATE_INTERNAL)) {
+            return UUID_DEFAULT;
+        } else if (Objects.equals(uuid, UUID_PRIMARY_PHYSICAL)) {
+            return UUID_PRIMARY_PHYSICAL_;
+        } else if (Objects.equals(uuid, UUID_SYSTEM)) {
+            return UUID_SYSTEM_;
+        } else {
+            return UUID.fromString(uuid);
+        }
+    }
+
+    /** {@hide} */
+    public static String convert(UUID storageUuid) {
+        if (UUID_DEFAULT.equals(storageUuid)) {
+            return UUID_PRIVATE_INTERNAL;
+        } else if (UUID_PRIMARY_PHYSICAL_.equals(storageUuid)) {
+            return UUID_PRIMARY_PHYSICAL;
+        } else if (UUID_SYSTEM_.equals(storageUuid)) {
+            return UUID_SYSTEM;
+        } else {
+            return storageUuid.toString();
+        }
+    }
+
     private final Object mFuseAppLoopLock = new Object();
 
     @GuardedBy("mFuseAppLoopLock")
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index d3adce7..7496cb2 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -135,6 +135,7 @@
     private boolean mDependencyMet = true;
     private boolean mParentDependencyMet = true;
     private boolean mRecycleEnabled = true;
+    private boolean mHasSingleLineTitleAttr;
     private boolean mSingleLineTitle = true;
     private boolean mIconSpaceReserved;
 
@@ -303,6 +304,7 @@
 
                 case com.android.internal.R.styleable.Preference_singleLineTitle:
                     mSingleLineTitle = a.getBoolean(attr, mSingleLineTitle);
+                    mHasSingleLineTitleAttr = true;
                     break;
 
                 case com.android.internal.R.styleable.Preference_iconSpaceReserved:
@@ -609,7 +611,9 @@
             if (!TextUtils.isEmpty(title)) {
                 titleView.setText(title);
                 titleView.setVisibility(View.VISIBLE);
-                titleView.setSingleLine(mSingleLineTitle);
+                if (mHasSingleLineTitleAttr) {
+                    titleView.setSingleLine(mSingleLineTitle);
+                }
             } else {
                 titleView.setVisibility(View.GONE);
             }
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index f2aed5d..e9ef770 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -15,10 +15,18 @@
  */
 package android.provider;
 
+import static android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.content.pm.Signature;
@@ -26,8 +34,10 @@
 import android.graphics.Typeface;
 import android.graphics.fonts.FontRequest;
 import android.graphics.fonts.FontResult;
+import android.graphics.fonts.FontVariationAxis;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
@@ -37,14 +47,22 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Utility class to deal with Font ContentProviders.
@@ -140,7 +158,6 @@
      * @hide
      */
     public static final String PARCEL_FONT_RESULTS = "font_results";
-
     // Error codes internal to the system, which can not come from a provider. To keep the number
     // space open for new provider codes, these should all be negative numbers.
     /** @hide */
@@ -165,11 +182,128 @@
         mPackageManager = mContext.getPackageManager();
     }
 
-    /** @hide */
-    @VisibleForTesting
-    public FontsContract(Context context, PackageManager packageManager) {
-        mContext = context;
-        mPackageManager = packageManager;
+    /**
+     * Object represent a font entry in the family returned from {@link #fetchFonts}.
+     */
+    public static class FontInfo {
+        private final Uri mUri;
+        private final int mTtcIndex;
+        private final FontVariationAxis[] mAxes;
+        private final int mWeight;
+        private final boolean mItalic;
+        private final int mResultCode;
+
+        /**
+         * Creates a Font with all the information needed about a provided font.
+         * @param uri A URI associated to the font file.
+         * @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0.
+         * @param axes If providing a variation font, the settings for it. May be null.
+         * @param weight An integer that indicates the font weight.
+         * @param italic A boolean that indicates the font is italic style or not.
+         * @param resultCode A boolean that indicates the font contents is ready.
+         */
+        /** @hide */
+        public FontInfo(@NonNull Uri uri, @IntRange(from = 0) int ttcIndex,
+                @Nullable FontVariationAxis[] axes, @IntRange(from = 1, to = 1000) int weight,
+                boolean italic, int resultCode) {
+            mUri = Preconditions.checkNotNull(uri);
+            mTtcIndex = ttcIndex;
+            mAxes = axes;
+            mWeight = weight;
+            mItalic = italic;
+            mResultCode = resultCode;
+        }
+
+        /**
+         * Returns a URI associated to this record.
+         */
+        public @NonNull Uri getUri() {
+            return mUri;
+        }
+
+        /**
+         * Returns the index to be used to access this font when accessing a TTC file.
+         */
+        public @IntRange(from = 0) int getTtcIndex() {
+            return mTtcIndex;
+        }
+
+        /**
+         * Returns the list of axes associated to this font.
+         */
+        public @Nullable FontVariationAxis[] getAxes() {
+            return mAxes;
+        }
+
+        /**
+         * Returns the weight value for this font.
+         */
+        public @IntRange(from = 1, to = 1000) int getWeight() {
+            return mWeight;
+        }
+
+        /**
+         * Returns whether this font is italic.
+         */
+        public boolean isItalic() {
+            return mItalic;
+        }
+
+        /**
+         * Returns result code.
+         *
+         * {@link FontsContract.Columns#RESULT_CODE}
+         */
+        public int getResultCode() {
+            return mResultCode;
+        }
+    }
+
+    /**
+     * Object returned from {@link #fetchFonts}.
+     */
+    public static class FontFamilyResult {
+        /**
+         * Constant represents that the font was successfully retrieved. Note that when this value
+         * is set and {@link #getFonts} returns an empty array, it means there were no fonts
+         * matching the given query.
+         */
+        public static final int STATUS_OK = 0;
+
+        /**
+         * Constant represents that the given certificate was not matched with the provider's
+         * signature. {@link #getFonts} returns null if this status was set.
+         */
+        public static final int STATUS_WRONG_CERTIFICATES = 1;
+
+        /**
+         * Constant represents that the provider returns unexpected data. {@link #getFonts} returns
+         * null if this status was set. For example, this value is set when the font provider
+         * gives invalid format of variation settings.
+         */
+        public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2;
+
+        /** @hide */
+        @IntDef({STATUS_OK, STATUS_WRONG_CERTIFICATES, STATUS_UNEXPECTED_DATA_PROVIDED})
+        @Retention(RetentionPolicy.SOURCE)
+        @interface FontResultStatus {}
+
+        private final @FontResultStatus int mStatusCode;
+        private final FontInfo[] mFonts;
+
+        /** @hide */
+        public FontFamilyResult(@FontResultStatus int statusCode, @Nullable FontInfo[] fonts) {
+            mStatusCode = statusCode;
+            mFonts = fonts;
+        }
+
+        public @FontResultStatus int getStatusCode() {
+            return mStatusCode;
+        }
+
+        public @NonNull FontInfo[] getFonts() {
+            return mFonts;
+        }
     }
 
     // We use a background thread to post the content resolving work for all requests on. This
@@ -196,33 +330,350 @@
                 mHandler = new Handler(mThread.getLooper());
             }
             mHandler.post(() -> {
-                ProviderInfo providerInfo = getProvider(request, receiver);
-                if (providerInfo == null) {
+                ProviderInfo providerInfo;
+                try {
+                    providerInfo = getProvider(mPackageManager, request);
+                    if (providerInfo == null) {
+                        receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
+                        return;
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
                     return;
                 }
-                getFontFromProvider(request, receiver, providerInfo.authority);
+                FontInfo[] fonts;
+                try {
+                    fonts = getFontFromProvider(mContext, request, providerInfo.authority,
+                            null /* cancellation signal */);
+                } catch (InvalidFormatException e) {
+                    receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
+                    return;
+                }
+
+                ArrayList<FontResult> result = new ArrayList<>();
+                int resultCode = -1;
+                for (FontInfo font : fonts) {
+                    try {
+                        resultCode = font.getResultCode();
+                        if (resultCode != Columns.RESULT_CODE_OK) {
+                            if (resultCode < 0) {
+                                // Negative values are reserved for the internal errors.
+                                resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND;
+                            }
+                            for (int i = 0; i < result.size(); ++i) {
+                                try {
+                                    result.get(i).getFileDescriptor().close();
+                                } catch (IOException e) {
+                                    // Ignore, as we are closing fds for cleanup.
+                                }
+                            }
+                            receiver.send(resultCode, null);
+                            return;
+                        }
+                        ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor(
+                                font.getUri(), "r");
+                        result.add(new FontResult(pfd, font.getTtcIndex(),
+                                FontVariationAxis.toFontVariationSettings(font.getAxes()),
+                                font.getWeight(), font.isItalic()));
+                    } catch (FileNotFoundException e) {
+                        Log.e(TAG, "FileNotFoundException raised when interacting with content "
+                                + "provider " + providerInfo.authority, e);
+                    }
+                }
+                if (!result.isEmpty()) {
+                    Bundle bundle = new Bundle();
+                    bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result);
+                    receiver.send(Columns.RESULT_CODE_OK, bundle);
+                    return;
+                }
+                receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null);
             });
             mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable);
             mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS);
         }
     }
 
+    /**
+     * Interface used to receive asynchronously fetched typefaces.
+     */
+    public static class FontRequestCallback {
+        /**
+         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+         * provider was not found on the device.
+         */
+        public static final int FAIL_REASON_PROVIDER_NOT_FOUND = RESULT_CODE_PROVIDER_NOT_FOUND;
+        /**
+         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+         * provider must be authenticated and the given certificates do not match its signature.
+         */
+        public static final int FAIL_REASON_WRONG_CERTIFICATES = RESULT_CODE_WRONG_CERTIFICATES;
+        /**
+         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+         * returned by the provider was not loaded properly.
+         */
+        public static final int FAIL_REASON_FONT_LOAD_ERROR = -3;
+        /**
+         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+         * provider did not return any results for the given query.
+         */
+        public static final int FAIL_REASON_FONT_NOT_FOUND = Columns.RESULT_CODE_FONT_NOT_FOUND;
+        /**
+         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+         * provider found the queried font, but it is currently unavailable.
+         */
+        public static final int FAIL_REASON_FONT_UNAVAILABLE = Columns.RESULT_CODE_FONT_UNAVAILABLE;
+        /**
+         * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+         * query was not supported by the provider.
+         */
+        public static final int FAIL_REASON_MALFORMED_QUERY = Columns.RESULT_CODE_MALFORMED_QUERY;
+
+        /** @hide */
+        @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR,
+                FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE,
+                FAIL_REASON_MALFORMED_QUERY })
+        @Retention(RetentionPolicy.SOURCE)
+        @interface FontRequestFailReason {}
+
+        public FontRequestCallback() {}
+
+        /**
+         * Called then a Typeface request done via {@link Typeface#create(FontRequest,
+         * FontRequestCallback)} is complete. Note that this method will not be called if
+         * {@link #onTypefaceRequestFailed(int)} is called instead.
+         * @param typeface  The Typeface object retrieved.
+         */
+        public void onTypefaceRetrieved(Typeface typeface) {}
+
+        /**
+         * Called when a Typeface request done via {@link Typeface#create(FontRequest,
+         * FontRequestCallback)} fails.
+         * @param reason One of {@link #FAIL_REASON_PROVIDER_NOT_FOUND},
+         *               {@link #FAIL_REASON_FONT_NOT_FOUND},
+         *               {@link #FAIL_REASON_FONT_LOAD_ERROR},
+         *               {@link #FAIL_REASON_FONT_UNAVAILABLE} or
+         *               {@link #FAIL_REASON_MALFORMED_QUERY}.
+         */
+        public void onTypefaceRequestFailed(@FontRequestFailReason int reason) {}
+    }
+
+    /**
+     * Create a typeface object given a font request. The font will be asynchronously fetched,
+     * therefore the result is delivered to the given callback. See {@link FontRequest}.
+     * Only one of the methods in callback will be invoked, depending on whether the request
+     * succeeds or fails. These calls will happen on the caller thread.
+     * @param context A context to be used for fetching from font provider.
+     * @param request A {@link FontRequest} object that identifies the provider and query for the
+     *                request. May not be null.
+     * @param callback A callback that will be triggered when results are obtained. May not be null.
+     * @param handler A handler to be processed the font fetching.
+     */
+    public static void requestFont(@NonNull Context context, @NonNull FontRequest request,
+            @NonNull FontRequestCallback callback, @NonNull Handler handler) {
+
+        final Handler callerThreadHandler = new Handler();
+        handler.post(() -> {
+            // TODO: Cache the result.
+            FontFamilyResult result;
+            try {
+                result = fetchFonts(context, null /* cancellation signal */, request);
+            } catch (NameNotFoundException e) {
+                callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+                        FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND));
+                return;
+            }
+
+            if (result.getStatusCode() != FontFamilyResult.STATUS_OK) {
+                switch (result.getStatusCode()) {
+                    case FontFamilyResult.STATUS_WRONG_CERTIFICATES:
+                        callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+                                FontRequestCallback.FAIL_REASON_WRONG_CERTIFICATES));
+                        return;
+                    case FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED:
+                        callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+                                FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+                        return;
+                    default:
+                        // fetchFont returns unexpected status type. Fallback to load error.
+                        callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+                                FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+                        return;
+                }
+            }
+
+            final FontInfo[] fonts = result.getFonts();
+            if (fonts == null || fonts.length == 0) {
+                callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+                        FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND));
+                return;
+            }
+            for (final FontInfo font : fonts) {
+                if (font.getResultCode() != Columns.RESULT_CODE_OK) {
+                    // We proceed if all font entry is ready to use. Otherwise report the first
+                    // error.
+                    final int resultCode = font.getResultCode();
+                    if (resultCode < 0) {
+                        // Negative values are reserved for internal errors. Fallback to load error.
+                        callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+                                FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+                    } else {
+                        callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+                                resultCode));
+                    }
+                    return;
+                }
+            }
+
+            final Typeface typeface = buildTypeface(context, null /* cancellation signal */, fonts);
+            if (typeface == null) {
+                // Something went wrong during reading font files. This happens if the given font
+                // file is an unsupported font type.
+                callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+                        FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+                return;
+            }
+
+            callerThreadHandler.post(() -> callback.onTypefaceRetrieved(typeface));
+        });
+    }
+
+    /**
+     * Fetch fonts given a font request.
+     *
+     * @param context A {@link Context} to be used for fetching fonts.
+     * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
+     *                           the operation is canceled, then {@link
+     *                           android.os.OperationCanceledException} will be thrown when the
+     *                           query is executed.
+     * @param request A {@link FontRequest} object that identifies the provider and query for the
+     *                request.
+     *
+     * @return {@link FontFamilyResult}
+     *
+     * @throws NameNotFoundException If requested package or authority was not found in system.
+     */
+    public static @NonNull FontFamilyResult fetchFonts(
+            @NonNull Context context, @Nullable CancellationSignal cancellationSignal,
+            @NonNull FontRequest request) throws NameNotFoundException {
+        ProviderInfo providerInfo = getProvider(context.getPackageManager(), request);
+        if (providerInfo == null) {
+            return new FontFamilyResult(FontFamilyResult.STATUS_WRONG_CERTIFICATES, null);
+
+        }
+        try {
+            FontInfo[] fonts = getFontFromProvider(
+                    context, request, providerInfo.authority, cancellationSignal);
+            return new FontFamilyResult(FontFamilyResult.STATUS_OK, fonts);
+        } catch (InvalidFormatException e) {
+            return new FontFamilyResult(FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED, null);
+        }
+    }
+
+    /**
+     * Build a Typeface from an array of {@link FontInfo}. Results that are marked as not ready
+     * will be skipped.
+     *
+     * @param context A {@link Context} that will be used to fetch the font contents.
+     * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
+     *                           the operation is canceled, then {@link
+     *                           android.os.OperationCanceledException} will be thrown.
+     * @param fonts An array of {@link FontInfo} to be used to create a Typeface.
+     * @param weight A weight value to be used for selecting a font from a font family.
+     * @param italic {@code true} if this font is of italic style. This will be used for font
+     *               selection from a font family.
+     * @param fallbackFontName A fallback font name used if this method fails to create the
+     *                         Typeface. By passing {@code null}, this method returns {@code null}
+     *                         if typeface creation fails.
+     * @return A Typeface object. May return {@code null} if that is the value passed to {@code
+     *         fallBackFontName}.
+     */
+    public static Typeface buildTypeface(@NonNull Context context,
+            @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts,
+            int weight, boolean italic, @Nullable String fallbackFontName) {
+        final Map<Uri, ByteBuffer> uriBuffer =
+                prepareFontData(context, fonts, cancellationSignal);
+        return new Typeface.Builder(fonts, uriBuffer)
+            .setFallback(fallbackFontName)
+            .setWeight(weight)
+            .setItalic(italic)
+            .build();
+    }
+
+    /**
+     * Build a Typeface from an array of {@link FontInfo}
+     *
+     * Results that are marked as not ready will be skipped.
+     *
+     * @param context A {@link Context} that will be used to fetch the font contents.
+     * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
+     *                           the operation is canceled, then {@link
+     *                           android.os.OperationCanceledException} will be thrown.
+     * @param fonts An array of {@link FontInfo} to be used to create a Typeface.
+     * @return A Typeface object. Returns null if typeface creation fails.
+     */
+    public static Typeface buildTypeface(@NonNull Context context,
+            @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts) {
+        final Map<Uri, ByteBuffer> uriBuffer =
+                prepareFontData(context, fonts, cancellationSignal);
+        return new Typeface.Builder(fonts, uriBuffer).build();
+    }
+
+    /**
+     * A helper function to create a mapping from {@link Uri} to {@link ByteBuffer}.
+     *
+     * Skip if the file contents is not ready to be read.
+     *
+     * @param context A {@link Context} to be used for resolving content URI in
+     *                {@link FontInfo}.
+     * @param fonts An array of {@link FontInfo}.
+     * @return A map from {@link Uri} to {@link ByteBuffer}.
+     */
+    private static Map<Uri, ByteBuffer> prepareFontData(Context context, FontInfo[] fonts,
+            CancellationSignal cancellationSignal) {
+        final HashMap<Uri, ByteBuffer> out = new HashMap<>();
+        final ContentResolver resolver = context.getContentResolver();
+
+        for (FontInfo font : fonts) {
+            if (font.getResultCode() != Columns.RESULT_CODE_OK) {
+                continue;
+            }
+
+            final Uri uri = font.getUri();
+            if (out.containsKey(uri)) {
+                continue;
+            }
+
+            ByteBuffer buffer = null;
+            try (final ParcelFileDescriptor pfd =
+                    resolver.openFileDescriptor(uri, "r", cancellationSignal);
+                    final FileInputStream fis = new FileInputStream(pfd.getFileDescriptor())) {
+                final FileChannel fileChannel = fis.getChannel();
+                final long size = fileChannel.size();
+                buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, size);
+            } catch (IOException e) {
+                // ignore
+            }
+
+            // TODO: try other approach?, e.g. read all contents instead of mmap.
+
+            out.put(uri, buffer);
+        }
+        return Collections.unmodifiableMap(out);
+    }
+
     /** @hide */
     @VisibleForTesting
-    public ProviderInfo getProvider(FontRequest request, ResultReceiver receiver) {
+    public static @Nullable ProviderInfo getProvider(
+            PackageManager packageManager, FontRequest request) throws NameNotFoundException {
         String providerAuthority = request.getProviderAuthority();
-        ProviderInfo info = mPackageManager.resolveContentProvider(providerAuthority, 0);
+        ProviderInfo info = packageManager.resolveContentProvider(providerAuthority, 0);
         if (info == null) {
-            Log.e(TAG, "Can't find content provider " + providerAuthority);
-            receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
-            return null;
+            throw new NameNotFoundException("No package found for authority: " + providerAuthority);
         }
 
         if (!info.packageName.equals(request.getProviderPackage())) {
-            Log.e(TAG, "Found content provider " + providerAuthority + ", but package was not "
-                    + request.getProviderPackage());
-            receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
-            return null;
+            throw new NameNotFoundException("Found content provider " + providerAuthority
+                    + ", but package was not " + request.getProviderPackage());
         }
         // Trust system apps without signature checks
         if (info.applicationInfo.isSystemApp()) {
@@ -230,16 +681,11 @@
         }
 
         List<byte[]> signatures;
-        try {
-            PackageInfo packageInfo = mPackageManager.getPackageInfo(info.packageName,
-                    PackageManager.GET_SIGNATURES);
-            signatures = convertToByteArrayList(packageInfo.signatures);
-            Collections.sort(signatures, sByteArrayComparator);
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, "Can't find content provider " + providerAuthority, e);
-            receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
-            return null;
-        }
+        PackageInfo packageInfo = packageManager.getPackageInfo(info.packageName,
+                PackageManager.GET_SIGNATURES);
+        signatures = convertToByteArrayList(packageInfo.signatures);
+        Collections.sort(signatures, sByteArrayComparator);
+
         List<List<byte[]>> requestCertificatesList = request.getCertificates();
         for (int i = 0; i < requestCertificatesList.size(); ++i) {
             // Make a copy so we can sort it without modifying the incoming data.
@@ -249,8 +695,6 @@
                 return info;
             }
         }
-        Log.e(TAG, "Certificates don't match for given provider " + providerAuthority);
-        receiver.send(RESULT_CODE_WRONG_CERTIFICATES, null);
         return null;
     }
 
@@ -266,7 +710,8 @@
         return 0;
     };
 
-    private boolean equalsByteArrayList(List<byte[]> signatures, List<byte[]> requestSignatures) {
+    private static boolean equalsByteArrayList(
+            List<byte[]> signatures, List<byte[]> requestSignatures) {
         if (signatures.size() != requestSignatures.size()) {
             return false;
         }
@@ -278,7 +723,7 @@
         return true;
     }
 
-    private List<byte[]> convertToByteArrayList(Signature[] signatures) {
+    private static List<byte[]> convertToByteArrayList(Signature[] signatures) {
         List<byte[]> shas = new ArrayList<>();
         for (int i = 0; i < signatures.length; ++i) {
             shas.add(signatures[i].toByteArray());
@@ -288,9 +733,10 @@
 
     /** @hide */
     @VisibleForTesting
-    public void getFontFromProvider(FontRequest request, ResultReceiver receiver,
-            String authority) {
-        ArrayList<FontResult> result = null;
+    public static @NonNull FontInfo[] getFontFromProvider(
+            Context context, FontRequest request, String authority,
+            CancellationSignal cancellationSignal) throws InvalidFormatException {
+        ArrayList<FontInfo> result = new ArrayList<>();
         final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
                 .authority(authority)
                 .build();
@@ -298,15 +744,14 @@
                 .authority(authority)
                 .appendPath("file")
                 .build();
-        try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID,
+        try (Cursor cursor = context.getContentResolver().query(uri, new String[] { Columns._ID,
                         Columns.FILE_ID, Columns.TTC_INDEX, Columns.VARIATION_SETTINGS,
                         Columns.STYLE, Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE },
-                "query = ?", new String[] { request.getQuery() }, null);) {
+                "query = ?", new String[] { request.getQuery() }, null, cancellationSignal);) {
             // TODO: Should we restrict the amount of fonts that can be returned?
             // TODO: Write documentation explaining that all results should be from the same family.
             if (cursor != null && cursor.getCount() > 0) {
                 final int resultCodeColumnIndex = cursor.getColumnIndex(Columns.RESULT_CODE);
-                int resultCode = -1;
                 result = new ArrayList<>();
                 final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID);
                 final int fileIdColumnIndex = cursor.getColumnIndex(Columns.FILE_ID);
@@ -316,23 +761,13 @@
                 final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC);
                 final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE);
                 while (cursor.moveToNext()) {
-                    resultCode = resultCodeColumnIndex != -1
+                    int resultCode = resultCodeColumnIndex != -1
                             ? cursor.getInt(resultCodeColumnIndex) : Columns.RESULT_CODE_OK;
-                    if (resultCode != Columns.RESULT_CODE_OK) {
-                        if (resultCode < 0) {
-                            // Negative values are reserved for the internal errors.
-                            resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND;
-                        }
-                        for (int i = 0; i < result.size(); ++i) {
-                            try {
-                                result.get(i).getFileDescriptor().close();
-                            } catch (IOException e) {
-                                // Ignore, as we are closing fds for cleanup.
-                            }
-                        }
-                        receiver.send(resultCode, null);
-                        return;
-                    }
+                    final int ttcIndex = ttcIndexColumnIndex != -1
+                            ? cursor.getInt(ttcIndexColumnIndex) : 0;
+                    final String variationSettings = vsColumnIndex != -1
+                            ? cursor.getString(vsColumnIndex) : null;
+
                     Uri fileUri;
                     if (fileIdColumnIndex == -1) {
                         long id = cursor.getLong(idColumnIndex);
@@ -341,42 +776,27 @@
                         long id = cursor.getLong(fileIdColumnIndex);
                         fileUri = ContentUris.withAppendedId(fileBaseUri, id);
                     }
-                    try {
-                        ParcelFileDescriptor pfd =
-                                mContext.getContentResolver().openFileDescriptor(fileUri, "r");
-                        final int ttcIndex = ttcIndexColumnIndex != -1
-                                ? cursor.getInt(ttcIndexColumnIndex) : 0;
-                        final String variationSettings = vsColumnIndex != -1
-                                ? cursor.getString(vsColumnIndex) : null;
-                        // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column.
-                        int weight;
-                        boolean italic;
-                        if (weightColumnIndex != -1 && italicColumnIndex != -1) {
-                            weight = cursor.getInt(weightColumnIndex);
-                            italic = cursor.getInt(italicColumnIndex) == 1;
-                        } else if (styleColumnIndex != -1) {
-                            final int style = cursor.getInt(styleColumnIndex);
-                            weight = (style & Typeface.BOLD) != 0 ? 700 : 400;
-                            italic = (style & Typeface.ITALIC) != 0;
-                        } else {
-                            weight = 400;
-                            italic = false;
-                        }
-                        result.add(
-                                new FontResult(pfd, ttcIndex, variationSettings, weight, italic));
-                    } catch (FileNotFoundException e) {
-                        Log.e(TAG, "FileNotFoundException raised when interacting with content "
-                                + "provider " + authority, e);
+                    // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column.
+                    int weight;
+                    boolean italic;
+                    if (weightColumnIndex != -1 && italicColumnIndex != -1) {
+                        weight = cursor.getInt(weightColumnIndex);
+                        italic = cursor.getInt(italicColumnIndex) == 1;
+                    } else if (styleColumnIndex != -1) {
+                        final int style = cursor.getInt(styleColumnIndex);
+                        weight = (style & Typeface.BOLD) != 0 ?
+                                Typeface.Builder.BOLD_WEIGHT : Typeface.Builder.NORMAL_WEIGHT;
+                        italic = (style & Typeface.ITALIC) != 0;
+                    } else {
+                        weight = Typeface.Builder.NORMAL_WEIGHT;
+                        italic = false;
                     }
+                    FontVariationAxis[] axes =
+                            FontVariationAxis.fromFontVariationSettings(variationSettings);
+                    result.add(new FontInfo(fileUri, ttcIndex, axes, weight, italic, resultCode));
                 }
             }
         }
-        if (result != null && !result.isEmpty()) {
-            Bundle bundle = new Bundle();
-            bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result);
-            receiver.send(Columns.RESULT_CODE_OK, bundle);
-            return;
-        }
-        receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+        return result.toArray(new FontInfo[0]);
     }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9877561..7c59324 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3150,6 +3150,13 @@
         public static final String VOLUME_BLUETOOTH_SCO = "volume_bluetooth_sco";
 
         /**
+         * @hide
+         * Acessibility volume. This is used internally, changing this
+         * value will not change the volume.
+         */
+        public static final String VOLUME_ACCESSIBILITY = "volume_a11y";
+
+        /**
          * Master volume (float in the range 0.0f to 1.0f).
          *
          * @hide
@@ -3212,6 +3219,22 @@
         };
 
         /**
+         * @hide
+         * The mapping of stream type (integer) to its setting.
+         * Unlike the VOLUME_SETTINGS array, this one contains as many entries as
+         * AudioSystem.NUM_STREAM_TYPES, and has empty strings for stream types whose volumes
+         * are never persisted.
+         */
+        public static final String[] VOLUME_SETTINGS_INT = {
+                VOLUME_VOICE, VOLUME_SYSTEM, VOLUME_RING, VOLUME_MUSIC,
+                VOLUME_ALARM, VOLUME_NOTIFICATION, VOLUME_BLUETOOTH_SCO,
+                "" /*STREAM_SYSTEM_ENFORCED, no setting for this stream*/,
+                "" /*STREAM_DTMF, no setting for this stream*/,
+                "" /*STREAM_TTS, no setting for this stream*/,
+                VOLUME_ACCESSIBILITY
+            };
+
+        /**
          * Appended to various volume related settings to record the previous
          * values before they the settings were affected by a silent/vibrate
          * ringer mode change.
@@ -6755,6 +6778,14 @@
                 "camera_double_twist_to_flip_enabled";
 
         /**
+         * Whether or not the smart camera lift trigger that launches the camera when the user moves
+         * the phone into a position for taking photos should be enabled.
+         *
+         * @hide
+         */
+        public static final String CAMERA_LIFT_TRIGGER_ENABLED = "camera_lift_trigger_enabled";
+
+        /**
          * Whether the assist gesture should be enabled.
          *
          * @hide
@@ -7054,6 +7085,7 @@
             CLONE_TO_MANAGED_PROFILE.add(ACCESSIBILITY_ENABLED);
             CLONE_TO_MANAGED_PROFILE.add(ALLOW_MOCK_LOCATION);
             CLONE_TO_MANAGED_PROFILE.add(ALLOWED_GEOLOCATION_ORIGINS);
+            CLONE_TO_MANAGED_PROFILE.add(AUTOFILL_SERVICE);
             CLONE_TO_MANAGED_PROFILE.add(DEFAULT_INPUT_METHOD);
             CLONE_TO_MANAGED_PROFILE.add(ENABLED_ACCESSIBILITY_SERVICES);
             CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
@@ -8307,7 +8339,6 @@
          * enabled state.
          * @hide
          */
-        @SystemApi
         public static final String NETWORK_RECOMMENDATIONS_ENABLED =
                 "network_recommendations_enabled";
 
@@ -8821,6 +8852,15 @@
         public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
 
         /**
+         * A comma separated list of URLs used for captive portal detection in addition to the
+         * fallback HTTP url associated with the CAPTIVE_PORTAL_FALLBACK_URL settings.
+         *
+         * @hide
+         */
+        public static final String CAPTIVE_PORTAL_OTHER_FALLBACK_URLS =
+                "captive_portal_other_fallback_urls";
+
+        /**
          * Whether to use HTTPS for network validation. This is enabled by default and the setting
          * needs to be set to 0 to disable it. This setting is a misnomer because captive portals
          * don't actually use HTTPS, but it's consistent with the other settings.
diff --git a/core/java/android/provider/SettingsStringUtil.java b/core/java/android/provider/SettingsStringUtil.java
index 3dfedea..a3dc947 100644
--- a/core/java/android/provider/SettingsStringUtil.java
+++ b/core/java/android/provider/SettingsStringUtil.java
@@ -23,6 +23,7 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.function.Function;
@@ -80,6 +81,12 @@
                 return s;
             }
 
+            public static String addAll(String delimitedElements, Collection<String> elements) {
+                final ColonDelimitedSet<String> set
+                        = new ColonDelimitedSet.OfStrings(delimitedElements);
+                return set.addAll(elements) ? set.toString() : delimitedElements;
+            }
+
             public static String add(String delimitedElements, String element) {
                 final ColonDelimitedSet<String> set
                         = new ColonDelimitedSet.OfStrings(delimitedElements);
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index a4d3fb2..813c54f 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -34,6 +34,8 @@
 
 import com.android.internal.os.SomeArgs;
 
+import java.util.List;
+
 //TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
 //life-cycle (and how state could be maintained on server-side) is well documented.
 
@@ -103,24 +105,22 @@
         }
 
         @Override
-        public void onFillRequest(AssistStructure structure, Bundle extras,
-                IFillCallback callback, int flags) {
+        public void onFillRequest(FillRequest request, IFillCallback callback) {
             ICancellationSignal transport = CancellationSignal.createTransport();
             try {
                 callback.onCancellable(transport);
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             }
-            mHandlerCaller.obtainMessageIIOOOO(MSG_ON_FILL_REQUEST, flags, UNUSED_ARG, structure,
-                    CancellationSignal.fromTransport(transport), extras, callback)
+            mHandlerCaller.obtainMessageOOO(MSG_ON_FILL_REQUEST, request,
+                    CancellationSignal.fromTransport(transport), callback)
                     .sendToTarget();
         }
 
         @Override
-        public void onSaveRequest(AssistStructure structure, Bundle extras,
-                ISaveCallback callback) {
-            mHandlerCaller.obtainMessageOOO(MSG_ON_SAVE_REQUEST, structure,
-                    extras, callback).sendToTarget();
+        public void onSaveRequest(SaveRequest request, ISaveCallback callback) {
+            mHandlerCaller.obtainMessageOO(MSG_ON_SAVE_REQUEST, request,
+                    callback).sendToTarget();
         }
     };
 
@@ -131,23 +131,20 @@
                 break;
             } case MSG_ON_FILL_REQUEST: {
                 final SomeArgs args = (SomeArgs) msg.obj;
-                final AssistStructure structure = (AssistStructure) args.arg1;
+                final FillRequest request = (FillRequest) args.arg1;
                 final CancellationSignal cancellation = (CancellationSignal) args.arg2;
-                final Bundle extras = (Bundle) args.arg3;
-                final IFillCallback callback = (IFillCallback) args.arg4;
-                final FillCallback fillCallback = new FillCallback(callback);
-                final int flags = msg.arg1;
+                final IFillCallback callback = (IFillCallback) args.arg3;
+                final FillCallback fillCallback = new FillCallback(callback, request.getId());
                 args.recycle();
-                onFillRequest(structure, extras, flags, cancellation, fillCallback);
+                onFillRequest(request, cancellation, fillCallback);
                 break;
             } case MSG_ON_SAVE_REQUEST: {
                 final SomeArgs args = (SomeArgs) msg.obj;
-                final AssistStructure structure = (AssistStructure) args.arg1;
-                final Bundle extras = (Bundle) args.arg2;
-                final ISaveCallback callback = (ISaveCallback) args.arg3;
+                final SaveRequest request = (SaveRequest) args.arg1;
+                final ISaveCallback callback = (ISaveCallback) args.arg2;
                 final SaveCallback saveCallback = new SaveCallback(callback);
                 args.recycle();
-                onSaveRequest(structure, extras, saveCallback);
+                onSaveRequest(request, saveCallback);
                 break;
             } case MSG_DISCONNECT: {
                 onDisconnected();
@@ -198,6 +195,28 @@
      * or {@link FillCallback#onFailure(CharSequence)})
      * to notify the result of the request.
      *
+     * @param request the {@link FillRequest request} to handle.
+     *        See {@link FillResponse} for examples of multiple-sections requests.
+     * @param cancellationSignal signal for observing cancellation requests. The system will use
+     *     this to notify you that the fill result is no longer needed and you should stop
+     *     handling this fill request in order to save resources.
+     * @param callback object used to notify the result of the request.
+     */
+    public void onFillRequest(@NonNull FillRequest request,
+            @NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback) {
+        onFillRequest(request.getStructure(), request.getClientState(), request.getFlags(),
+                cancellationSignal, callback);
+    }
+
+    /**
+     * Called by the Android system do decide if an {@link Activity} can be autofilled by the
+     * service.
+     *
+     * <p>Service must call one of the {@link FillCallback} methods (like
+     * {@link FillCallback#onSuccess(FillResponse)}
+     * or {@link FillCallback#onFailure(CharSequence)})
+     * to notify the result of the request.
+     *
      * @param structure {@link Activity}'s view structure.
      * @param data bundle containing data passed by the service in a last call to
      *        {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
@@ -211,6 +230,7 @@
      *     handling this fill request in order to save resources.
      * @param callback object used to notify the result of the request.
      */
+    @Deprecated
     public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
             int flags, @NonNull CancellationSignal cancellationSignal,
             @NonNull FillCallback callback);
@@ -222,6 +242,23 @@
      * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
      * to notify the result of the request.
      *
+     * @param request the {@link SaveRequest request} to handle.
+     *        See {@link FillResponse} for examples of multiple-sections requests.
+     * @param callback object used to notify the result of the request.
+     */
+    public void onSaveRequest(@NonNull SaveRequest request, @NonNull SaveCallback callback) {
+        final List<FillContext> contexts = request.getFillContexts();
+        onSaveRequest(contexts.get(contexts.size() - 1).getStructure(),
+                request.getClientState(), callback);
+    }
+
+    /**
+     * Called when user requests service to save the fields of an {@link Activity}.
+     *
+     * <p>Service must call one of the {@link SaveCallback} methods (like
+     * {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
+     * to notify the result of the request.
+     *
      * @param structure {@link Activity}'s view structure.
      * @param data bundle containing data passed by the service in a last call to
      *        {@link FillResponse.Builder#setExtras(Bundle)}, if any. This bundle allows your
@@ -231,6 +268,7 @@
      *        See {@link FillResponse} for examples of multiple-sections requests.
      * @param callback object used to notify the result of the request.
      */
+    @Deprecated
     public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
             @NonNull SaveCallback callback);
 
@@ -247,4 +285,22 @@
         // TODO(b/33197203): Remove when GCore has migrated off this API
         getSystemService(AutofillManager.class).disableOwnedAutofillServices();
     }
+
+    /**
+     * Returns the {@link FillEventHistory.Event events} since the last {@link FillResponse} was
+     * returned.
+     *
+     * <p>The history is not persisted over reboots.
+     *
+     * @return The history or {@code null} if there are not events.
+     */
+    @Nullable public final FillEventHistory getFillEventHistory() {
+        AutofillManager afm = getSystemService(AutofillManager.class);
+
+        if (afm == null) {
+            return null;
+        } else {
+            return afm.getFillEventHistory();
+        }
+    }
 }
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index e77bd0d..e04fae7 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -24,6 +24,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
 import android.widget.RemoteViews;
 import com.android.internal.util.Preconditions;
@@ -50,6 +51,7 @@
     private final ArrayList<RemoteViews> mFieldPresentations;
     private final RemoteViews mPresentation;
     private final IntentSender mAuthentication;
+    @Nullable String mId;
 
     private Dataset(Builder builder) {
         mFieldIds = builder.mFieldIds;
@@ -57,6 +59,7 @@
         mFieldPresentations = builder.mFieldPresentations;
         mPresentation = builder.mPresentation;
         mAuthentication = builder.mAuthentication;
+        mId = builder.mId;
     }
 
     /** @hide */
@@ -89,7 +92,7 @@
     public String toString() {
         if (!DEBUG) return super.toString();
 
-        return new StringBuilder("Dataset [")
+        return new StringBuilder("Dataset " + mId + " [")
                 .append("fieldIds=").append(mFieldIds)
                 .append(", fieldValues=").append(mFieldValues)
                 .append(", fieldPresentations=")
@@ -100,6 +103,17 @@
     }
 
     /**
+     * Gets the id of this dataset.
+     *
+     * @return The id of this dataset or {@code null} if not set
+     *
+     * @hide
+     */
+    public String getId() {
+        return mId;
+    }
+
+    /**
      * A builder for {@link Dataset} objects. You must to provide at least
      * one value for a field or set an authentication intent.
      */
@@ -110,6 +124,7 @@
         private RemoteViews mPresentation;
         private IntentSender mAuthentication;
         private boolean mDestroyed;
+        @Nullable private String mId;
 
         /**
          * Creates a new builder.
@@ -173,6 +188,25 @@
         }
 
         /**
+         * Sets the id for the dataset.
+         *
+         * <p>The id of the last selected dataset can be read from
+         * {@link AutofillService#getFillEventHistory()}. If the id is not set it will not be clear
+         * if a dataset was selected as {@link AutofillService#getFillEventHistory()} uses
+         * {@code null} to indicate that no dataset was selected.
+         *
+         * @param id id for this dataset or {@code null} to unset.
+
+         * @return This builder.
+         */
+        public @NonNull Builder setId(@Nullable String id) {
+            throwIfDestroyed();
+
+            mId = id;
+            return this;
+        }
+
+        /**
          * Sets the value of a field.
          *
          * @param id id returned by {@link
@@ -269,6 +303,7 @@
         parcel.writeTypedArrayList(mFieldValues, flags);
         parcel.writeParcelableList(mFieldPresentations, flags);
         parcel.writeParcelable(mAuthentication, flags);
+        parcel.writeString(mId);
     }
 
     public static final Creator<Dataset> CREATOR = new Creator<Dataset>() {
@@ -295,6 +330,7 @@
                 builder.setValueAndPresentation(id, value, fieldPresentation);
             }
             builder.setAuthentication(parcel.readParcelable(null));
+            builder.setId(parcel.readString());
             return builder.build();
         }
 
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index e8ad14f..7774bdd 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -18,7 +18,6 @@
 
 import android.annotation.Nullable;
 import android.app.Activity;
-import android.os.Bundle;
 import android.os.RemoteException;
 
 /**
@@ -27,17 +26,19 @@
  */
 public final class FillCallback {
     private final IFillCallback mCallback;
+    private final int mRequestId;
     private boolean mCalled;
 
     /** @hide */
-    public FillCallback(IFillCallback callback) {
+    public FillCallback(IFillCallback callback, int requestId) {
         mCallback = callback;
+        mRequestId = requestId;
     }
 
     /**
      * Notifies the Android System that an
-     * {@link AutofillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
-     * int, android.os.CancellationSignal, FillCallback)} was successfully fulfilled by the service.
+     * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+     * FillCallback)} was successfully fulfilled by the service.
      *
      * @param response autofill information for that activity, or {@code null} when the activity
      * cannot be autofilled (for example, if it only contains read-only fields). See
@@ -47,7 +48,7 @@
         assertNotCalled();
         mCalled = true;
         try {
-            mCallback.onSuccess(response);
+            mCallback.onSuccess(response, mRequestId);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         }
@@ -55,9 +56,8 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutofillService#onFillRequest(android.app.assist.AssistStructure,
-     * Bundle, int, android.os.CancellationSignal, FillCallback)}
-     * could not be fulfilled by the service.
+     * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+     * FillCallback)} could not be fulfilled by the service.
      *
      * @param message error message to be displayed to the user.
      */
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
new file mode 100644
index 0000000..2efa08c
--- /dev/null
+++ b/core/java/android/service/autofill/FillContext.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.annotation.NonNull;
+import android.app.assist.AssistStructure;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class represents a context for each fill request made via {@link
+ * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)}.
+ * It contains a snapshot of the UI state, the view ids that were returned by
+ * the {@link AutofillService autofill service} as both required to trigger a save
+ * and optional that can be saved, and the id of the corresponding {@link
+ * FillRequest}.
+ * <p>
+ * This context allows you to inspect the values for the interesting views
+ * in the context they appeared. Also a reference to the corresponding fill
+ * request is useful to store meta-data in the client state bundle passed
+ * to {@link FillResponse.Builder#setClientState(Bundle)} to avoid interpreting
+ * the UI state again while saving.
+ */
+public final class FillContext implements Parcelable {
+    private final int mRequestId;
+    private final @NonNull AssistStructure mStructure;
+
+    /** @hide */
+    public FillContext(int requestId, @NonNull AssistStructure structure) {
+        mRequestId = requestId;
+        mStructure = structure;
+    }
+
+    private FillContext(Parcel parcel) {
+        this(parcel.readInt(), parcel.readParcelable(null));
+    }
+
+    /**
+     * Gets the id of the {@link FillRequest fill request} this context
+     * corresponds to. This is useful to associate your custom client
+     * state with every request to avoid reinterpreting the UI when saving
+     * user data.
+     *
+     * @return The request id.
+     */
+    public int getRequestId() {
+        return mRequestId;
+    }
+
+    /**
+     * @return The screen content.
+     */
+    public AssistStructure getStructure() {
+        return mStructure;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mRequestId);
+        parcel.writeParcelable(mStructure, flags);
+    }
+
+    public static final Parcelable.Creator<FillContext> CREATOR =
+            new Parcelable.Creator<FillContext>() {
+        @Override
+        public FillContext createFromParcel(Parcel parcel) {
+            return new FillContext(parcel);
+        }
+
+        @Override
+        public FillContext[] newArray(int size) {
+            return new FillContext[size];
+        }
+    };
+}
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/core/java/android/service/autofill/FillEventHistory.aidl
similarity index 67%
rename from packages/SystemUI/res/values/dimens_tv.xml
rename to core/java/android/service/autofill/FillEventHistory.aidl
index 30355d4..3c48524 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/core/java/android/service/autofill/FillEventHistory.aidl
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2016, The Android Open Source Project
+/**
+ * Copyright (c) 2017, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
--->
-<resources>
-    <!-- Extra space around the PIP and its outline in PIP onboarding activity  -->
-    <dimen name="tv_pip_bounds_space">3dp</dimen>
-</resources>
+
+package android.service.autofill;
+
+parcelable FillEventHistory;
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
new file mode 100644
index 0000000..3d72fcc
--- /dev/null
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.autofill.AutofillId;
+import android.widget.RemoteViews;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Describes what happened after the latest call to {@link FillCallback#onSuccess(FillResponse)}.
+ */
+public final class FillEventHistory implements Parcelable {
+    /**
+     * Not in parcel. The UID of the {@link AutofillService} that created the {@link FillResponse}.
+     */
+    private final int mServiceUid;
+
+    @Nullable private final Bundle mClientState;
+    @Nullable List<Event> mEvents;
+
+    /**
+     * Gets the UID of the {@link AutofillService} that created the {@link FillResponse}.
+     *
+     * @return The UID of the {@link AutofillService}
+     *
+     * @hide
+     */
+    public int getServiceUid() {
+        return mServiceUid;
+    }
+
+    /**
+     * Returns the client state of the {@link FillResponse}.
+     *
+     * @return The client state set by the last {@link FillResponse}
+     */
+    @Nullable public Bundle getClientState() {
+        return mClientState;
+    }
+
+    /**
+     * Returns the events occurred after the latest call to
+     * {@link FillCallback#onSuccess(FillResponse)}.
+     *
+     * @return The list of events or {@code null} if non occurred.
+     */
+    @Nullable public List<Event> getEvents() {
+        return mEvents;
+    }
+
+    /**
+     * @hide
+     */
+    public void addEvent(Event event) {
+        if (mEvents == null) {
+            mEvents = new ArrayList<>(1);
+        }
+        mEvents.add(event);
+    }
+
+    /**
+     * @hide
+     */
+    public FillEventHistory(int serviceUid, @Nullable Bundle clientState) {
+        mClientState = clientState;
+        mServiceUid = serviceUid;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeBundle(mClientState);
+
+        if (mEvents == null) {
+            dest.writeInt(0);
+        } else {
+            dest.writeInt(mEvents.size());
+
+            int numEvents = mEvents.size();
+            for (int i = 0; i < numEvents; i++) {
+                Event event = mEvents.get(i);
+                dest.writeInt(event.getType());
+                dest.writeString(event.getDatasetId());
+            }
+        }
+    }
+
+    /**
+     * Description of an event that occured after the latest call to
+     * {@link FillCallback#onSuccess(FillResponse)}.
+     */
+    public static final class Event {
+        /**
+         * A dataset was selected. The dataset selected can be read from {@link #getDatasetId()}.
+         */
+        public static final int TYPE_DATASET_SELECTED = 0;
+
+        /**
+         * A {@link Dataset.Builder#setAuthentication(IntentSender) dataset authentication} was
+         * selected. The dataset authenticated can be read from {@link #getDatasetId()}.
+         */
+        public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1;
+
+        /**
+         * A {@link FillResponse.Builder#setAuthentication(AutofillId[], IntentSender, RemoteViews)
+         * fill response authentication} was selected.
+         */
+        public static final int TYPE_AUTHENTICATION_SELECTED = 2;
+
+        /** A save UI was shown. */
+        public static final int TYPE_SAVE_SHOWN = 3;
+
+        /** @hide */
+        @IntDef(
+                value = {TYPE_DATASET_SELECTED,
+                        TYPE_DATASET_AUTHENTICATION_SELECTED,
+                        TYPE_AUTHENTICATION_SELECTED,
+                        TYPE_SAVE_SHOWN})
+        @Retention(RetentionPolicy.SOURCE)
+        @interface EventIds{}
+
+        @EventIds private final int mEventType;
+        @Nullable private final String mDatasetId;
+
+        /**
+         * Returns the type of the event.
+         *
+         * @return The type of the event
+         */
+        public int getType() {
+            return mEventType;
+        }
+
+        /**
+         * Returns the id of dataset the id was on.
+         *
+         * @return The id of dataset, or {@code null} the event is not associated with a dataset.
+         */
+        @Nullable public String getDatasetId() {
+            return mDatasetId;
+        }
+
+        /**
+         * Creates a new event.
+         *
+         * @param eventType The type of the event
+         * @param datasetId The dataset the event was on, or {@code null} if the event was on the
+         *                  whole response.
+         *
+         * @hide
+         */
+        public Event(int eventType, String datasetId) {
+            mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_SAVE_SHOWN,
+                    "eventType");
+            mDatasetId = datasetId;
+        }
+    }
+
+    public static final Parcelable.Creator<FillEventHistory> CREATOR =
+            new Parcelable.Creator<FillEventHistory>() {
+                @Override
+                public FillEventHistory createFromParcel(Parcel parcel) {
+                    FillEventHistory selection = new FillEventHistory(0, parcel.readBundle());
+
+                    int numEvents = parcel.readInt();
+                    for (int i = 0; i < numEvents; i++) {
+                        selection.addEvent(new Event(parcel.readInt(), parcel.readString()));
+                    }
+
+                    return selection;
+                }
+
+                @Override
+                public FillEventHistory[] newArray(int size) {
+                    return new FillEventHistory[size];
+                }
+            };
+}
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/core/java/android/service/autofill/FillRequest.aidl
similarity index 67%
copy from packages/SystemUI/res/values/dimens_tv.xml
copy to core/java/android/service/autofill/FillRequest.aidl
index 30355d4..2b1a8fe 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/core/java/android/service/autofill/FillRequest.aidl
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2016, The Android Open Source Project
+/**
+ * Copyright (c) 2017, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
--->
-<resources>
-    <!-- Extra space around the PIP and its outline in PIP onboarding activity  -->
-    <dimen name="tv_pip_bounds_space">3dp</dimen>
-</resources>
+
+package android.service.autofill;
+
+parcelable FillRequest;
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
new file mode 100644
index 0000000..aa6db4d
--- /dev/null
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.assist.AssistStructure;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class represents a request to an {@link AutofillService autofill provider}
+ * to interpret the screen and provide information to the system which views are
+ * interesting for saving and what are the possible ways to fill the inputs on
+ * the screen if applicable.
+ *
+ * @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
+ */
+public final class FillRequest implements Parcelable {
+    private static AtomicInteger sIdCounter = new AtomicInteger();
+
+    /**
+     * Indicates autofill was explicitly requested by the user.
+     */
+    public static final int FLAG_MANUAL_REQUEST = 0x1;
+
+    /** @hide */
+    @IntDef(
+        flag = true,
+        value = {FLAG_MANUAL_REQUEST})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface RequestFlags{}
+
+    private final int mId;
+    private final @RequestFlags int mFlags;
+    private final @NonNull AssistStructure mStructure;
+    private final @Nullable Bundle mClientState;
+
+    /** @hide */
+    public FillRequest(@NonNull AssistStructure structure,
+            @Nullable Bundle clientState, @RequestFlags int flags) {
+        this(sIdCounter.incrementAndGet(), structure, clientState, flags);
+    }
+
+    private FillRequest(@NonNull Parcel parcel) {
+        mId = parcel.readInt();
+        mStructure = parcel.readParcelable(null);
+        mClientState = parcel.readBundle();
+        mFlags = parcel.readInt();
+    }
+
+    private FillRequest(int id, @NonNull AssistStructure structure,
+            @Nullable Bundle clientState, @RequestFlags int flags) {
+        mId = id;
+        mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST);
+        mStructure = Preconditions.checkNotNull(structure, "structure");
+        mClientState = clientState;
+    }
+
+    /**
+     * @return The unique id of this request.
+     */
+    public int getId() {
+        return mId;
+    }
+
+    /**
+     * @return The flags associated with this request.
+     *
+     * @see #FLAG_MANUAL_REQUEST
+     */
+    public @RequestFlags int getFlags() {
+        return mFlags;
+    }
+
+    /**
+     * @return The structure capturing the UI state.
+     */
+    public @NonNull AssistStructure getStructure() {
+        return mStructure;
+    }
+
+    /**
+     * Gets the extra client state returned from the last {@link
+     * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
+     * fill request}.
+     * <p>
+     * Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+     * save request} is made the client state is cleared.
+     *
+     * @return The client state.
+     */
+    public @Nullable Bundle getClientState() {
+        return mClientState;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mId);
+        parcel.writeParcelable(mStructure, flags);
+        parcel.writeBundle(mClientState);
+        parcel.writeInt(mFlags);
+    }
+
+    public static final Parcelable.Creator<FillRequest> CREATOR =
+            new Parcelable.Creator<FillRequest>() {
+        @Override
+        public FillRequest createFromParcel(Parcel parcel) {
+            return new FillRequest(parcel);
+        }
+
+        @Override
+        public FillRequest[] newArray(int size) {
+            return new FillRequest[size];
+        }
+    };
+}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index eab0d4c..0025365 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -32,8 +32,7 @@
 
 /**
  * Response for a {@link
- * AutofillService#onFillRequest(android.app.assist.AssistStructure,
- * Bundle, int, android.os.CancellationSignal, FillCallback)}.
+ * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}.
  *
  * <p>The response typically contains one or more {@link Dataset}s, each representing a set of
  * fields that can be autofilled together, and the Android system displays a dataset picker UI
@@ -132,25 +131,25 @@
  */
 public final class FillResponse implements Parcelable {
 
-    private final ArrayList<Dataset> mDatasets;
-    private final SaveInfo mSaveInfo;
-    private final Bundle mExtras;
-    private final RemoteViews mPresentation;
-    private final IntentSender mAuthentication;
-    private AutofillId[] mAuthenticationIds;
+    private final @Nullable ArrayList<Dataset> mDatasets;
+    private final @Nullable SaveInfo mSaveInfo;
+    private final @Nullable Bundle mClientState;
+    private final @Nullable RemoteViews mPresentation;
+    private final @Nullable IntentSender mAuthentication;
+    private final @Nullable AutofillId[] mAuthenticationIds;
 
     private FillResponse(@NonNull Builder builder) {
         mDatasets = builder.mDatasets;
         mSaveInfo = builder.mSaveInfo;
-        mExtras = builder.mExtras;
+        mClientState = builder.mCLientState;
         mPresentation = builder.mPresentation;
         mAuthentication = builder.mAuthentication;
         mAuthenticationIds = builder.mAuthenticationIds;
     }
 
     /** @hide */
-    public @Nullable Bundle getExtras() {
-        return mExtras;
+    public @Nullable Bundle getClientState() {
+        return mClientState;
     }
 
     /** @hide */
@@ -185,7 +184,7 @@
     public static final class Builder {
         private ArrayList<Dataset> mDatasets;
         private SaveInfo mSaveInfo;
-        private Bundle mExtras;
+        private Bundle mCLientState;
         private RemoteViews mPresentation;
         private IntentSender mAuthentication;
         private AutofillId[] mAuthenticationIds;
@@ -258,6 +257,19 @@
         }
 
         /**
+         * Specifies views that should not trigger new
+         * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+         * FillCallback)} requests.
+         *
+         * <p>This is typically used when the service cannot autofill the view; for example, an
+         * {@code EditText} representing a captcha.
+         */
+        public Builder setIgnoredIds(AutofillId...ids) {
+            // TODO: implement
+            return this;
+        }
+
+        /**
          * Adds a new {@link Dataset} to this response.
          *
          * @return This builder.
@@ -290,22 +302,35 @@
         }
 
         /**
-         * Sets a {@link Bundle} that will be passed to subsequent APIs that
+         * @deprecated Use {@link #setClientState(Bundle)} instead.
+         */
+        @Deprecated
+        public Builder setExtras(@Nullable Bundle extras) {
+            throwIfDestroyed();
+            mCLientState = extras;
+            return this;
+        }
+
+        /**
+         * Sets a {@link Bundle state} that will be passed to subsequent APIs that
          * manipulate this response. For example, they are passed to subsequent
-         * calls to {@link AutofillService#onFillRequest(
-         * android.app.assist.AssistStructure, Bundle, int,
-         * android.os.CancellationSignal, FillCallback)} and {@link AutofillService#onSaveRequest(
-         * android.app.assist.AssistStructure, Bundle, SaveCallback)}.
+         * calls to {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
+         * FillCallback)} and {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}.
+         * You can use this to store intermediate state that is persistent across multiple
+         * fill requests and the subsequent save request.
          *
          * <p>If this method is called on multiple {@link FillResponse} objects for the same
          * activity, just the latest bundle is passed back to the service.
          *
-         * @param extras The response extras.
+         * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+         * save request} is made the client state is cleared.
+         *
+         * @param clientState The custom client state.
          * @return This builder.
          */
-        public Builder setExtras(Bundle extras) {
+        public Builder setClientState(@Nullable Bundle clientState) {
             throwIfDestroyed();
-            mExtras = extras;
+            mCLientState = clientState;
             return this;
         }
 
@@ -344,7 +369,7 @@
         return new StringBuilder(
                 "FillResponse: [datasets=").append(mDatasets)
                 .append(", saveInfo=").append(mSaveInfo)
-                .append(", hasExtras=").append(mExtras != null)
+                .append(", clientState=").append(mClientState != null)
                 .append(", hasPresentation=").append(mPresentation != null)
                 .append(", hasAuthentication=").append(mAuthentication != null)
                 .append(", authenticationSize=").append(mAuthenticationIds != null
@@ -365,7 +390,7 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeTypedArrayList(mDatasets, flags);
         parcel.writeParcelable(mSaveInfo, flags);
-        parcel.writeParcelable(mExtras, flags);
+        parcel.writeParcelable(mClientState, flags);
         parcel.writeParcelableArray(mAuthenticationIds, flags);
         parcel.writeParcelable(mAuthentication, flags);
         parcel.writeParcelable(mPresentation, flags);
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index a8d86ca..23a1a3f 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -16,10 +16,10 @@
 
 package android.service.autofill;
 
-import android.app.assist.AssistStructure;
-import android.os.Bundle;
+import android.service.autofill.FillRequest;
 import android.service.autofill.IFillCallback;
 import android.service.autofill.ISaveCallback;
+import android.service.autofill.SaveRequest;
 import com.android.internal.os.IResultReceiver;
 
 /**
@@ -29,8 +29,6 @@
  */
 oneway interface IAutoFillService {
     void onConnectedStateChanged(boolean connected);
-    void onFillRequest(in AssistStructure structure, in Bundle extras,
-            in IFillCallback callback, int flags);
-    void onSaveRequest(in AssistStructure structure, in Bundle extras,
-            in ISaveCallback callback);
+    void onFillRequest(in FillRequest request, in IFillCallback callback);
+    void onSaveRequest(in SaveRequest request, in ISaveCallback callback);
 }
diff --git a/core/java/android/service/autofill/IFillCallback.aidl b/core/java/android/service/autofill/IFillCallback.aidl
index 2bb3e9a..688ac84 100644
--- a/core/java/android/service/autofill/IFillCallback.aidl
+++ b/core/java/android/service/autofill/IFillCallback.aidl
@@ -27,6 +27,6 @@
  */
 interface IFillCallback {
     void onCancellable(in ICancellationSignal cancellation);
-    void onSuccess(in FillResponse response);
+    void onSuccess(in FillResponse response, int requestId);
     void onFailure(CharSequence message);
 }
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
index 2c4ba6c..3a70138 100644
--- a/core/java/android/service/autofill/SaveCallback.java
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -17,7 +17,6 @@
 package android.service.autofill;
 
 import android.app.Activity;
-import android.os.Bundle;
 import android.os.RemoteException;
 
 /**
@@ -35,8 +34,8 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutofillService#onSaveRequest (android.app.assist.AssistStructure, Bundle,
-     * SaveCallback)} was successfully fulfilled by the service.
+     * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} was successfully fulfilled
+     * by the service.
      *
      * @throws RuntimeException if an error occurred while calling the Android System.
      */
@@ -52,8 +51,8 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
-     * SaveCallback)} could not be fulfilled by the service.
+     * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} could not be fulfilled
+     * by the service.
      *
      * @param message error message to be displayed to the user.
      *
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 4ad0f08..f796444 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -21,6 +21,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.assist.AssistStructure;
 import android.content.IntentSender;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -39,7 +40,7 @@
 /**
  * Information used to indicate that an {@link AutofillService} is interested on saving the
  * user-inputed data for future use, through a
- * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, SaveCallback)}
+ * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
  * call.
  *
  * <p>A {@link SaveInfo} is always associated with a {@link FillResponse}, and it contains at least
@@ -93,7 +94,7 @@
  * </pre>
  *
  * The
- * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, SaveCallback)}
+ * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
  * is triggered after a call to {@link AutofillManager#commit()}, but only when all conditions
  * below are met:
  *
@@ -140,12 +141,39 @@
      */
     public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10;
 
-    private final int mType;
+    /** @hide */
+    @IntDef(
+       flag = true,
+       value = {
+               SAVE_DATA_TYPE_GENERIC,
+               SAVE_DATA_TYPE_PASSWORD,
+               SAVE_DATA_TYPE_ADDRESS,
+               SAVE_DATA_TYPE_CREDIT_CARD,
+               SAVE_DATA_TYPE_EMAIL_ADDRESS})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface SaveDataType{}
+
+    /**
+     * Usually {@link AutofillService#onSaveRequest(AssistStructure, Bundle, SaveCallback)}
+     * is called once the activity finishes. If this flag is set it is called once all saved views
+     * become invisible.
+     */
+    public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 0x1;
+
+    /** @hide */
+    @IntDef(
+            flag = true,
+            value = {FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface SaveInfoFlags{}
+
+    private final @SaveDataType int mType;
     private final CharSequence mNegativeActionTitle;
     private final IntentSender mNegativeActionListener;
     private final AutofillId[] mRequiredIds;
     private final AutofillId[] mOptionalIds;
     private final CharSequence mDescription;
+    private final int mFlags;
 
     private SaveInfo(Builder builder) {
         mType = builder.mType;
@@ -154,6 +182,7 @@
         mRequiredIds = builder.mRequiredIds;
         mOptionalIds = builder.mOptionalIds;
         mDescription = builder.mDescription;
+        mFlags = builder.mFlags;
     }
 
     /** @hide */
@@ -177,11 +206,16 @@
     }
 
     /** @hide */
-    public int getType() {
+    public @SaveDataType int getType() {
         return mType;
     }
 
     /** @hide */
+    public @SaveInfoFlags int getFlags() {
+        return mFlags;
+    }
+
+    /** @hide */
     public CharSequence getDescription() {
         return mDescription;
     }
@@ -191,7 +225,7 @@
      */
     public static final class Builder {
 
-        private final int mType;
+        private final @SaveDataType int mType;
         private CharSequence mNegativeActionTitle;
         private IntentSender mNegativeActionListener;
         // TODO(b/33197203): make mRequiredIds final once addSavableIds() is gone
@@ -199,6 +233,7 @@
         private AutofillId[] mOptionalIds;
         private CharSequence mDescription;
         private boolean mDestroyed;
+        private int mFlags;
 
         /**
          * Creates a new builder.
@@ -215,7 +250,7 @@
          *
          * @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty.
          */
-        public Builder(int type, @NonNull AutofillId[] requiredIds) {
+        public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) {
             if (false) {// TODO(b/33197203): re-move when clients use it
             Preconditions.checkArgument(requiredIds != null && requiredIds.length > 0,
                     "must have at least one required id: " + Arrays.toString(requiredIds));
@@ -230,7 +265,7 @@
          * // TODO(b/33197203): make sure is removed when clients migrated
          */
         @Deprecated
-        public Builder(int type) {
+        public Builder(@SaveDataType int type) {
             this(type, null);
         }
 
@@ -247,6 +282,19 @@
         }
 
         /**
+         * Set flags changing the save behavior.
+         *
+         * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} or 0.
+         * @return This builder.
+         */
+        public @NonNull Builder setFlags(@SaveInfoFlags int flags) {
+            throwIfDestroyed();
+
+            mFlags = Preconditions.checkFlagsArgument(flags, FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE);
+            return this;
+        }
+
+        /**
          * Sets the ids of additional, optional views the service would be interested to save.
          *
          * <p>See {@link SaveInfo} for more info.
@@ -342,6 +390,7 @@
                 .append(", requiredIds=").append(Arrays.toString(mRequiredIds))
                 .append(", optionalIds=").append(Arrays.toString(mOptionalIds))
                 .append(", description=").append(mDescription)
+                .append(", mFlags=").append(mFlags)
                 .append("]").toString();
     }
 
@@ -362,6 +411,7 @@
         parcel.writeParcelable(mNegativeActionListener, flags);
         parcel.writeParcelableArray(mOptionalIds, flags);
         parcel.writeCharSequence(mDescription);
+        parcel.writeInt(mFlags);
     }
 
     public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
@@ -375,6 +425,7 @@
             builder.setNegativeAction(parcel.readCharSequence(), parcel.readParcelable(null));
             builder.setOptionalIds(parcel.readParcelableArray(null, AutofillId.class));
             builder.setDescription(parcel.readCharSequence());
+            builder.setFlags(parcel.readInt());
             return builder.build();
         }
 
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/core/java/android/service/autofill/SaveRequest.aidl
similarity index 67%
copy from packages/SystemUI/res/values/dimens_tv.xml
copy to core/java/android/service/autofill/SaveRequest.aidl
index 30355d4..7789b577 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/core/java/android/service/autofill/SaveRequest.aidl
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2016, The Android Open Source Project
+/**
+ * Copyright (c) 2017, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,8 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
--->
-<resources>
-    <!-- Extra space around the PIP and its outline in PIP onboarding activity  -->
-    <dimen name="tv_pip_bounds_space">3dp</dimen>
-</resources>
+
+package android.service.autofill;
+
+parcelable SaveRequest;
diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java
new file mode 100644
index 0000000..9de9315
--- /dev/null
+++ b/core/java/android/service/autofill/SaveRequest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Parcel;
+import android.os.Parcelable;
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class represents a request to an {@link AutofillService
+ * autofill provider} to save applicable data entered by the user.
+ *
+ * @see AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+ */
+public final class SaveRequest implements Parcelable {
+    private final @NonNull ArrayList<FillContext> mFillContexts;
+    private final @Nullable Bundle mClientState;
+
+    /** @hide */
+    public SaveRequest(@NonNull ArrayList<FillContext> fillContexts,
+            @Nullable Bundle clientState) {
+        mFillContexts = Preconditions.checkNotNull(fillContexts, "fillContexts");
+        mClientState = clientState;
+    }
+
+    private SaveRequest(@NonNull Parcel parcel) {
+        this(parcel.readTypedArrayList(null), parcel.readBundle());
+    }
+
+    /**
+     * @return The contexts associated with each previous fill request.
+     */
+    public @NonNull List<FillContext> getFillContexts() {
+        return mFillContexts;
+    }
+
+    /**
+     * Gets the extra client state returned from the last {@link
+     * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)}
+     * fill request}.
+     *
+     * @return The client state.
+     */
+    public @Nullable Bundle getClientState() {
+        return mClientState;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeTypedArrayList(mFillContexts, flags);
+        parcel.writeBundle(mClientState);
+    }
+
+    public static final Creator<SaveRequest> CREATOR =
+            new Creator<SaveRequest>() {
+        @Override
+        public SaveRequest createFromParcel(Parcel parcel) {
+            return new SaveRequest(parcel);
+        }
+
+        @Override
+        public SaveRequest[] newArray(int size) {
+            return new SaveRequest[size];
+        }
+    };
+}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 94505d3..6a15ade 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -462,7 +462,7 @@
      * @return The view if found or null otherwise.
      */
     @Nullable
-    public View findViewById(@IdRes int id) {
+    public <T extends View> T findViewById(@IdRes int id) {
         return getWindow().findViewById(id);
     }
 
diff --git a/core/java/android/service/euicc/DownloadResult.java b/core/java/android/service/euicc/DownloadResult.java
index 0aa55fb..4e2af53 100644
--- a/core/java/android/service/euicc/DownloadResult.java
+++ b/core/java/android/service/euicc/DownloadResult.java
@@ -46,14 +46,14 @@
     @IntDef({
             RESULT_OK,
             RESULT_GENERIC_ERROR,
-            RESULT_MUST_DEACTIVATE_REMOVABLE_SIM,
+            RESULT_MUST_DEACTIVATE_SIM,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ResultCode {}
 
     public static final int RESULT_OK = 0;
     public static final int RESULT_GENERIC_ERROR = 1;
-    public static final int RESULT_MUST_DEACTIVATE_REMOVABLE_SIM = 2;
+    public static final int RESULT_MUST_DEACTIVATE_SIM = 2;
 
     /** Result of the operation - one of the RESULT_* constants. */
     public final @ResultCode int result;
@@ -83,11 +83,10 @@
     }
 
     /**
-     * Return a result indicating that the removable SIM must be deactivated to perform the
-     * operation.
+     * Return a result indicating that an active SIM must be deactivated to perform the operation.
      */
-    public static DownloadResult mustDeactivateRemovableSim() {
-        return new DownloadResult(RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, 0);
+    public static DownloadResult mustDeactivateSim() {
+        return new DownloadResult(RESULT_MUST_DEACTIVATE_SIM, 0);
     }
 
     /**
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index 6407507..03aa967 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -21,6 +21,7 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.telephony.euicc.DownloadableSubscription;
+import android.util.ArraySet;
 
 /**
  * Service interface linking the system with an eUICC local profile assistant (LPA) application.
@@ -74,6 +75,33 @@
     public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION =
             "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
 
+    // LUI resolution actions. These are called by the platform to resolve errors in situations that
+    // require user interaction.
+    // TODO(b/33075886): Define extras for any input parameters to these dialogs once they are
+    // more scoped out.
+    /** Alert the user that this action will result in an active SIM being deactivated. */
+    public static final String ACTION_RESOLVE_DEACTIVATE_SIM =
+            "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
+    /**
+     * Alert the user about a download/switch being done for an app that doesn't currently have
+     * carrier privileges.
+     */
+    public static final String ACTION_RESOLVE_NO_PRIVILEGES =
+            "android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
+    /**
+     * List of all valid resolution actions for validation purposes.
+     * @hide
+     */
+    public static final ArraySet<String> RESOLUTION_ACTIONS;
+    static {
+        RESOLUTION_ACTIONS = new ArraySet<>();
+        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM);
+        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES);
+    }
+
+    /** Boolean extra for resolution actions indicating whether the user granted consent. */
+    public static final String RESOLUTION_EXTRA_CONSENT = "consent";
+
     private final IEuiccService.Stub mStubWrapper;
 
     public EuiccService() {
@@ -107,11 +135,15 @@
      * @param slotId ID of the SIM slot to use when starting the download. This is currently not
      *     populated but is here to future-proof the APIs.
      * @param subscription A subscription whose metadata needs to be populated.
+     * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
+     *     eUICC, perform this action automatically. Otherwise,
+     *     {@link GetDownloadableSubscriptionMetadataResult#mustDeactivateSim()} should be returned
+     *     to allow the user to consent to this operation first.
      * @return The result of the operation.
      * @see android.telephony.euicc.EuiccManager#getDownloadableSubscriptionMetadata
      */
     public abstract GetDownloadableSubscriptionMetadataResult getDownloadableSubscriptionMetadata(
-            int slotId, DownloadableSubscription subscription);
+            int slotId, DownloadableSubscription subscription, boolean forceDeactivateSim);
 
     /**
      * Download the given subscription.
@@ -121,11 +153,16 @@
      * @param subscription The subscription to download.
      * @param switchAfterDownload If true, the subscription should be enabled upon successful
      *     download.
+     * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
+     *     eUICC, perform this action automatically. Otherwise,
+     *     {@link DownloadResult#mustDeactivateSim()} should be returned to allow the user to
+     *     consent to this operation first.
      * @return the result of the download operation.
      * @see android.telephony.euicc.EuiccManager#downloadSubscription
      */
     public abstract DownloadResult downloadSubscription(int slotId,
-            DownloadableSubscription subscription, boolean switchAfterDownload);
+            DownloadableSubscription subscription, boolean switchAfterDownload,
+            boolean forceDeactivateSim);
 
     /**
      * Wrapper around IEuiccService that forwards calls to implementations of {@link EuiccService}.
@@ -133,9 +170,10 @@
     private class IEuiccServiceWrapper extends IEuiccService.Stub {
         @Override
         public void downloadSubscription(int slotId, DownloadableSubscription subscription,
-                boolean switchAfterDownload, IDownloadSubscriptionCallback callback) {
+                boolean switchAfterDownload, boolean forceDeactivateSim,
+                IDownloadSubscriptionCallback callback) {
             DownloadResult result = EuiccService.this.downloadSubscription(
-                    slotId, subscription, switchAfterDownload);
+                    slotId, subscription, switchAfterDownload, forceDeactivateSim);
             try {
                 callback.onComplete(result);
             } catch (RemoteException e) {
@@ -156,9 +194,11 @@
         @Override
         public void getDownloadableSubscriptionMetadata(int slotId,
                 DownloadableSubscription subscription,
+                boolean forceDeactivateSim,
                 IGetDownloadableSubscriptionMetadataCallback callback) {
             GetDownloadableSubscriptionMetadataResult result =
-                    EuiccService.this.getDownloadableSubscriptionMetadata(slotId, subscription);
+                    EuiccService.this.getDownloadableSubscriptionMetadata(
+                            slotId, subscription, forceDeactivateSim);
             try {
                 callback.onComplete(result);
             } catch (RemoteException e) {
diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
index 04f4980..ca3c159 100644
--- a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
+++ b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java
@@ -49,13 +49,13 @@
     @IntDef({
             RESULT_OK,
             RESULT_GENERIC_ERROR,
-            RESULT_MUST_DEACTIVATE_REMOVABLE_SIM,
+            RESULT_MUST_DEACTIVATE_SIM,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ResultCode {}
 
     public static final int RESULT_OK = 0;
-    public static final int RESULT_MUST_DEACTIVATE_REMOVABLE_SIM = 1;
+    public static final int RESULT_MUST_DEACTIVATE_SIM = 1;
     public static final int RESULT_GENERIC_ERROR = 2;
 
     /** Result of the operation - one of the RESULT_* constants. */
@@ -100,11 +100,10 @@
     }
 
     /**
-     * Return a result indicating that the removable SIM must be deactivated to perform the
-     * operation.
+     * Return a result indicating that an active SIM must be deactivated to perform the operation.
      */
-    public static GetDownloadableSubscriptionMetadataResult mustDeactivateRemovableSim() {
-        return new GetDownloadableSubscriptionMetadataResult(RESULT_MUST_DEACTIVATE_REMOVABLE_SIM,
+    public static GetDownloadableSubscriptionMetadataResult mustDeactivateSim() {
+        return new GetDownloadableSubscriptionMetadataResult(RESULT_MUST_DEACTIVATE_SIM,
                 null /* subscription */, 0 /* detailedCode */);
     }
 
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
index 58fe262..3658d9a 100644
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ b/core/java/android/service/euicc/IEuiccService.aidl
@@ -24,8 +24,9 @@
 /** @hide */
 oneway interface IEuiccService {
     void downloadSubscription(int slotId, in DownloadableSubscription subscription,
-            boolean switchAfterDownload, in IDownloadSubscriptionCallback callback);
+            boolean switchAfterDownload, boolean forceDeactivateSim,
+            in IDownloadSubscriptionCallback callback);
     void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription,
-            in IGetDownloadableSubscriptionMetadataCallback callback);
+            boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback);
     void getEid(int slotId, in IGetEidCallback callback);
 }
\ No newline at end of file
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index dc1a70d..ed44f25 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -18,6 +18,7 @@
 
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
+import android.os.UserHandle;
 import android.service.notification.IStatusBarNotificationHolder;
 import android.service.notification.StatusBarNotification;
 import android.service.notification.NotificationRankingUpdate;
@@ -36,8 +37,8 @@
     void onInterruptionFilterChanged(int interruptionFilter);
 
     // companion device managers only
-    void onNotificationChannelModification(String pkgName, in NotificationChannel channel, int modificationType);
-    void onNotificationChannelGroupModification(String pkgName, in NotificationChannelGroup group, int modificationType);
+    void onNotificationChannelModification(String pkgName, in UserHandle user, in NotificationChannel channel, int modificationType);
+    void onNotificationChannelGroupModification(String pkgName, in UserHandle user, in NotificationChannelGroup group, int modificationType);
 
     // rankers only
     void onNotificationEnqueued(in IStatusBarNotificationHolder notificationHolder);
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 4833be3..00bd304 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -49,6 +49,7 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
@@ -231,25 +232,25 @@
 
     /**
      * Channel or group modification reason provided to
-     * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
-     * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
-     * provided object was created.
+     * {@link #onNotificationChannelModified(String, UserHandle,NotificationChannel, int)} or
+     * {@link #onNotificationChannelGroupModified(String, UserHandle, NotificationChannelGroup,
+     * int)}- the provided object was created.
      */
     public static final int NOTIFICATION_CHANNEL_OR_GROUP_ADDED = 1;
 
     /**
      * Channel or group modification reason provided to
-     * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
-     * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
-     * provided object was updated.
+     * {@link #onNotificationChannelModified(String, UserHandle, NotificationChannel, int)} or
+     * {@link #onNotificationChannelGroupModified(String, UserHandle,NotificationChannelGroup, int)}
+     * - the provided object was updated.
      */
     public static final int NOTIFICATION_CHANNEL_OR_GROUP_UPDATED = 2;
 
     /**
      * Channel or group modification reason provided to
-     * {@link #onNotificationChannelModified(String, NotificationChannel, int)} or
-     * {@link #onNotificationChannelGroupModified(String, NotificationChannelGroup, int)}- the
-     * provided object was deleted.
+     * {@link #onNotificationChannelModified(String, UserHandle, NotificationChannel, int)} or
+     * {@link #onNotificationChannelGroupModified(String, UserHandle, NotificationChannelGroup,
+     * int)}- the provided object was deleted.
      */
     public static final int NOTIFICATION_CHANNEL_OR_GROUP_DELETED = 3;
 
@@ -432,13 +433,14 @@
      * device} in order to receive this callback.
      *
      * @param pkg The package the channel belongs to.
+     * @param user The user on which the change was made.
      * @param channel The channel that has changed.
      * @param modificationType One of {@link #NOTIFICATION_CHANNEL_OR_GROUP_ADDED},
      *                   {@link #NOTIFICATION_CHANNEL_OR_GROUP_UPDATED},
      *                   {@link #NOTIFICATION_CHANNEL_OR_GROUP_DELETED}.
      */
-    public void onNotificationChannelModified(String pkg, NotificationChannel channel,
-            @ChannelOrGroupModificationTypes int modificationType) {
+    public void onNotificationChannelModified(String pkg, UserHandle user,
+            NotificationChannel channel, @ChannelOrGroupModificationTypes int modificationType) {
         // optional
     }
 
@@ -449,13 +451,14 @@
      * device} in order to receive this callback.
      *
      * @param pkg The package the group belongs to.
+     * @param user The user on which the change was made.
      * @param group The group that has changed.
      * @param modificationType One of {@link #NOTIFICATION_CHANNEL_OR_GROUP_ADDED},
      *                   {@link #NOTIFICATION_CHANNEL_OR_GROUP_UPDATED},
      *                   {@link #NOTIFICATION_CHANNEL_OR_GROUP_DELETED}.
      */
-    public void onNotificationChannelGroupModified(String pkg, NotificationChannelGroup group,
-            @ChannelOrGroupModificationTypes int modificationType) {
+    public void onNotificationChannelGroupModified(String pkg, UserHandle user,
+            NotificationChannelGroup group, @ChannelOrGroupModificationTypes int modificationType) {
         // optional
     }
 
@@ -661,21 +664,24 @@
 
 
     /**
-     * Updates a notification channel for a given package. This should only be used to reflect
-     * changes a user has made to the channel via the listener's user interface.
+     * Updates a notification channel for a given package for a given user. This should only be used
+     * to reflect changes a user has made to the channel via the listener's user interface.
      *
+     * <p>This method will throw a security exception if you don't have access to notifications
+     * for the given user.</p>
      * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
      * device} in order to use this method.
      *
      * @param pkg The package the channel belongs to.
+     * @param user The user the channel belongs to.
      * @param channel the channel to update.
      */
-    public final void updateNotificationChannel(@NonNull String pkg,
+    public final void updateNotificationChannel(@NonNull String pkg, @NonNull UserHandle user,
             @NonNull NotificationChannel channel) {
         if (!isBound()) return;
         try {
             getNotificationInterface().updateNotificationChannelFromPrivilegedListener(
-                    mWrapper, pkg, channel);
+                    mWrapper, pkg, user, channel);
         } catch (RemoteException e) {
             Log.v(TAG, "Unable to contact notification manager", e);
             throw e.rethrowFromSystemServer();
@@ -683,19 +689,22 @@
     }
 
     /**
-     * Returns all notification channels belonging to the given package.
+     * Returns all notification channels belonging to the given package for a given user.
      *
+     * <p>This method will throw a security exception if you don't have access to notifications
+     * for the given user.</p>
      * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
      * device} in order to use this method.
      *
      * @param pkg The package to retrieve channels for.
      */
-    public final List<NotificationChannel> getNotificationChannels(@NonNull String pkg) {
+    public final List<NotificationChannel> getNotificationChannels(@NonNull String pkg,
+            @NonNull UserHandle user) {
         if (!isBound()) return null;
         try {
 
             return getNotificationInterface().getNotificationChannelsFromPrivilegedListener(
-                    mWrapper, pkg).getList();
+                    mWrapper, pkg, user).getList();
         } catch (RemoteException e) {
             Log.v(TAG, "Unable to contact notification manager", e);
             throw e.rethrowFromSystemServer();
@@ -703,19 +712,22 @@
     }
 
     /**
-     * Returns all notification channel groups belonging to the given package.
+     * Returns all notification channel groups belonging to the given package for a given user.
      *
+     * <p>This method will throw a security exception if you don't have access to notifications
+     * for the given user.</p>
      * <p>The caller must have {@link CompanionDeviceManager#getAssociations() an associated
      * device} in order to use this method.
      *
      * @param pkg The package to retrieve channel groups for.
      */
-    public final List<NotificationChannelGroup> getNotificationChannelGroups(@NonNull String pkg) {
+    public final List<NotificationChannelGroup> getNotificationChannelGroups(@NonNull String pkg,
+            @NonNull UserHandle user) {
         if (!isBound()) return null;
         try {
 
             return getNotificationInterface().getNotificationChannelGroupsFromPrivilegedListener(
-                    mWrapper, pkg).getList();
+                    mWrapper, pkg, user).getList();
         } catch (RemoteException e) {
             Log.v(TAG, "Unable to contact notification manager", e);
             throw e.rethrowFromSystemServer();
@@ -1252,24 +1264,27 @@
         }
 
         @Override
-        public void onNotificationChannelModification(String pkgName, NotificationChannel channel,
+        public void onNotificationChannelModification(String pkgName, UserHandle user,
+                NotificationChannel channel,
                 @ChannelOrGroupModificationTypes int modificationType) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = pkgName;
-            args.arg2 = channel;
-            args.arg3 = modificationType;
+            args.arg2 = user;
+            args.arg3 = channel;
+            args.arg4 = modificationType;
             mHandler.obtainMessage(
                     MyHandler.MSG_ON_NOTIFICATION_CHANNEL_MODIFIED, args).sendToTarget();
         }
 
         @Override
-        public void onNotificationChannelGroupModification(String pkgName,
+        public void onNotificationChannelGroupModification(String pkgName, UserHandle user,
                 NotificationChannelGroup group,
                 @ChannelOrGroupModificationTypes int modificationType) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = pkgName;
-            args.arg2 = group;
-            args.arg3 = modificationType;
+            args.arg2 = user;
+            args.arg3 = group;
+            args.arg4 = modificationType;
             mHandler.obtainMessage(
                     MyHandler.MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED, args).sendToTarget();
         }
@@ -1841,17 +1856,19 @@
                 case MSG_ON_NOTIFICATION_CHANNEL_MODIFIED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     String pkgName = (String) args.arg1;
-                    NotificationChannel channel = (NotificationChannel) args.arg2;
-                    int modificationType = (int) args.arg3;
-                    onNotificationChannelModified(pkgName, channel, modificationType);
+                    UserHandle user= (UserHandle) args.arg2;
+                    NotificationChannel channel = (NotificationChannel) args.arg3;
+                    int modificationType = (int) args.arg4;
+                    onNotificationChannelModified(pkgName, user, channel, modificationType);
                 } break;
 
                 case MSG_ON_NOTIFICATION_CHANNEL_GROUP_MODIFIED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     String pkgName = (String) args.arg1;
-                    NotificationChannelGroup group = (NotificationChannelGroup) args.arg2;
-                    int modificationType = (int) args.arg3;
-                    onNotificationChannelGroupModified(pkgName, group, modificationType);
+                    UserHandle user = (UserHandle) args.arg2;
+                    NotificationChannelGroup group = (NotificationChannelGroup) args.arg3;
+                    int modificationType = (int) args.arg4;
+                    onNotificationChannelGroupModified(pkgName, user, group, modificationType);
                 } break;
             }
         }
diff --git a/core/java/android/service/oemlock/IOemLockService.aidl b/core/java/android/service/oemlock/IOemLockService.aidl
new file mode 100644
index 0000000..682e7ee
--- /dev/null
+++ b/core/java/android/service/oemlock/IOemLockService.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.oemlock;
+
+/**
+ * Interface for communication with the OemLockService.
+ *
+ * @hide
+ */
+interface IOemLockService {
+    void setOemUnlockAllowedByCarrier(boolean allowed, in byte[] signature);
+    boolean isOemUnlockAllowedByCarrier();
+
+    void setOemUnlockAllowedByUser(boolean allowed);
+    boolean isOemUnlockAllowedByUser();
+
+    boolean canUserAllowOemUnlock();
+    boolean isOemUnlockAllowed();
+    boolean isDeviceOemUnlocked();
+}
diff --git a/core/java/android/service/oemlock/OemLockManager.java b/core/java/android/service/oemlock/OemLockManager.java
new file mode 100644
index 0000000..9e69362
--- /dev/null
+++ b/core/java/android/service/oemlock/OemLockManager.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.oemlock;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+
+/**
+ * Interface for managing the OEM lock on the device.
+ *
+ * This will only be available if the device implements OEM lock protection.
+ *
+ * Multiple actors have an opinion on whether the device can be OEM unlocked and they must all be in
+ * agreement for unlock to be possible.
+ *
+ * @hide
+ */
+@SystemApi
+public class OemLockManager {
+    private IOemLockService mService;
+
+    /** @hide */
+    public OemLockManager(IOemLockService service) {
+        mService = service;
+    }
+
+    /**
+     * Sets whether the carrier has allowed this device to be OEM unlocked.
+     *
+     * Depending on the implementation, the validity of the request might need to be proved. This
+     * can be acheived by passing a signature that the system will use to verify the request is
+     * legitimate.
+     *
+     * All actors involved must agree for OEM unlock to be possible.
+     *
+     * @param allowed Whether the device should be allowed to be unlocked.
+     * @param signature Optional proof of request validity, {@code null} for none.
+     * @throws IllegalArgumentException if a signature is required but was not provided.
+     * @throws SecurityException if the wrong signature was provided.
+     *
+     * @see #isOemUnlockAllowedByCarrier()
+     */
+    public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+        try {
+            mService.setOemUnlockAllowedByCarrier(allowed, signature);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns whether the carrier has allowed this device to be OEM unlocked.
+     * @return Whether OEM unlock is allowed by the carrier, or true if no OEM lock is present.
+     *
+     * @see #setOemUnlockAllowedByCarrier(boolean, byte[])
+     */
+    public boolean isOemUnlockAllowedByCarrier() {
+        try {
+            return mService.isOemUnlockAllowedByCarrier();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets whether the user has allowed this device to be unlocked.
+     *
+     * All actors involved must agree for OEM unlock to be possible.
+     *
+     * @param allowed Whether the device should be allowed to be unlocked.
+     * @throws SecurityException if the user is not allowed to unlock the device.
+     *
+     * @see #isOemUnlockAllowedByUser()
+     */
+    public void setOemUnlockAllowedByUser(boolean allowed) {
+        try {
+            mService.setOemUnlockAllowedByUser(allowed);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns whether, or not, the user has allowed this device to be OEM unlocked.
+     * @return Whether OEM unlock is allowed by the user, or true if no OEM lock is present.
+     *
+     * @see #setOemUnlockAllowedByUser(boolean)
+     */
+    public boolean isOemUnlockAllowedByUser() {
+        try {
+            return mService.isOemUnlockAllowedByUser();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns whether all parties other than the user allow OEM unlock meaning the user can
+     * directly control whether or not the device can be OEM unlocked.
+     *
+     * If this is true, {@link #isOemUnlockAllowedByUser} is the same as {@link #isOemUnlockAllowed}
+     *
+     * @return Whether the user can directly control whether the device can be OEM unlocked.
+     *
+     * @hide
+     */
+    public boolean canUserAllowOemUnlock() {
+        try {
+            return mService.canUserAllowOemUnlock();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @return Whether the bootloader is able to OEM unlock the device.
+     *
+     * @hide
+     */
+    public boolean isOemUnlockAllowed() {
+        try {
+            return mService.isOemUnlockAllowed();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @return Whether the device has been OEM unlocked by the bootloader.
+     *
+     * @hide
+     */
+    public boolean isDeviceOemUnlocked() {
+        try {
+            return mService.isOemUnlockAllowed();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
index cb021bc..326796a 100644
--- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java
+++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java
@@ -146,6 +146,8 @@
 
     /**
      * Writes a byte enabling or disabling the ability to "OEM unlock" the device.
+     *
+     * @deprecated use {@link OemLockManager#setOemUnlockAllowedByUser(boolean)} instead.
      */
     public void setOemUnlockEnabled(boolean enabled) {
         try {
@@ -157,6 +159,8 @@
 
     /**
      * Returns whether or not "OEM unlock" is enabled or disabled on this device.
+     *
+     * @deprecated use {@link OemLockManager#isOemUnlockAllowedByUser()} instead.
      */
     public boolean getOemUnlockEnabled() {
         try {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 6bbb0ff..98780a7 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -16,6 +16,8 @@
 
 package android.service.wallpaper;
 
+import android.annotation.Nullable;
+import android.app.WallpaperColors;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.util.MergedConfiguration;
@@ -542,6 +544,24 @@
          */
         public void onSurfaceDestroyed(SurfaceHolder holder) {
         }
+
+        /**
+         * Notifies the engine that wallpaper colors changed significantly.
+         * This will trigger a {@link #onComputeWallpaperColors()} call.
+         */
+        public void invalidateColors() {
+        }
+
+        /**
+         * Notifies the system about what colors the wallpaper is using.
+         * You might return null if no color information is available at the moment. In that case
+         * you might want to call {@link #invalidateColors()} in a near future.
+         *
+         * @return List of wallpaper colors and their weights.
+         */
+        public @Nullable WallpaperColors onComputeWallpaperColors() {
+            return null;
+        }
         
         protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
             out.print(prefix); out.print("mInitializing="); out.print(mInitializing);
diff --git a/core/java/android/speech/tts/SynthesisCallback.java b/core/java/android/speech/tts/SynthesisCallback.java
index e535cfa..f5e5f4d 100644
--- a/core/java/android/speech/tts/SynthesisCallback.java
+++ b/core/java/android/speech/tts/SynthesisCallback.java
@@ -151,6 +151,9 @@
      * listener ({@link UtteranceProgressListener#onRangeStart}) at the moment that frame has been
      * reached by the playback head.
      *
+     * <p>This information can be used by the client, for example, to highlight ranges of the text
+     * while it is spoken.
+     *
      * <p>The markerInFrames is a frame index into the audio for this synthesis request, i.e. into
      * the concatenation of the audio bytes sent to audioAvailable for this synthesis request. The
      * definition of a frame depends on the format given by {@link #start}. See {@link AudioFormat}
diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java
index 59ee8f3..ef81f12 100644
--- a/core/java/android/speech/tts/UtteranceProgressListener.java
+++ b/core/java/android/speech/tts/UtteranceProgressListener.java
@@ -128,6 +128,9 @@
      * <p>This method is called when the audio is expected to start playing on the speaker. Note
      * that this is different from {@link #onAudioAvailable} which is called as soon as the audio is
      * generated.
+
+     * <p>This information can be used, for example, to highlight ranges of the text while it is
+     * spoken.
      *
      * <p>Only called if the engine supplies timing information by calling {@link
      * SynthesisCallback#rangeStart(int, int, int)}.
diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java
new file mode 100644
index 0000000..b07942f
--- /dev/null
+++ b/core/java/android/util/IconDrawableFactory.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.util;
+
+import android.annotation.UserIdInt;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Utility class to load app drawables with appropriate badging.
+ *
+ * @hide
+ */
+public class IconDrawableFactory {
+
+    protected final Context mContext;
+    protected final PackageManager mPm;
+    protected final UserManager mUm;
+    protected final LauncherIcons mLauncherIcons;
+    protected final boolean mEmbedShadow;
+
+    private IconDrawableFactory(Context context, boolean embedShadow) {
+        mContext = context;
+        mPm = context.getPackageManager();
+        mUm = context.getSystemService(UserManager.class);
+        mLauncherIcons = new LauncherIcons(context);
+        mEmbedShadow = embedShadow;
+    }
+
+    protected boolean needsBadging(ApplicationInfo appInfo, @UserIdInt int userId) {
+        return appInfo.isInstantApp() || mUm.isManagedProfile(userId);
+    }
+
+    public Drawable getBadgedIcon(ApplicationInfo appInfo) {
+        return getBadgedIcon(appInfo, UserHandle.getUserId(appInfo.uid));
+    }
+
+    public Drawable getBadgedIcon(ApplicationInfo appInfo, @UserIdInt int userId) {
+        return getBadgedIcon(appInfo, appInfo, userId);
+    }
+
+    public Drawable getBadgedIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo,
+            @UserIdInt int userId) {
+        Drawable icon = mPm.loadUnbadgedItemIcon(itemInfo, appInfo);
+        if (!mEmbedShadow && !needsBadging(appInfo, userId)) {
+            return icon;
+        }
+
+        // Before badging, add shadow to adaptive icon if needed.
+        icon = mLauncherIcons.wrapIconDrawableWithShadow(icon);
+        if (appInfo.isInstantApp()) {
+            int badgeColor = Resources.getSystem().getColor(
+                    com.android.internal.R.color.instant_app_badge, null);
+            icon = mLauncherIcons.getBadgedDrawable(icon,
+                    com.android.internal.R.drawable.ic_instant_icon_badge_bolt,
+                    badgeColor);
+        }
+        if (mUm.isManagedProfile(userId)) {
+            icon = mLauncherIcons.getBadgedDrawable(icon,
+                    com.android.internal.R.drawable.ic_corp_icon_badge_case,
+                    getUserBadgeColor(mUm, userId));
+        }
+        return icon;
+    }
+
+    // Should have enough colors to cope with UserManagerService.getMaxManagedProfiles()
+    @VisibleForTesting
+    public static final int[] CORP_BADGE_COLORS = new int[] {
+            com.android.internal.R.color.profile_badge_1,
+            com.android.internal.R.color.profile_badge_2,
+            com.android.internal.R.color.profile_badge_3
+    };
+
+    public static int getUserBadgeColor(UserManager um, @UserIdInt int userId) {
+        int badge = um.getManagedProfileBadge(userId);
+        if (badge < 0) {
+            badge = 0;
+        }
+        int resourceId = CORP_BADGE_COLORS[badge % CORP_BADGE_COLORS.length];
+        return Resources.getSystem().getColor(resourceId, null);
+    }
+
+    public static IconDrawableFactory newInstance(Context context) {
+        return new IconDrawableFactory(context, true);
+    }
+
+    public static IconDrawableFactory newInstance(Context context, boolean embedShadow) {
+        return new IconDrawableFactory(context, embedShadow);
+    }
+}
diff --git a/core/java/android/util/LauncherIcons.java b/core/java/android/util/LauncherIcons.java
index e5aa2b5..402bef9 100644
--- a/core/java/android/util/LauncherIcons.java
+++ b/core/java/android/util/LauncherIcons.java
@@ -20,14 +20,12 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.Matrix;
 import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
-import android.graphics.Path;
-import android.graphics.RectF;
+import android.graphics.Rect;
 import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableWrapper;
+import android.graphics.drawable.LayerDrawable;
 
 /**
  * Utility class to handle icon treatments (e.g., shadow generation) for the Launcher icons.
@@ -35,79 +33,152 @@
  */
 public final class LauncherIcons {
 
-    private final Paint mPaint = new Paint();
-    private final Canvas mCanvas = new Canvas();
+    // Percent of actual icon size
+    private static final float ICON_SIZE_BLUR_FACTOR = 0.5f/48;
+    // Percent of actual icon size
+    private static final float ICON_SIZE_KEY_SHADOW_DELTA_FACTOR = 1f/48;
 
     private static final int KEY_SHADOW_ALPHA = 61;
     private static final int AMBIENT_SHADOW_ALPHA = 30;
-    private static final float BLUR_FACTOR = 0.5f / 48;
-    private int mShadowInset;
-    private Bitmap mShadowBitmap;
-    private int mIconSize;
-    private Resources mRes;
+
+    private final SparseArray<Bitmap> mShadowCache = new SparseArray<>();
+    private final int mIconSize;
+    private final Resources mRes;
 
     public LauncherIcons(Context context) {
         mRes = context.getResources();
-        DisplayMetrics metrics = mRes.getDisplayMetrics();
-        mShadowInset = (int) metrics.density / DisplayMetrics.DENSITY_DEFAULT;
-        mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG,
-            Paint.FILTER_BITMAP_FLAG));
-        mIconSize = (int) mRes.getDimensionPixelSize(android.R.dimen.app_icon_size);
-    }
-
-    /**
-     * Draw the drawable into a bitmap.
-     */
-    public Bitmap createIconBitmap(Drawable icon) {
-        final Bitmap bitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ARGB_8888);
-        mPaint.setAlpha(255);
-        mCanvas.setBitmap(bitmap);
-        int iconInset = 0;
-        if (mShadowBitmap != null) {
-            mCanvas.drawBitmap(mShadowBitmap, 0, 0, mPaint);
-            iconInset = mShadowInset;
-        }
-
-        icon.setBounds(iconInset, iconInset, mIconSize - iconInset,
-            mIconSize - iconInset);
-        icon.draw(mCanvas);
-        mCanvas.setBitmap(null);
-        return bitmap;
+        mIconSize = mRes.getDimensionPixelSize(android.R.dimen.app_icon_size);
     }
 
     public Drawable wrapIconDrawableWithShadow(Drawable drawable) {
         if (!(drawable instanceof AdaptiveIconDrawable)) {
             return drawable;
         }
-        AdaptiveIconDrawable d =
-            (AdaptiveIconDrawable) drawable.getConstantState().newDrawable().mutate();
-        getShadowBitmap(d);
-        Bitmap iconbitmap = createIconBitmap(d);
-        return new BitmapDrawable(mRes, iconbitmap);
+        Bitmap shadow = getShadowBitmap((AdaptiveIconDrawable) drawable);
+        return new ShadowDrawable(shadow, drawable);
     }
 
     private Bitmap getShadowBitmap(AdaptiveIconDrawable d) {
-        if (mShadowBitmap != null) {
-            return mShadowBitmap;
+        int shadowSize = Math.max(mIconSize, d.getIntrinsicHeight());
+        synchronized (mShadowCache) {
+            Bitmap shadow = mShadowCache.get(shadowSize);
+            if (shadow != null) {
+                return shadow;
+            }
         }
 
-        int shadowSize = mIconSize - mShadowInset;
-        mShadowBitmap = Bitmap.createBitmap(mIconSize, mIconSize, Bitmap.Config.ALPHA_8);
-        mCanvas.setBitmap(mShadowBitmap);
+        d.setBounds(0, 0, shadowSize, shadowSize);
 
-        // Draw key shadow
-        mPaint.setColor(Color.TRANSPARENT);
-        float blur = BLUR_FACTOR * mIconSize;
-        mPaint.setShadowLayer(blur, 0, mShadowInset, KEY_SHADOW_ALPHA << 24);
-        d.setBounds(mShadowInset, mShadowInset, mIconSize - mShadowInset, mIconSize - mShadowInset);
-        mCanvas.drawPath(d.getIconMask(), mPaint);
+        float blur = ICON_SIZE_BLUR_FACTOR * shadowSize;
+        float keyShadowDistance = ICON_SIZE_KEY_SHADOW_DELTA_FACTOR * shadowSize;
+
+        int bitmapSize = (int) (shadowSize + 2 * blur + keyShadowDistance);
+        Bitmap shadow = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888);
+
+        Canvas canvas = new Canvas(shadow);
+        canvas.translate(blur + keyShadowDistance / 2, blur);
+
+        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        paint.setColor(Color.TRANSPARENT);
 
         // Draw ambient shadow
-        mPaint.setShadowLayer(blur, 0, 0, AMBIENT_SHADOW_ALPHA << 24);
-        d.setBounds(mShadowInset, 2 * mShadowInset, mIconSize - mShadowInset, mIconSize);
-        mCanvas.drawPath(d.getIconMask(), mPaint);
-        mPaint.clearShadowLayer();
+        paint.setShadowLayer(blur, 0, 0, AMBIENT_SHADOW_ALPHA << 24);
+        canvas.drawPath(d.getIconMask(), paint);
 
-        return mShadowBitmap;
+        // Draw key shadow
+        canvas.translate(0, keyShadowDistance);
+        paint.setShadowLayer(blur, 0, 0, KEY_SHADOW_ALPHA << 24);
+        canvas.drawPath(d.getIconMask(), paint);
+
+        canvas.setBitmap(null);
+        synchronized (mShadowCache) {
+            mShadowCache.put(shadowSize, shadow);
+        }
+        return shadow;
+    }
+
+    public Drawable getBadgeDrawable(int foregroundRes, int backgroundColor) {
+        return getBadgedDrawable(null, foregroundRes, backgroundColor);
+    }
+
+    public Drawable getBadgedDrawable(Drawable base, int foregroundRes, int backgroundColor) {
+        Resources sysRes = Resources.getSystem();
+
+        Drawable badgeShadow = sysRes.getDrawable(
+                com.android.internal.R.drawable.ic_corp_icon_badge_shadow);
+
+        Drawable badgeColor = sysRes.getDrawable(
+                com.android.internal.R.drawable.ic_corp_icon_badge_color)
+                .getConstantState().newDrawable().mutate();
+        badgeColor.setTint(backgroundColor);
+
+        Drawable badgeForeground = sysRes.getDrawable(foregroundRes);
+
+        Drawable[] drawables = base == null
+                ? new Drawable[] {badgeShadow, badgeColor, badgeForeground }
+                : new Drawable[] {base, badgeShadow, badgeColor, badgeForeground };
+        return new LayerDrawable(drawables);
+    }
+
+    /**
+     * A drawable which draws a shadow bitmap behind a drawable
+     */
+    private static class ShadowDrawable extends DrawableWrapper {
+
+        final MyConstantState mState;
+
+        public ShadowDrawable(Bitmap shadow, Drawable dr) {
+            super(dr);
+            mState = new MyConstantState(shadow, dr.getConstantState());
+        }
+
+        ShadowDrawable(MyConstantState state) {
+            super(state.mChildState.newDrawable());
+            mState = state;
+        }
+
+        @Override
+        public ConstantState getConstantState() {
+            return mState;
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            Rect bounds = getBounds();
+            canvas.drawBitmap(mState.mShadow, null, bounds, mState.mPaint);
+            canvas.save();
+            // Ratio of child drawable size to shadow bitmap size
+            float factor = 1 / (1 + 2 * ICON_SIZE_BLUR_FACTOR + ICON_SIZE_KEY_SHADOW_DELTA_FACTOR);
+
+            canvas.translate(
+                    bounds.width() * factor *
+                            (ICON_SIZE_BLUR_FACTOR + ICON_SIZE_KEY_SHADOW_DELTA_FACTOR / 2),
+                    bounds.height() * factor * ICON_SIZE_BLUR_FACTOR);
+            canvas.scale(factor, factor);
+            super.draw(canvas);
+            canvas.restore();
+        }
+
+        private static class MyConstantState extends ConstantState {
+
+            final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+            final Bitmap mShadow;
+            final ConstantState mChildState;
+
+            MyConstantState(Bitmap shadow, ConstantState childState) {
+                mShadow = shadow;
+                mChildState = childState;
+            }
+
+            @Override
+            public Drawable newDrawable() {
+                return new ShadowDrawable(this);
+            }
+
+            @Override
+            public int getChangingConfigurations() {
+                return mChildState.getChangingConfigurations();
+            }
+        }
     }
 }
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 4ae5a29..2c9bb66 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -187,6 +187,27 @@
     /**
      * If the value came from a resource, these are the configurations for
      * which its contents can change.
+     *
+     * <p>For example, if a resource has a value defined for the -land resource qualifier,
+     * this field will have the {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION} bit set.
+     * </p>
+     *
+     * @see android.content.pm.ActivityInfo#CONFIG_MCC
+     * @see android.content.pm.ActivityInfo#CONFIG_MNC
+     * @see android.content.pm.ActivityInfo#CONFIG_LOCALE
+     * @see android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
+     * @see android.content.pm.ActivityInfo#CONFIG_KEYBOARD
+     * @see android.content.pm.ActivityInfo#CONFIG_KEYBOARD_HIDDEN
+     * @see android.content.pm.ActivityInfo#CONFIG_NAVIGATION
+     * @see android.content.pm.ActivityInfo#CONFIG_ORIENTATION
+     * @see android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
+     * @see android.content.pm.ActivityInfo#CONFIG_UI_MODE
+     * @see android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
+     * @see android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
+     * @see android.content.pm.ActivityInfo#CONFIG_DENSITY
+     * @see android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
+     * @see android.content.pm.ActivityInfo#CONFIG_COLOR_MODE
+     *
      */
     public @Config int changingConfigurations = -1;
 
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 6dedbde..3e9fab1 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -205,6 +205,7 @@
      * </p>
      *
      * @see #getFlags
+     * @hide
      */
     public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
 
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 7792939..1ccf16a 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -18,14 +18,17 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -58,7 +61,7 @@
     private final UserSpecifiedFocusComparator mUserSpecifiedClusterComparator =
             new UserSpecifiedFocusComparator((r, v) -> isValidId(v.getNextClusterForwardId())
                     ? v.findUserSetNextKeyboardNavigationCluster(r, View.FOCUS_FORWARD) : null);
-    private final FocusComparator mFocusComparator = new FocusComparator();
+    private final FocusSorter mFocusSorter = new FocusSorter();
 
     private final ArrayList<View> mTempList = new ArrayList<View>();
 
@@ -124,20 +127,23 @@
         if (focused == null || focused == root) {
             return root;
         }
-        ViewParent effective = focused.getParent();
+        ViewGroup effective = null;
+        ViewParent nextParent = focused.getParent();
         do {
-            if (effective == root) {
-                return root;
+            if (nextParent == root) {
+                return effective != null ? effective : root;
             }
-            ViewGroup vg = (ViewGroup) effective;
+            ViewGroup vg = (ViewGroup) nextParent;
             if (vg.getTouchscreenBlocksFocus()
                     && focused.getContext().getPackageManager().hasSystemFeature(
                             PackageManager.FEATURE_TOUCHSCREEN)
                     && vg.isKeyboardNavigationCluster()) {
-                return vg;
+                // Don't stop and return here because the cluster could be nested and we only
+                // care about the top-most one.
+                effective = vg;
             }
-            effective = effective.getParent();
-        } while (effective != null);
+            nextParent = nextParent.getParent();
+        } while (nextParent instanceof ViewGroup);
         return root;
     }
 
@@ -760,66 +766,102 @@
         return id != 0 && id != View.NO_ID;
     }
 
-    static FocusComparator getFocusComparator(ViewGroup root, boolean isRtl) {
-        FocusComparator comparator = getInstance().mFocusComparator;
-        comparator.setRoot(root);
-        comparator.setIsLayoutRtl(isRtl);
-        return comparator;
-    }
+    static final class FocusSorter {
+        private ArrayList<Rect> mRectPool = new ArrayList<>();
+        private int mLastPoolRect;
+        private int mRtlMult;
+        private HashMap<View, Rect> mRectByView = null;
 
-    static final class FocusComparator implements Comparator<View> {
-        private final Rect mFirstRect = new Rect();
-        private final Rect mSecondRect = new Rect();
-        private ViewGroup mRoot = null;
-        private boolean mIsLayoutRtl;
-
-        public void setIsLayoutRtl(boolean b) {
-            mIsLayoutRtl = b;
-        }
-
-        public void setRoot(ViewGroup root) {
-            mRoot = root;
-        }
-
-        public int compare(View first, View second) {
+        private Comparator<View> mTopsComparator = (first, second) -> {
             if (first == second) {
                 return 0;
             }
 
-            getRect(first, mFirstRect);
-            getRect(second, mSecondRect);
+            Rect firstRect = mRectByView.get(first);
+            Rect secondRect = mRectByView.get(second);
 
-            if (mFirstRect.top < mSecondRect.top) {
-                return -1;
-            } else if (mFirstRect.top > mSecondRect.top) {
-                return 1;
-            } else if (mFirstRect.left < mSecondRect.left) {
-                return mIsLayoutRtl ? 1 : -1;
-            } else if (mFirstRect.left > mSecondRect.left) {
-                return mIsLayoutRtl ? -1 : 1;
-            } else if (mFirstRect.bottom < mSecondRect.bottom) {
-                return -1;
-            } else if (mFirstRect.bottom > mSecondRect.bottom) {
-                return 1;
-            } else if (mFirstRect.right < mSecondRect.right) {
-                return mIsLayoutRtl ? 1 : -1;
-            } else if (mFirstRect.right > mSecondRect.right) {
-                return mIsLayoutRtl ? -1 : 1;
-            } else {
-                // The view are distinct but completely coincident so we consider
-                // them equal for our purposes.  Since the sort is stable, this
-                // means that the views will retain their layout order relative to one another.
+            int result = firstRect.top - secondRect.top;
+            if (result == 0) {
+                return firstRect.bottom - secondRect.bottom;
+            }
+            return result;
+        };
+
+        private Comparator<View> mSidesComparator = (first, second) -> {
+            if (first == second) {
                 return 0;
             }
-        }
 
-        private void getRect(View view, Rect rect) {
-            view.getDrawingRect(rect);
-            mRoot.offsetDescendantRectToMyCoords(view, rect);
+            Rect firstRect = mRectByView.get(first);
+            Rect secondRect = mRectByView.get(second);
+
+            int result = firstRect.left - secondRect.left;
+            if (result == 0) {
+                return firstRect.right - secondRect.right;
+            }
+            return mRtlMult * result;
+        };
+
+        public void sort(View[] views, int start, int end, ViewGroup root, boolean isRtl) {
+            int count = end - start;
+            if (count < 2) {
+                return;
+            }
+            if (mRectByView == null) {
+                mRectByView = new HashMap<>();
+            }
+            mRtlMult = isRtl ? -1 : 1;
+            for (int i = mRectPool.size(); i < count; ++i) {
+                mRectPool.add(new Rect());
+            }
+            for (int i = start; i < end; ++i) {
+                Rect next = mRectPool.get(mLastPoolRect++);
+                views[i].getDrawingRect(next);
+                root.offsetDescendantRectToMyCoords(views[i], next);
+                mRectByView.put(views[i], next);
+            }
+
+            // Sort top-to-bottom
+            Arrays.sort(views, start, count, mTopsComparator);
+            // Sweep top-to-bottom to identify rows
+            int sweepBottom = mRectByView.get(views[start]).bottom;
+            int rowStart = start;
+            int sweepIdx = start + 1;
+            for (; sweepIdx < end; ++sweepIdx) {
+                Rect currRect = mRectByView.get(views[sweepIdx]);
+                if (currRect.top >= sweepBottom) {
+                    // Next view is on a new row, sort the row we've just finished left-to-right.
+                    if ((sweepIdx - rowStart) > 1) {
+                        Arrays.sort(views, rowStart, sweepIdx, mSidesComparator);
+                    }
+                    sweepBottom = currRect.bottom;
+                    rowStart = sweepIdx;
+                } else {
+                    // Next view vertically overlaps, we need to extend our "row height"
+                    sweepBottom = Math.max(sweepBottom, currRect.bottom);
+                }
+            }
+            // Sort whatever's left (final row) left-to-right
+            if ((sweepIdx - rowStart) > 1) {
+                Arrays.sort(views, rowStart, sweepIdx, mSidesComparator);
+            }
+
+            mLastPoolRect = 0;
+            mRectByView.clear();
         }
     }
 
     /**
+     * Public for testing.
+     *
+     * @hide
+     */
+    @TestApi
+    public static void sort(View[] views, int start, int end, ViewGroup root, boolean isRtl) {
+        getInstance().mFocusSorter.sort(views, start, end, root, isRtl);
+    }
+
+    /**
      * Sorts views according to any explicitly-specified focus-chains. If there are no explicitly
      * specified focus chains (eg. no nextFocusForward attributes defined), this should be a no-op.
      */
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index 2fe98c0..dbeb747 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -28,4 +28,9 @@
      * Notifies the controller that the PiP is currently minimized.
      */
     oneway void setIsMinimized(boolean isMinimized);
+
+    /**
+     * @return what WM considers to be the current device rotation.
+     */
+    int getDisplayRotation();
 }
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl
index 782f349..9382741 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedStackListener.aidl
@@ -41,9 +41,13 @@
      * current state with the aspect ratio applied.  The {@param animatingBounds} are provided
      * to indicate the current target bounds of the pinned stack (the final bounds if animating,
      * the current bounds if not), which may be helpful in calculating dependent animation bounds.
+     *
+     * The {@param displayRotation} is provided so that the client can verify when making certain
+     * calls that it will not provide stale information based on an old display rotation (ie. if
+     * the WM has changed in the mean time but the client has not received onMovementBoundsChanged).
      */
     void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds, in Rect animatingBounds,
-            boolean fromImeAdjustement);
+            boolean fromImeAdjustement, int displayRotation);
 
     /**
      * Called when window manager decides to adjust the pinned stack bounds because of the IME, or
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index fe91978..20f7ace 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -94,8 +94,8 @@
         super.onFinishInflate();
         mAppName = findViewById(com.android.internal.R.id.app_name_text);
         mHeaderText = findViewById(com.android.internal.R.id.header_text);
-        mExpandButton = (ImageView) findViewById(com.android.internal.R.id.expand_button);
-        mIcon = (CachingIconView) findViewById(com.android.internal.R.id.icon);
+        mExpandButton = findViewById(com.android.internal.R.id.expand_button);
+        mIcon = findViewById(com.android.internal.R.id.icon);
         mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
     }
 
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 1cb563f..3b15456 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -55,6 +55,8 @@
     private static native void nativeSetAnimationTransaction();
 
     private static native void nativeSetLayer(long nativeObject, int zorder);
+    private static native void nativeSetRelativeLayer(long nativeObject, IBinder relativeTo,
+            int zorder);
     private static native void nativeSetPosition(long nativeObject, float x, float y);
     private static native void nativeSetGeometryAppliesWithResize(long nativeObject);
     private static native void nativeSetSize(long nativeObject, int w, int h);
@@ -461,6 +463,11 @@
         nativeSetLayer(mNativeObject, zorder);
     }
 
+    public void setRelativeLayer(IBinder relativeTo, int zorder) {
+        checkNotReleased();
+        nativeSetRelativeLayer(mNativeObject, relativeTo, zorder);
+    }
+
     public void setPosition(float x, float y) {
         checkNotReleased();
         nativeSetPosition(mNativeObject, x, y);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 076b33c..9d40895 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -93,7 +93,7 @@
  * artifacts may occur on previous versions of the platform when its window is
  * positioned asynchronously.</p>
  */
-public class SurfaceView extends View {
+public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
     private static final String TAG = "SurfaceView";
     private static final boolean DEBUG = false;
 
@@ -169,6 +169,8 @@
     boolean mWindowVisibility = false;
     boolean mLastWindowVisibility = false;
     boolean mViewVisibility = false;
+    boolean mWindowStopped = false;
+
     int mRequestedWidth = -1;
     int mRequestedHeight = -1;
     /* Set SurfaceView's format to 565 by default to maintain backward
@@ -226,12 +228,27 @@
         return mSurfaceHolder;
     }
 
+    private void updateRequestedVisibility() {
+        mRequestedVisible = mViewVisibility && mWindowVisibility && !mWindowStopped;
+    }
+
+    /** @hide */
+    @Override
+    public void windowStopped(boolean stopped) {
+        mWindowStopped = stopped;
+        updateRequestedVisibility();
+        updateSurface();
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+
+        getViewRootImpl().addWindowStoppedCallback(this);
+
         mParent.requestTransparentRegion(this);
         mViewVisibility = getVisibility() == VISIBLE;
-        mRequestedVisible = mViewVisibility && mWindowVisibility;
+        updateRequestedVisibility();
 
         mAttachedToWindow = true;
         if (!mGlobalListenersAdded) {
@@ -246,7 +263,7 @@
     protected void onWindowVisibilityChanged(int visibility) {
         super.onWindowVisibilityChanged(visibility);
         mWindowVisibility = visibility == VISIBLE;
-        mRequestedVisible = mWindowVisibility && mViewVisibility;
+        updateRequestedVisibility();
         updateSurface();
     }
 
@@ -254,7 +271,7 @@
     public void setVisibility(int visibility) {
         super.setVisibility(visibility);
         mViewVisibility = visibility == VISIBLE;
-        boolean newRequestedVisible = mWindowVisibility && mViewVisibility;
+        boolean newRequestedVisible = mWindowVisibility && mViewVisibility && !mWindowStopped;
         if (newRequestedVisible != mRequestedVisible) {
             // our base class (View) invalidates the layout only when
             // we go from/to the GONE state. However, SurfaceView needs
@@ -278,6 +295,16 @@
 
     @Override
     protected void onDetachedFromWindow() {
+        ViewRootImpl viewRoot = getViewRootImpl();
+        // It's possible to create a SurfaceView using the default constructor and never
+        // attach it to a view hierarchy, this is a common use case when dealing with
+        // OpenGL. A developer will probably create a new GLSurfaceView, and let it manage
+        // the lifecycle. Instead of attaching it to a view, he/she can just pass
+        // the SurfaceHolder forward, most live wallpapers do it.
+        if (viewRoot != null) {
+            viewRoot.removeWindowStoppedCallback(this);
+        }
+
         mAttachedToWindow = false;
         if (mGlobalListenersAdded) {
             ViewTreeObserver observer = getViewTreeObserver();
@@ -299,6 +326,7 @@
         mSurfaceControl = null;
 
         mHaveFrame = false;
+
         super.onDetachedFromWindow();
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index eacf319..668f65d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -66,6 +66,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
@@ -109,7 +110,6 @@
 import android.widget.ScrollBarDrawable;
 
 import com.android.internal.R;
-import com.android.internal.util.Preconditions;
 import com.android.internal.view.TooltipPopup;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.widget.ScrollBarUtils;
@@ -321,7 +321,7 @@
  * </pre></li>
  * <li>From the onCreate method of an Activity, find the Button
  * <pre class="prettyprint">
- *      Button myButton = (Button) findViewById(R.id.my_button);
+ *      Button myButton = findViewById(R.id.my_button);
  * </pre></li>
  * </ul>
  * <p>
@@ -954,41 +954,6 @@
 
     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
 
-    /** @hide */
-    @IntDef({
-            AUTOFILL_MODE_INHERIT,
-            AUTOFILL_MODE_AUTO,
-            AUTOFILL_MODE_MANUAL
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AutofillMode {}
-
-    /**
-     * This view inherits the autofill state from it's parent. If there is no parent it is
-     * {@link #AUTOFILL_MODE_AUTO}.
-     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
-     * {@code android:autofillMode}.
-     */
-    public static final int AUTOFILL_MODE_INHERIT = 0;
-
-    /**
-     * Allows this view to automatically trigger an autofill request when it get focus.
-     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">
-     * {@code android:autofillMode}.
-     */
-    public static final int AUTOFILL_MODE_AUTO = 1;
-
-    /**
-     * Do not trigger an autofill request if this view is focused. The user can still force
-     * an autofill request.
-     * <p>This does not prevent this field from being autofilled if an autofill operation is
-     * triggered from a different view.</p>
-     *
-     * Use with {@link #setAutofillMode(int)} and <a href="#attr_android:autofillMode">{@code
-     * android:autofillMode}.
-     */
-    public static final int AUTOFILL_MODE_MANUAL = 2;
-
     /**
      * This view contains an email address.
      *
@@ -1170,27 +1135,39 @@
     @IntDef({
             IMPORTANT_FOR_AUTOFILL_AUTO,
             IMPORTANT_FOR_AUTOFILL_YES,
-            IMPORTANT_FOR_AUTOFILL_NO
+            IMPORTANT_FOR_AUTOFILL_NO,
+            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
+            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AutofillImportance {}
 
     /**
-     * Automatically determine whether a view is important for auto-fill.
+     * Automatically determine whether a view is important for autofill.
      */
     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
 
     /**
-     * The view is important for important for auto-fill.
+     * The view is important for autofill, and its children (if any) will be traversed.
      */
     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
 
     /**
-     * The view is not important for auto-fill.
+     * The view is not important for autofill, and its children (if any) will be traversed.
      */
     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
 
     /**
+     * The view is important for autofill, but its children (if any) will not be traversed.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
+
+    /**
+     * The view is not important for autofill, and its children (if any) will not be traversed.
+     */
+    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
+
+    /**
      * This view is enabled. Interpretation varies by subclass.
      * Use with ENABLED_MASK when calling setFlags.
      * {@hide}
@@ -2762,7 +2739,7 @@
      *                 1                 PFLAG3_IS_AUTOFILLED
      *                1                  PFLAG3_FINGER_DOWN
      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
-     *             11                    PFLAG3_AUTO_FILL_MODE_MASK
+     *             __                    unused
      *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
      *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
      *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
@@ -2992,23 +2969,6 @@
     private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
 
     /**
-     * Shift for the place where the autofill mode is stored in the pflags
-     *
-     * @see #getAutofillMode()
-     * @see #setAutofillMode(int)
-     */
-    private static final int PFLAG3_AUTOFILL_MODE_SHIFT = 19;
-
-    /**
-     * Mask for autofill modes
-     *
-     * @see #getAutofillMode()
-     * @see #setAutofillMode(int)
-     */
-    private static final int PFLAG3_AUTOFILL_MODE_MASK = (AUTOFILL_MODE_INHERIT
-            | AUTOFILL_MODE_AUTO | AUTOFILL_MODE_MANUAL) << PFLAG3_AUTOFILL_MODE_SHIFT;
-
-    /**
      * Shift for the bits in {@link #mPrivateFlags3} related to the
      * "importantForAutofill" attribute.
      */
@@ -3927,6 +3887,10 @@
     private Drawable mDefaultFocusHighlight;
     private Drawable mDefaultFocusHighlightCache;
     private boolean mDefaultFocusHighlightSizeChanged;
+    /**
+     * True if the default focus highlight is needed on the target device.
+     */
+    private static boolean sUseDefaultFocusHighlight;
 
     private String mTransitionName;
 
@@ -4433,6 +4397,9 @@
     @Nullable
     private RoundScrollbarRenderer mRoundScrollbarRenderer;
 
+    /** Used to delay visibility updates sent to the autofill manager */
+    private Handler mVisibilityChangeForAutofillHandler;
+
     /**
      * Simple constructor to use when creating a view from code.
      *
@@ -4501,6 +4468,9 @@
 
             sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
 
+            sUseDefaultFocusHighlight = context.getResources().getBoolean(
+                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
+
             sCompatibilityDone = true;
         }
     }
@@ -5055,11 +5025,6 @@
                         setFocusedByDefault(a.getBoolean(attr, true));
                     }
                     break;
-                case R.styleable.View_autofillMode:
-                    if (a.peekValue(attr) != null) {
-                        setAutofillMode(a.getInt(attr, AUTOFILL_MODE_INHERIT));
-                    }
-                    break;
                 case R.styleable.View_autofillHints:
                     if (a.peekValue(attr) != null) {
                         CharSequence[] rawHints = null;
@@ -6849,8 +6814,7 @@
     }
 
     private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
-        if (isAutofillable() && isAttachedToWindow()
-                && getResolvedAutofillMode() == AUTOFILL_MODE_AUTO) {
+        if (isAutofillable() && isAttachedToWindow()) {
             AutofillManager afm = getAutofillManager();
             if (afm != null) {
                 if (enter && hasWindowFocus() && isFocused()) {
@@ -7623,7 +7587,7 @@
      * should use {@link #setImportantForAutofill(int)} instead.
      *
      * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
-     * excluded from the structure; for example, if the user explicitly requested auto-fill, the
+     * excluded from the structure; for example, if the user explicitly requested autofill, the
      * View might be always included.
      *
      * <p>This decision applies just for the view, not its children - if the view children are not
@@ -9159,21 +9123,6 @@
     }
 
     /**
-     * Set autofill mode for the view.
-     *
-     * @param autofillMode One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO},
-     *                     or {@link #AUTOFILL_MODE_MANUAL}.
-     * @attr ref android.R.styleable#View_autofillMode
-     */
-    public void setAutofillMode(@AutofillMode int autofillMode) {
-        Preconditions.checkArgumentInRange(autofillMode, AUTOFILL_MODE_INHERIT,
-                AUTOFILL_MODE_MANUAL, "autofillMode");
-
-        mPrivateFlags3 &= ~PFLAG3_AUTOFILL_MODE_MASK;
-        mPrivateFlags3 |= autofillMode << PFLAG3_AUTOFILL_MODE_SHIFT;
-    }
-
-    /**
      * Sets the hints that helps the autofill service to select the appropriate data to fill the
      * view.
      *
@@ -9790,7 +9739,7 @@
             @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
             @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
             @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
-            })
+            }, category = "focus")
     @Focusable
     public int getFocusable() {
         return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
@@ -9804,54 +9753,12 @@
      * @return Whether the view is focusable in touch mode.
      * @attr ref android.R.styleable#View_focusableInTouchMode
      */
-    @ViewDebug.ExportedProperty
+    @ViewDebug.ExportedProperty(category = "focus")
     public final boolean isFocusableInTouchMode() {
         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
     }
 
     /**
-     * Returns the autofill mode for this view.
-     *
-     * @return One of {@link #AUTOFILL_MODE_INHERIT}, {@link #AUTOFILL_MODE_AUTO}, or
-     * {@link #AUTOFILL_MODE_MANUAL}.
-     * @attr ref android.R.styleable#View_autofillMode
-     */
-    @ViewDebug.ExportedProperty(mapping = {
-            @ViewDebug.IntToString(from = AUTOFILL_MODE_INHERIT, to = "AUTOFILL_MODE_INHERIT"),
-            @ViewDebug.IntToString(from = AUTOFILL_MODE_AUTO, to = "AUTOFILL_MODE_AUTO"),
-            @ViewDebug.IntToString(from = AUTOFILL_MODE_MANUAL, to = "AUTOFILL_MODE_MANUAL")
-            })
-    @AutofillMode
-    public int getAutofillMode() {
-        return (mPrivateFlags3 & PFLAG3_AUTOFILL_MODE_MASK) >> PFLAG3_AUTOFILL_MODE_SHIFT;
-    }
-
-    /**
-     * Returns the resolved autofill mode for this view.
-     *
-     * This is the same as {@link #getAutofillMode()} but if the mode is
-     * {@link #AUTOFILL_MODE_INHERIT} the parents autofill mode will be returned.
-     *
-     * @return One of {@link #AUTOFILL_MODE_AUTO}, or {@link #AUTOFILL_MODE_MANUAL}. If the auto-
-     *         fill mode can not be resolved e.g. {@link #getAutofillMode()} is
-     *         {@link #AUTOFILL_MODE_INHERIT} and the {@link View} is detached
-     *         {@link #AUTOFILL_MODE_AUTO} is returned.
-     */
-    public @AutofillMode int getResolvedAutofillMode() {
-        @AutofillMode int autofillMode = getAutofillMode();
-
-        if (autofillMode == AUTOFILL_MODE_INHERIT) {
-            if (mParent == null) {
-                return AUTOFILL_MODE_AUTO;
-            } else {
-                return mParent.getResolvedAutofillMode();
-            }
-        } else {
-            return autofillMode;
-        }
-    }
-
-    /**
      * Find the nearest view in the specified direction that can take focus.
      * This does not actually give focus to that view.
      *
@@ -9874,12 +9781,31 @@
      * @return True if this view is a root of a cluster, or false otherwise.
      * @attr ref android.R.styleable#View_keyboardNavigationCluster
      */
-    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
+    @ViewDebug.ExportedProperty(category = "focus")
     public final boolean isKeyboardNavigationCluster() {
         return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
     }
 
     /**
+     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
+     * will be ignored.
+     *
+     * @return the keyboard navigation cluster that this view is in (can be this view)
+     *         or {@code null} if not in one
+     */
+    View findKeyboardNavigationCluster() {
+        if (mParent instanceof View) {
+            View cluster = ((View) mParent).findKeyboardNavigationCluster();
+            if (cluster != null) {
+                return cluster;
+            } else if (isKeyboardNavigationCluster()) {
+                return this;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Set whether this view is a root of a keyboard navigation cluster.
      *
      * @param isCluster If true, this view is a root of a cluster.
@@ -9901,9 +9827,20 @@
      *
      * @hide
      */
-    public void setFocusedInCluster() {
-        if (mParent instanceof ViewGroup) {
-            ((ViewGroup) mParent).setFocusInCluster(this);
+    public final void setFocusedInCluster() {
+        View top = findKeyboardNavigationCluster();
+        if (top == this) {
+            return;
+        }
+        ViewParent parent = mParent;
+        View child = this;
+        while (parent instanceof ViewGroup) {
+            ((ViewGroup) parent).setFocusedInCluster(child);
+            if (parent == top) {
+                return;
+            }
+            child = (View) parent;
+            parent = parent.getParent();
         }
     }
 
@@ -9919,7 +9856,7 @@
      * @return {@code true} if this view is the default-focus view, {@code false} otherwise
      * @attr ref android.R.styleable#View_focusedByDefault
      */
-    @ViewDebug.ExportedProperty(category = "focusedByDefault")
+    @ViewDebug.ExportedProperty(category = "focus")
     public final boolean isFocusedByDefault() {
         return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
     }
@@ -10032,7 +9969,7 @@
      * @return True if this View should use a default focus highlight.
      * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
      */
-    @ViewDebug.ExportedProperty(category = "defaultFocusHighlightEnabled")
+    @ViewDebug.ExportedProperty(category = "focus")
     public final boolean getDefaultFocusHighlightEnabled() {
         return mDefaultFocusHighlightEnabled;
     }
@@ -11812,6 +11749,30 @@
         if (fg != null && isVisible != fg.isVisible()) {
             fg.setVisible(isVisible, false);
         }
+
+        if (isAutofillable()) {
+            AutofillManager afm = getAutofillManager();
+
+            if (afm != null && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID) {
+                if (mVisibilityChangeForAutofillHandler != null) {
+                    mVisibilityChangeForAutofillHandler.removeMessages(0);
+                }
+
+                // If the view is in the background but still part of the hierarchy this is called
+                // with isVisible=false. Hence visibility==false requires further checks
+                if (isVisible) {
+                    afm.notifyViewVisibilityChange(this, true);
+                } else {
+                    if (mVisibilityChangeForAutofillHandler == null) {
+                        mVisibilityChangeForAutofillHandler =
+                                new VisibilityChangeForAutofillHandler(afm, this);
+                    }
+                    // Let current operation (e.g. removal of the view from the hierarchy)
+                    // finish before checking state
+                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
+                }
+            }
+        }
     }
 
     /**
@@ -19723,7 +19684,7 @@
         final boolean hasFocusStateSpecified = background == null || !background.isStateful()
                 || !background.hasFocusStateSpecified();
         return !isInTouchMode() && getDefaultFocusHighlightEnabled() && hasFocusStateSpecified
-                && isAttachedToWindow();
+                && isAttachedToWindow() && sUseDefaultFocusHighlight;
     }
 
     /**
@@ -24608,6 +24569,27 @@
     }
 
     /**
+     * When a view becomes invisible checks if autofill considers the view invisible too. This
+     * happens after the regular removal operation to make sure the operation is finished by the
+     * time this is called.
+     */
+    private static class VisibilityChangeForAutofillHandler extends Handler {
+        private final AutofillManager mAfm;
+        private final View mView;
+
+        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
+                @NonNull View view) {
+            mAfm = afm;
+            mView = view;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            mAfm.notifyViewVisibilityChange(mView, mView.isShown());
+        }
+    }
+
+    /**
      * Base class for derived classes that want to save and restore their own
      * state in {@link android.view.View#onSaveInstanceState()}.
      */
@@ -25810,6 +25792,7 @@
         // focus
         stream.addProperty("focus:hasFocus", hasFocus());
         stream.addProperty("focus:isFocused", isFocused());
+        stream.addProperty("focus:focusable", getFocusable());
         stream.addProperty("focus:isFocusable", isFocusable());
         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9e1ceee..1977ef5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -61,7 +61,6 @@
 import com.android.internal.R;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -808,33 +807,27 @@
         return mDefaultFocus != null || super.hasDefaultFocus();
     }
 
-    void setFocusInCluster(View child) {
-        // Stop at the root of the cluster
-        if (child.isKeyboardNavigationCluster()) {
-            return;
-        }
-
+    void setFocusedInCluster(View child) {
         mFocusedInCluster = child;
-
-        if (mParent instanceof ViewGroup) {
-            ((ViewGroup) mParent).setFocusInCluster(this);
-        }
     }
 
-    void clearFocusInCluster(View child) {
+    /**
+     * Removes {@code child} (and associated focusedInCluster chain) from the cluster containing
+     * it.
+     * <br>
+     * This is intended to be run on {@code child}'s immediate parent. This is necessary because
+     * the chain is sometimes cleared after {@code child} has been detached.
+     */
+    void clearFocusedInCluster(View child) {
         if (mFocusedInCluster != child) {
             return;
         }
-
-        if (child.isKeyboardNavigationCluster()) {
-            return;
-        }
-
-        mFocusedInCluster = null;
-
-        if (mParent instanceof ViewGroup) {
-            ((ViewGroup) mParent).clearFocusInCluster(this);
-        }
+        View top = findKeyboardNavigationCluster();
+        ViewParent parent = this;
+        do {
+            ((ViewGroup) parent).mFocusedInCluster = null;
+            parent = parent.getParent();
+        } while (parent != top && parent instanceof ViewGroup);
     }
 
     @Override
@@ -1216,7 +1209,7 @@
                 children[count++] = child;
             }
         }
-        Arrays.sort(children, 0, count, FocusFinder.getFocusComparator(this, false));
+        FocusFinder.sort(children, 0, count, this, isLayoutRtl());
         for (int i = 0; i < count; ++i) {
             children[i].addFocusables(views, direction, focusableMode);
         }
@@ -1266,7 +1259,7 @@
                 visibleChildren[count++] = child;
             }
         }
-        Arrays.sort(visibleChildren, 0, count, FocusFinder.getFocusComparator(this, false));
+        FocusFinder.sort(visibleChildren, 0, count, this, isLayoutRtl());
         for (int i = 0; i < count; ++i) {
             visibleChildren[i].addKeyboardNavigationClusters(views, direction);
         }
@@ -1282,7 +1275,7 @@
     public void setTouchscreenBlocksFocus(boolean touchscreenBlocksFocus) {
         if (touchscreenBlocksFocus) {
             mGroupFlags |= FLAG_TOUCHSCREEN_BLOCKS_FOCUS;
-            if (hasFocus()) {
+            if (hasFocus() && !isKeyboardNavigationCluster()) {
                 final View focusedChild = getDeepestFocusedChild();
                 if (!focusedChild.isFocusableInTouchMode()) {
                     final View newFocus = focusSearch(FOCUS_FORWARD);
@@ -1307,6 +1300,7 @@
     /**
      * Check whether this ViewGroup should ignore focus requests for itself and its children.
      */
+    @ViewDebug.ExportedProperty(category = "focus")
     public boolean getTouchscreenBlocksFocus() {
         return (mGroupFlags & FLAG_TOUCHSCREEN_BLOCKS_FOCUS) != 0;
     }
@@ -1317,7 +1311,8 @@
         // cluster, focus is free to move around within it.
         return getTouchscreenBlocksFocus() &&
                 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
-                && (!hasFocus() || !isKeyboardNavigationCluster());
+                && !(isKeyboardNavigationCluster()
+                        && (hasFocus() || (findKeyboardNavigationCluster() != this)));
     }
 
     @Override
@@ -3218,8 +3213,7 @@
     }
 
     private boolean restoreFocusInClusterInternal(@FocusRealDirection int direction) {
-        if (mFocusedInCluster != null && !mFocusedInCluster.isKeyboardNavigationCluster()
-                && getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
+        if (mFocusedInCluster != null && getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS
                 && (mFocusedInCluster.mViewFlags & VISIBILITY_MASK) == VISIBLE
                 && mFocusedInCluster.restoreFocusInCluster(direction)) {
             return true;
@@ -5183,7 +5177,7 @@
             clearChildFocus = true;
         }
         if (view == mFocusedInCluster) {
-            clearFocusInCluster(view);
+            clearFocusedInCluster(view);
         }
 
         view.clearAccessibilityFocus();
@@ -5303,7 +5297,7 @@
                 clearDefaultFocus = view;
             }
             if (view == mFocusedInCluster) {
-                clearFocusInCluster(view);
+                clearFocusedInCluster(view);
             }
 
             view.clearAccessibilityFocus();
@@ -5459,7 +5453,7 @@
             clearDefaultFocus(child);
         }
         if (child == mFocusedInCluster) {
-            clearFocusInCluster(child);
+            clearFocusedInCluster(child);
         }
 
         child.clearAccessibilityFocus();
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d5aab48..cc11cb8 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -659,17 +659,4 @@
      * @return true if the action was consumed by this ViewParent
      */
     public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments);
-
-    /**
-     * Return the resolved autofill mode.
-     *
-     * @return One of {@link View#AUTOFILL_MODE_AUTO}, {@link View#AUTOFILL_MODE_MANUAL} if the
-     *         autofill mode can be resolved. If the autofill mode cannot be resolved
-     *         {@link View#AUTOFILL_MODE_AUTO}.
-     *
-     * @see View#getResolvedAutofillMode()
-     */
-    default @View.AutofillMode int getResolvedAutofillMode() {
-        return View.AUTOFILL_MODE_AUTO;
-    }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 58ef0af..9ecced6 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1249,6 +1249,19 @@
         mIsAmbientMode = ambient;
     }
 
+    interface WindowStoppedCallback {
+        public void windowStopped(boolean stopped);
+    }
+    private final ArrayList<WindowStoppedCallback> mWindowStoppedCallbacks =  new ArrayList<>();
+
+    void addWindowStoppedCallback(WindowStoppedCallback c) {
+        mWindowStoppedCallbacks.add(c);
+    }
+
+    void removeWindowStoppedCallback(WindowStoppedCallback c) {
+        mWindowStoppedCallbacks.remove(c);
+    }
+
     void setWindowStopped(boolean stopped) {
         if (mStopped != stopped) {
             mStopped = stopped;
@@ -1264,6 +1277,10 @@
                     renderer.destroyHardwareResources(mView);
                 }
             }
+
+            for (int i = 0; i < mWindowStoppedCallbacks.size(); i++) {
+                mWindowStoppedCallbacks.get(i).windowStopped(stopped);
+            }
         }
     }
 
@@ -1544,6 +1561,16 @@
         host.dispatchApplyWindowInsets(getWindowInsets(true /* forceConstruct */));
     }
 
+    /**
+     * @return the last content insets for use in adjusting the source hint rect for the
+     * picture-in-picture transition.
+     *
+     * @hide
+     */
+    public Rect getLastContentInsets() {
+        return mAttachInfo.mContentInsets;
+    }
+
     private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) {
         return lp.type == TYPE_STATUS_BAR_PANEL
                 || lp.type == TYPE_INPUT_METHOD
@@ -4648,7 +4675,8 @@
             if (focused == null && mView.restoreDefaultFocus()) {
                 return true;
             }
-            View cluster = focused.keyboardNavigationClusterSearch(null, direction);
+            View cluster = focused == null ? keyboardNavigationClusterSearch(null, direction)
+                    : focused.keyboardNavigationClusterSearch(null, direction);
 
             // Since requestFocus only takes "real" focus directions (and therefore also
             // restoreFocusInCluster), convert forward/backward focus into FOCUS_DOWN.
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index b157709..92b0d98 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -326,8 +326,8 @@
     /**
      * Sets whether the data on this node is sensitive; if it is, then its content (text, autofill
      * value, etc..) is striped before calls to {@link
-     * android.service.autofill.AutofillService#onFillRequest(android.app.assist.AssistStructure,
-     * Bundle, int, android.os.CancellationSignal, android.service.autofill.FillCallback)}.
+     * android.service.autofill.AutofillService#onFillRequest(android.service.autofill.FillRequest,
+     * android.os.CancellationSignal, android.service.autofill.FillCallback)}.
      *
      * <p>By default, all nodes are assumed to be sensitive, and only nodes that does not have PII
      * (Personally Identifiable Information - sensitive data such as email addresses, credit card
@@ -336,8 +336,8 @@
      *
      * <p>Notice that the content of even sensitive nodes are sent to the service (through the
      * {@link
-     * android.service.autofill.AutofillService#onSaveRequest(android.app.assist.AssistStructure,
-     * Bundle, android.service.autofill.SaveCallback)} call) when the user consented to save
+     * android.service.autofill.AutofillService#onSaveRequest(android.service.autofill.SaveRequest,
+     * android.service.autofill.SaveCallback)} call) when the user consented to save
      * thedata, so it is important to set the content of sensitive nodes as well, but mark them as
      * sensitive.
      *
diff --git a/core/java/android/view/ViewStub.java b/core/java/android/view/ViewStub.java
index 85d10f1..e9d1b87 100644
--- a/core/java/android/view/ViewStub.java
+++ b/core/java/android/view/ViewStub.java
@@ -58,7 +58,7 @@
  * The preferred way to perform the inflation of the layout resource is the following:
  *
  * <pre>
- *     ViewStub stub = (ViewStub) findViewById(R.id.stub);
+ *     ViewStub stub = findViewById(R.id.stub);
  *     View inflated = stub.inflate();
  * </pre>
  *
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 6dbc09c..bf0e10f 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -303,13 +303,16 @@
      *                         hidden, no matter how WindowManagerService will react / has reacted
      *                         to corresponding API calls.  Note that this state is not guaranteed
      *                         to be synchronized with state in WindowManagerService.
+     * @param dismissImeOnBackKeyPressed {@code true} if the software keyboard is shown and the back
+     *                                   key is expected to dismiss the software keyboard.
      * @param targetWindowToken token to identify the target window that the IME is associated with.
      *                          {@code null} when application, system, or the IME itself decided to
      *                          change its window visibility before being associated with any target
      *                          window.
      */
     public abstract void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
-            boolean imeWindowVisible, @Nullable IBinder targetWindowToken);
+            boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed,
+            @Nullable IBinder targetWindowToken);
 
     /**
       * Returns true when the hardware keyboard is available.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index bb6e0ee..030c78b 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1537,6 +1537,18 @@
     public void setLastInputMethodWindowLw(WindowState ime, WindowState target);
 
     /**
+     * An internal callback (from InputMethodManagerService) to notify a state change regarding
+     * whether the back key should dismiss the software keyboard (IME) or not.
+     *
+     * @param newValue {@code true} if the software keyboard is shown and the back key is expected
+     *                 to dismiss the software keyboard.
+     * @hide
+     */
+    default void setDismissImeOnBackKeyPressed(boolean newValue) {
+        // Default implementation does nothing.
+    }
+
+    /**
      * Show the recents task list app.
      * @hide
      */
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index f5f5f42..5118bf4 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -190,13 +190,17 @@
      * Listener for changes to the state of accessibility services. Changes include services being
      * enabled or disabled, or changes to the {@link AccessibilityServiceInfo} of a running service.
      * {@see #addAccessibilityServicesStateChangeListener}.
+     *
+     * @hide
      */
     public interface AccessibilityServicesStateChangeListener {
 
         /**
          * Called when the state of accessibility services changes.
+         *
+         * @param manager The manager that is calling back
          */
-        void onAccessibilityServicesStateChanged();
+        void onAccessibilityServicesStateChanged(AccessibilityManager manager);
     }
 
     /**
@@ -621,11 +625,13 @@
      *
      * @param listener The listener.
      * @return True if successfully registered.
+     *
+     * @hide
      */
-    public boolean addAccessibilityServicesStateChangeListener(
+    public void addAccessibilityServicesStateChangeListener(
             @NonNull AccessibilityServicesStateChangeListener listener) {
         // Final CopyOnWriteArrayList - no lock needed.
-        return mServicesStateChangeListeners.add(listener);
+        mServicesStateChangeListeners.add(listener);
     }
 
     /**
@@ -633,11 +639,13 @@
      *
      * @param listener The listener.
      * @return True if successfully unregistered.
+     *
+     * @hide
      */
-    public boolean removeAccessibilityServicesStateChangeListener(
+    public void removeAccessibilityServicesStateChangeListener(
             @NonNull AccessibilityServicesStateChangeListener listener) {
         // Final CopyOnWriteArrayList - no lock needed.
-        return mServicesStateChangeListeners.remove(listener);
+        mServicesStateChangeListeners.remove(listener);
     }
 
     /**
@@ -1024,7 +1032,7 @@
     private void handleNotifyServicesStateChanged() {
         // Listeners are a final CopyOnWriteArrayList, hence no lock needed.
         for (AccessibilityServicesStateChangeListener listener : mServicesStateChangeListeners) {
-            listener.onAccessibilityServicesStateChanged();
+            listener.onAccessibilityServicesStateChanged(this);
         }
     }
 
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index e85a658..8ed0762 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -31,7 +31,10 @@
 import android.os.IBinder;
 import android.os.Parcelable;
 import android.os.RemoteException;
+import android.service.autofill.AutofillService;
+import android.service.autofill.FillEventHistory;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.View;
@@ -101,7 +104,11 @@
     // Public flags start from the lowest bit
     /**
      * Indicates autofill was explicitly requested by the user.
+     *
+     * @deprecated Use {@link android.service.autofill.FillRequest#FLAG_MANUAL_REQUEST}
      */
+    // TODO(b/33197203): remove
+    @Deprecated
     public static final int FLAG_MANUAL_REQUEST = 0x1;
 
     // Private flags start from the highest bit
@@ -140,6 +147,10 @@
     @GuardedBy("mLock")
     @Nullable private ParcelableMap mLastAutofilledData;
 
+    /** If view tracking is enabled, contains the tracking state */
+    @GuardedBy("mLock")
+    @Nullable private TrackedViews mTrackedViews;
+
     /** @hide */
     public interface AutofillClient {
         /**
@@ -174,6 +185,20 @@
          * @return Whether the UI was hidden.
          */
         boolean autofillCallbackRequestHideFillUi();
+
+        /**
+         * Checks if the view is currently attached and visible.
+         *
+         * @return {@code true} iff the view is attached or visible
+         */
+        boolean getViewVisibility(int viewId);
+
+        /**
+         * Checks is the client is currently visible as understood by autofill.
+         *
+         * @return {@code true} if the client is currently visible
+         */
+        boolean isVisibleForAutofill();
     }
 
     /**
@@ -257,6 +282,21 @@
     }
 
     /**
+     * Called once the client becomes visible.
+     *
+     * @see AutofillClient#isVisibleForAutofill()
+     *
+     * {@hide}
+     */
+    public void onVisibleForAutofill() {
+        synchronized (mLock) {
+            if (mEnabled && mSessionId != NO_SESSION && mTrackedViews != null) {
+                mTrackedViews.onVisibleForAutofill();
+            }
+        }
+    }
+
+    /**
      * Save state before activity lifecycle
      *
      * @param outState Place to store the state
@@ -297,6 +337,20 @@
     }
 
     /**
+     * Should always be called from {@link AutofillService#getFillEventHistory()}.
+     *
+     * @hide
+     */
+    @Nullable public FillEventHistory getFillEventHistory() {
+        try {
+            return mService.getFillEventHistory();
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return null;
+        }
+    }
+
+    /**
      * Explicitly requests a new autofill context.
      *
      * <p>Normally, the autofill context is automatically started when autofillable views are
@@ -409,6 +463,22 @@
     }
 
     /**
+     * Called when a {@link View view's} visibility changes.
+     *
+     * @param view {@link View} that was exited.
+     * @param isVisible visible if the view is visible in the view hierarchy.
+     *
+     * @hide
+     */
+    public void notifyViewVisibilityChange(@NonNull View view, boolean isVisible) {
+        synchronized (mLock) {
+            if (mEnabled && mSessionId != NO_SESSION && mTrackedViews != null) {
+                mTrackedViews.notifyViewVisibilityChange(view, isVisible);
+            }
+        }
+    }
+
+    /**
      * Called when a virtual view that supports autofill is entered.
      *
      * @param view the {@link View} whose descendant is the virtual view.
@@ -666,6 +736,7 @@
             throw e.rethrowFromSystemServer();
         }
 
+        mTrackedViews = null;
         mSessionId = NO_SESSION;
     }
 
@@ -680,6 +751,7 @@
             throw e.rethrowFromSystemServer();
         }
 
+        mTrackedViews = null;
         mSessionId = NO_SESSION;
     }
 
@@ -760,8 +832,8 @@
         }
     }
 
-    private void requestShowFillUi(IBinder windowToken, AutofillId id, int width, int height,
-            Rect anchorBounds, IAutofillWindowPresenter presenter) {
+    private void requestShowFillUi(int sessionId, IBinder windowToken, AutofillId id, int width,
+            int height, Rect anchorBounds, IAutofillWindowPresenter presenter) {
         final View anchor = findAchorView(windowToken, id);
         if (anchor == null) {
             return;
@@ -769,9 +841,15 @@
 
         AutofillCallback callback = null;
         synchronized (mLock) {
-            if (getClientLocked().autofillCallbackRequestShowFillUi(anchor, width, height,
-                    anchorBounds, presenter) && mCallback != null) {
-                callback = mCallback;
+            if (mSessionId == sessionId) {
+                AutofillClient client = getClientLocked();
+
+                if (client != null) {
+                    if (client.autofillCallbackRequestShowFillUi(anchor, width, height,
+                            anchorBounds, presenter) && mCallback != null) {
+                        callback = mCallback;
+                    }
+                }
             }
         }
 
@@ -785,6 +863,23 @@
         }
     }
 
+    private void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) {
+        synchronized (mLock) {
+            if (sessionId == mSessionId) {
+                AutofillClient client = getClientLocked();
+                if (client != null) {
+                    client.autofillCallbackAuthenticate(intent, fillInIntent);
+                }
+            }
+        }
+    }
+
+    private void setState(boolean enabled) {
+        synchronized (mLock) {
+            mEnabled = enabled;
+        }
+    }
+
     /**
      * Sets a view as autofilled if the current value is the {code targetValue}.
      *
@@ -804,80 +899,111 @@
         }
     }
 
-    private void handleAutofill(IBinder windowToken, List<AutofillId> ids,
+    private void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids,
             List<AutofillValue> values) {
-        final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken);
-        if (root == null) {
-            return;
-        }
-
-        final int itemCount = ids.size();
-        int numApplied = 0;
-        ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null;
-
-        for (int i = 0; i < itemCount; i++) {
-            final AutofillId id = ids.get(i);
-            final AutofillValue value = values.get(i);
-            final int viewId = id.getViewId();
-            final View view = root.findViewByAccessibilityIdTraversal(viewId);
-            if (view == null) {
-                Log.w(TAG, "autofill(): no View with id " + viewId);
-                continue;
+        synchronized (mLock) {
+            if (sessionId != mSessionId) {
+                return;
             }
-            if (id.isVirtual()) {
-                if (virtualValues == null) {
-                    // Most likely there will be just one view with virtual children.
-                    virtualValues = new ArrayMap<>(1);
+
+            final View root = WindowManagerGlobal.getInstance().getWindowView(windowToken);
+            if (root == null) {
+                return;
+            }
+
+            final int itemCount = ids.size();
+            int numApplied = 0;
+            ArrayMap<View, SparseArray<AutofillValue>> virtualValues = null;
+
+            for (int i = 0; i < itemCount; i++) {
+                final AutofillId id = ids.get(i);
+                final AutofillValue value = values.get(i);
+                final int viewId = id.getViewId();
+                final View view = root.findViewByAccessibilityIdTraversal(viewId);
+                if (view == null) {
+                    Log.w(TAG, "autofill(): no View with id " + viewId);
+                    continue;
                 }
-                SparseArray<AutofillValue> valuesByParent = virtualValues.get(view);
-                if (valuesByParent == null) {
-                    // We don't know the size yet, but usually it will be just a few fields...
-                    valuesByParent = new SparseArray<>(5);
-                    virtualValues.put(view, valuesByParent);
-                }
-                valuesByParent.put(id.getVirtualChildId(), value);
-            } else {
-                synchronized (mLock) {
+                if (id.isVirtual()) {
+                    if (virtualValues == null) {
+                        // Most likely there will be just one view with virtual children.
+                        virtualValues = new ArrayMap<>(1);
+                    }
+                    SparseArray<AutofillValue> valuesByParent = virtualValues.get(view);
+                    if (valuesByParent == null) {
+                        // We don't know the size yet, but usually it will be just a few fields...
+                        valuesByParent = new SparseArray<>(5);
+                        virtualValues.put(view, valuesByParent);
+                    }
+                    valuesByParent.put(id.getVirtualChildId(), value);
+                } else {
                     // Mark the view as to be autofilled with 'value'
                     if (mLastAutofilledData == null) {
                         mLastAutofilledData = new ParcelableMap(itemCount - i);
                     }
                     mLastAutofilledData.put(id, value);
+
+                    view.autofill(value);
+
+                    // Set as autofilled if the values match now, e.g. when the value was updated
+                    // synchronously.
+                    // If autofill happens async, the view is set to autofilled in
+                    // notifyValueChanged.
+                    setAutofilledIfValuesIs(view, value);
+
+                    numApplied++;
                 }
-
-                view.autofill(value);
-
-                // Set as autofilled if the values match now, e.g. when the value was updated
-                // synchronously.
-                // If autofill happens async, the view is set to autofilled in notifyValueChanged.
-                setAutofilledIfValuesIs(view, value);
-
-                numApplied++;
             }
-        }
 
-        if (virtualValues != null) {
-            for (int i = 0; i < virtualValues.size(); i++) {
-                final View parent = virtualValues.keyAt(i);
-                final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i);
-                parent.autofill(childrenValues);
-                numApplied += childrenValues.size();
+            if (virtualValues != null) {
+                for (int i = 0; i < virtualValues.size(); i++) {
+                    final View parent = virtualValues.keyAt(i);
+                    final SparseArray<AutofillValue> childrenValues = virtualValues.valueAt(i);
+                    parent.autofill(childrenValues);
+                    numApplied += childrenValues.size();
+                }
             }
-        }
 
-        final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED);
-        log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount);
-        log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied);
-        mMetricsLogger.write(log);
+            final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED);
+            log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount);
+            log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED,
+                    numApplied);
+            mMetricsLogger.write(log);
+        }
     }
 
-    private void requestHideFillUi(IBinder windowToken, AutofillId id) {
+    /**
+     *  Set the tracked views.
+     *
+     * @param trackedIds The views to be tracked
+     * @param saveOnAllViewsInvisible Finish the session once all tracked views are invisible.
+     */
+    private void setTrackedViews(int sessionId, List<AutofillId> trackedIds,
+            boolean saveOnAllViewsInvisible) {
+        synchronized (mLock) {
+            if (mEnabled && mSessionId == sessionId) {
+                if (saveOnAllViewsInvisible) {
+                    mTrackedViews = new TrackedViews(trackedIds);
+                } else {
+                    mTrackedViews = null;
+                }
+            }
+        }
+    }
+
+    private void requestHideFillUi(int sessionId, IBinder windowToken, AutofillId id) {
         final View anchor = findAchorView(windowToken, id);
 
         AutofillCallback callback = null;
         synchronized (mLock) {
-            if (getClientLocked().autofillCallbackRequestHideFillUi() && mCallback != null) {
-                callback = mCallback;
+            if (mSessionId == sessionId) {
+                AutofillClient client = getClientLocked();
+
+                if (client != null) {
+                    if (client.autofillCallbackRequestHideFillUi() && mCallback != null) {
+                        callback = mCallback;
+                    }
+                }
             }
         }
 
@@ -891,12 +1017,14 @@
         }
     }
 
-    private void notifyNoFillUi(IBinder windowToken, AutofillId id) {
+    private void notifyNoFillUi(int sessionId, IBinder windowToken, AutofillId id) {
         final View anchor = findAchorView(windowToken, id);
 
-        AutofillCallback callback;
+        AutofillCallback callback = null;
         synchronized (mLock) {
-            callback = mCallback;
+            if (mSessionId == sessionId && getClientLocked() != null) {
+                callback = mCallback;
+            }
         }
 
         if (callback != null) {
@@ -929,6 +1057,195 @@
     }
 
     /**
+     * View tracking information. Once all tracked views become invisible the session is finished.
+     */
+    private class TrackedViews {
+        /** Visible tracked views */
+        @Nullable private ArraySet<AutofillId> mVisibleTrackedIds;
+
+        /** Invisible tracked views */
+        @Nullable private ArraySet<AutofillId> mInvisibleTrackedIds;
+
+        /**
+         * Check if set is null or value is in set.
+         *
+         * @param set   The set or null (== empty set)
+         * @param value The value that might be in the set
+         *
+         * @return {@code true} iff set is not empty and value is in set
+         */
+        private <T> boolean isInSet(@Nullable ArraySet<T> set, T value) {
+            return set != null && set.contains(value);
+        }
+
+        /**
+         * Add a value to a set. If set is null, create a new set.
+         *
+         * @param set        The set or null (== empty set)
+         * @param valueToAdd The value to add
+         *
+         * @return The set including the new value. If set was {@code null}, a set containing only
+         *         the new value.
+         */
+        @NonNull
+        private <T> ArraySet<T> addToSet(@Nullable ArraySet<T> set, T valueToAdd) {
+            if (set == null) {
+                set = new ArraySet<>(1);
+            }
+
+            set.add(valueToAdd);
+
+            return set;
+        }
+
+        /**
+         * Remove a value from a set.
+         *
+         * @param set           The set or null (== empty set)
+         * @param valueToRemove The value to remove
+         *
+         * @return The set without the removed value. {@code null} if set was null, or is empty
+         *         after removal.
+         */
+        @Nullable
+        private <T> ArraySet<T> removeFromSet(@Nullable ArraySet<T> set, T valueToRemove) {
+            if (set == null) {
+                return null;
+            }
+
+            set.remove(valueToRemove);
+
+            if (set.isEmpty()) {
+                return null;
+            }
+
+            return set;
+        }
+
+        /**
+         * Set the tracked views.
+         *
+         * @param trackedIds The views to be tracked
+         */
+        TrackedViews(@NonNull List<AutofillId> trackedIds) {
+            mVisibleTrackedIds = null;
+            mInvisibleTrackedIds = null;
+
+            AutofillClient client = getClientLocked();
+            if (trackedIds != null) {
+                int numIds = trackedIds.size();
+                for (int i = 0; i < numIds; i++) {
+                    AutofillId id = trackedIds.get(i);
+
+                    boolean isVisible = true;
+                    if (client != null && client.isVisibleForAutofill()) {
+                        isVisible = client.getViewVisibility(id.getViewId());
+                    }
+
+                    if (isVisible) {
+                        mVisibleTrackedIds = addToSet(mInvisibleTrackedIds, id);
+                    } else {
+                        mInvisibleTrackedIds = addToSet(mInvisibleTrackedIds, id);
+                    }
+                }
+            }
+
+            if (DEBUG) {
+                Log.d(TAG, "TrackedViews(trackedIds=" + trackedIds + "): "
+                        + " mVisibleTrackedIds=" + mVisibleTrackedIds
+                        + " mInvisibleTrackedIds=" + mInvisibleTrackedIds);
+            }
+
+            if (mVisibleTrackedIds == null) {
+                finishSessionLocked();
+            }
+        }
+
+        /**
+         * Called when a {@link View view's} visibility changes.
+         *
+         * @param view {@link View} that was exited.
+         * @param isVisible visible if the view is visible in the view hierarchy.
+         */
+        void notifyViewVisibilityChange(@NonNull View view, boolean isVisible) {
+            AutofillId id = getAutofillId(view);
+            AutofillClient client = getClientLocked();
+
+            if (DEBUG) {
+                Log.d(TAG, "notifyViewVisibilityChange(): id=" + id + " isVisible="
+                        + isVisible);
+            }
+
+            if (client != null && client.isVisibleForAutofill()) {
+                if (isVisible) {
+                    if (isInSet(mInvisibleTrackedIds, id)) {
+                        mInvisibleTrackedIds = removeFromSet(mInvisibleTrackedIds, id);
+                        mVisibleTrackedIds = addToSet(mVisibleTrackedIds, id);
+                    }
+                } else {
+                    if (isInSet(mVisibleTrackedIds, id)) {
+                        mVisibleTrackedIds = removeFromSet(mVisibleTrackedIds, id);
+                        mInvisibleTrackedIds = addToSet(mInvisibleTrackedIds, id);
+                    }
+                }
+            }
+
+            if (mVisibleTrackedIds == null) {
+                finishSessionLocked();
+            }
+        }
+
+        /**
+         * Called once the client becomes visible.
+         *
+         * @see AutofillClient#isVisibleForAutofill()
+         */
+        void onVisibleForAutofill() {
+            // The visibility of the views might have changed while the client was not started,
+            // hence update the visibility state for all views.
+            AutofillClient client = getClientLocked();
+            ArraySet<AutofillId> updatedVisibleTrackedIds = null;
+            ArraySet<AutofillId> updatedInvisibleTrackedIds = null;
+            if (client != null) {
+                if (mInvisibleTrackedIds != null) {
+                    for (AutofillId id : mInvisibleTrackedIds) {
+                        if (client.getViewVisibility(id.getViewId())) {
+                            updatedVisibleTrackedIds = addToSet(updatedVisibleTrackedIds, id);
+
+                            if (DEBUG) {
+                                Log.i(TAG, "onVisibleForAutofill() " + id + " became visible");
+                            }
+                        } else {
+                            updatedInvisibleTrackedIds = addToSet(updatedInvisibleTrackedIds, id);
+                        }
+                    }
+                }
+
+                if (mVisibleTrackedIds != null) {
+                    for (AutofillId id : mVisibleTrackedIds) {
+                        if (client.getViewVisibility(id.getViewId())) {
+                            updatedVisibleTrackedIds = addToSet(updatedVisibleTrackedIds, id);
+                        } else {
+                            updatedInvisibleTrackedIds = addToSet(updatedInvisibleTrackedIds, id);
+
+                            if (DEBUG) {
+                                Log.i(TAG, "onVisibleForAutofill() " + id + " became invisible");
+                            }
+                        }
+                    }
+                }
+
+                mInvisibleTrackedIds = updatedInvisibleTrackedIds;
+                mVisibleTrackedIds = updatedVisibleTrackedIds;
+            }
+
+            if (mVisibleTrackedIds == null) {
+                finishSessionLocked();
+            }
+        }
+    }
+
+    /**
      * Callback for auto-fill related events.
      *
      * <p>Typically used for applications that display their own "auto-complete" views, so they can
@@ -999,73 +1316,82 @@
         public void setState(boolean enabled) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() -> {
-                    synchronized (afm.mLock) {
-                        afm.mEnabled = enabled;
-                    }
-                });
+                afm.mContext.getMainThreadHandler().post(() -> afm.setState(enabled));
             }
         }
 
         @Override
-        public void autofill(IBinder windowToken, List<AutofillId> ids,
+        public void autofill(int sessionId, IBinder windowToken, List<AutofillId> ids,
                 List<AutofillValue> values) {
             // TODO(b/33197203): must keep the dataset so subsequent calls pass the same
             // dataset.extras to service
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() ->
-                        afm.handleAutofill(windowToken, ids, values));
+                afm.mContext.getMainThreadHandler().post(
+                        () -> afm.autofill(sessionId, windowToken, ids, values));
             }
         }
 
         @Override
-        public void authenticate(IntentSender intent, Intent fillInIntent) {
+        public void authenticate(int sessionId, IntentSender intent, Intent fillInIntent) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() -> {
-                    if (afm.getClientLocked() != null) {
-                        afm.getClientLocked().autofillCallbackAuthenticate(intent, fillInIntent);
-                    }
-                });
+                afm.mContext.getMainThreadHandler().post(
+                        () -> afm.authenticate(sessionId, intent, fillInIntent));
             }
         }
 
         @Override
-        public void requestShowFillUi(IBinder windowToken, AutofillId id,
+        public void requestShowFillUi(int sessionId, IBinder windowToken, AutofillId id,
                 int width, int height, Rect anchorBounds, IAutofillWindowPresenter presenter) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
+                afm.mContext.getMainThreadHandler().post(
+                        () -> afm.requestShowFillUi(sessionId, windowToken, id, width, height,
+                                anchorBounds, presenter));
+            }
+        }
+
+        @Override
+        public void requestHideFillUi(int sessionId, IBinder windowToken, AutofillId id) {
+            final AutofillManager afm = mAfm.get();
+            if (afm != null) {
+                afm.mContext.getMainThreadHandler().post(
+                        () -> afm.requestHideFillUi(sessionId, windowToken, id));
+            }
+        }
+
+        @Override
+        public void notifyNoFillUi(int sessionId, IBinder windowToken, AutofillId id) {
+            final AutofillManager afm = mAfm.get();
+            if (afm != null) {
+                afm.mContext.getMainThreadHandler().post(
+                        () -> afm.notifyNoFillUi(sessionId, windowToken, id));
+            }
+        }
+
+        @Override
+        public void startIntentSender(IntentSender intentSender) {
+            final AutofillManager afm = mAfm.get();
+            if (afm != null) {
                 afm.mContext.getMainThreadHandler().post(() -> {
-                    if (afm.getClientLocked() != null) {
-                        afm.requestShowFillUi(windowToken, id, width,
-                                height, anchorBounds, presenter);
+                    try {
+                        afm.mContext.startIntentSender(intentSender, null, 0, 0, 0);
+                    } catch (IntentSender.SendIntentException e) {
+                        Log.e(TAG, "startIntentSender() failed for intent:" + intentSender, e);
                     }
                 });
             }
         }
 
         @Override
-        public void requestHideFillUi(IBinder windowToken, AutofillId id) {
+        public void setTrackedViews(int sessionId, List<AutofillId> ids,
+                boolean saveOnAllViewsInvisible) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() -> {
-                    if (afm.getClientLocked() != null) {
-                        afm.requestHideFillUi(windowToken, id);
-                    }
-                });
-            }
-        }
-
-        @Override
-        public void notifyNoFillUi(IBinder windowToken, AutofillId id) {
-            final AutofillManager afm = mAfm.get();
-            if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() -> {
-                    if (afm.getClientLocked() != null) {
-                        afm.notifyNoFillUi(windowToken, id);
-                    }
-                });
+                afm.mContext.getMainThreadHandler().post(
+                        () -> afm.setTrackedViews(sessionId, ids, saveOnAllViewsInvisible)
+                );
             }
         }
     }
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 68b3ccabc..df777c4 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -19,6 +19,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.service.autofill.FillEventHistory;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.view.autofill.IAutoFillManagerClient;
@@ -33,6 +34,7 @@
     int startSession(IBinder activityToken, IBinder windowToken, in IBinder appCallback,
             in AutofillId autoFillId, in Rect bounds, in AutofillValue value, int userId,
             boolean hasCallback, int flags, String packageName);
+    FillEventHistory getFillEventHistory();
     boolean restoreSession(int sessionId, in IBinder activityToken, in IBinder appCallback);
     void setWindow(int sessionId, in IBinder windowToken);
     void updateSession(int sessionId, in AutofillId id, in Rect bounds,
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 7bea174..1a6bad2 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -40,26 +40,39 @@
     /**
       * Autofills the activity with the contents of a dataset.
       */
-    void autofill(in IBinder windowToken, in List<AutofillId> ids, in List<AutofillValue> values);
+    void autofill(int sessionId, in IBinder windowToken, in List<AutofillId> ids,
+            in List<AutofillValue> values);
 
     /**
       * Authenticates a fill response or a data set.
       */
-    void authenticate(in IntentSender intent, in Intent fillInIntent);
+    void authenticate(int sessionId, in IntentSender intent, in Intent fillInIntent);
+
+    /**
+      * Sets the views to track. If saveOnAllViewsInvisible is set and all these view are invisible
+      * the session is finished automatically.
+      */
+    void setTrackedViews(int sessionId, in List<AutofillId> ids,
+            boolean saveOnAllViewsInvisible);
 
     /**
      * Requests showing the fill UI.
      */
-    void requestShowFillUi(in IBinder windowToken, in AutofillId id, int width,
+    void requestShowFillUi(int sessionId, in IBinder windowToken, in AutofillId id, int width,
             int height, in Rect anchorBounds, in IAutofillWindowPresenter presenter);
 
     /**
      * Requests hiding the fill UI.
      */
-    void requestHideFillUi(in IBinder windowToken, in AutofillId id);
+    void requestHideFillUi(int sessionId, in IBinder windowToken, in AutofillId id);
 
     /**
-     * Nitifies no fill UI will be shown.
+     * Notifies no fill UI will be shown.
      */
-    void notifyNoFillUi(in IBinder windowToken, in AutofillId id);
+    void notifyNoFillUi(int sessionId, in IBinder windowToken, in AutofillId id);
+
+    /**
+     * Starts the provided intent sender
+     */
+    void startIntentSender(in IntentSender intentSender);
 }
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 2f12e9b..28d9fcf 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -155,7 +155,7 @@
     public static final int IME_ACTION_PREVIOUS = 0x00000007;
 
     /**
-     * Flag of {@link #imeOptions}: used to request that the IME does not update any personalized
+     * Flag of {@link #imeOptions}: used to request that the IME should not update any personalized
      * data such as typing history and personalized language model based on what the user typed on
      * this text editing object.  Typical use cases are:
      * <ul>
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 71809bd..f0645b8 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -57,7 +57,6 @@
  * @attr ref android.R.styleable#InputMethod_settingsActivity
  * @attr ref android.R.styleable#InputMethod_isDefault
  * @attr ref android.R.styleable#InputMethod_supportsSwitchingToNextInputMethod
- * @attr ref android.R.styleable#InputMethod_supportsDismissingWindow
  */
 public final class InputMethodInfo implements Parcelable {
     static final String TAG = "InputMethodInfo";
@@ -105,11 +104,6 @@
     private final boolean mSupportsSwitchingToNextInputMethod;
 
     /**
-     * The flag whether this IME supports ways to dismiss its window (e.g. dismiss button.)
-     */
-    private final boolean mSupportsDismissingWindow;
-
-    /**
      * @param service the {@link ResolveInfo} corresponds in which the IME is implemented.
      * @return a unique ID to be returned by {@link #getId()}. We have used
      *         {@link ComponentName#flattenToShortString()} for this purpose (and it is already
@@ -151,7 +145,6 @@
         mId = computeId(service);
         boolean isAuxIme = true;
         boolean supportsSwitchingToNextInputMethod = false; // false as default
-        boolean supportsDismissingWindow = false; // false as default
         mForceDefault = false;
 
         PackageManager pm = context.getPackageManager();
@@ -191,8 +184,6 @@
             supportsSwitchingToNextInputMethod = sa.getBoolean(
                     com.android.internal.R.styleable.InputMethod_supportsSwitchingToNextInputMethod,
                     false);
-            supportsDismissingWindow = sa.getBoolean(
-                    com.android.internal.R.styleable.InputMethod_supportsDismissingWindow, false);
             sa.recycle();
 
             final int depth = parser.getDepth();
@@ -263,7 +254,6 @@
         mIsDefaultResId = isDefaultResId;
         mIsAuxIme = isAuxIme;
         mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
-        mSupportsDismissingWindow = supportsDismissingWindow;
     }
 
     InputMethodInfo(Parcel source) {
@@ -272,7 +262,6 @@
         mIsDefaultResId = source.readInt();
         mIsAuxIme = source.readInt() == 1;
         mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
-        mSupportsDismissingWindow = source.readInt() == 1;
         mService = ResolveInfo.CREATOR.createFromParcel(source);
         mSubtypes = new InputMethodSubtypeArray(source);
         mForceDefault = false;
@@ -285,8 +274,7 @@
             CharSequence label, String settingsActivity) {
         this(buildDummyResolveInfo(packageName, className, label), false /* isAuxIme */,
                 settingsActivity, null /* subtypes */, 0 /* isDefaultResId */,
-                false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */,
-                true /* supportsDismissingWindow */);
+                false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */);
     }
 
     /**
@@ -297,8 +285,7 @@
             String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
             boolean forceDefault) {
         this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId, forceDefault,
-                 true /* supportsSwitchingToNextInputMethod */,
-                 true /* supportsDismissingWindow */);
+                true /* supportsSwitchingToNextInputMethod */);
     }
 
     /**
@@ -307,7 +294,7 @@
      */
     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme, String settingsActivity,
             List<InputMethodSubtype> subtypes, int isDefaultResId, boolean forceDefault,
-            boolean supportsSwitchingToNextInputMethod, boolean supportsDismissingWindow) {
+            boolean supportsSwitchingToNextInputMethod) {
         final ServiceInfo si = ri.serviceInfo;
         mService = ri;
         mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -317,7 +304,6 @@
         mSubtypes = new InputMethodSubtypeArray(subtypes);
         mForceDefault = forceDefault;
         mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
-        mSupportsDismissingWindow = supportsDismissingWindow;
     }
 
     private static ResolveInfo buildDummyResolveInfo(String packageName, String className,
@@ -458,8 +444,7 @@
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + "mId=" + mId
                 + " mSettingsActivityName=" + mSettingsActivityName
-                + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod
-                + " mSupportsDismissingWindow=" + mSupportsDismissingWindow);
+                + " mSupportsSwitchingToNextInputMethod=" + mSupportsSwitchingToNextInputMethod);
         pw.println(prefix + "mIsDefaultResId=0x"
                 + Integer.toHexString(mIsDefaultResId));
         pw.println(prefix + "Service:");
@@ -512,14 +497,6 @@
     }
 
     /**
-     * @return true if this input method supports ways to dismiss its window.
-     * @hide
-     */
-    public boolean supportsDismissingWindow() {
-        return mSupportsDismissingWindow;
-    }
-
-    /**
      * Used to package this object into a {@link Parcel}.
      *
      * @param dest The {@link Parcel} to be written.
@@ -532,7 +509,6 @@
         dest.writeInt(mIsDefaultResId);
         dest.writeInt(mIsAuxIme ? 1 : 0);
         dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
-        dest.writeInt(mSupportsDismissingWindow ? 1 : 0);
         mService.writeToParcel(dest, flags);
         mSubtypes.writeToParcel(dest);
     }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index f634a1b..022c157 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -53,7 +53,6 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
-import java.util.StringJoiner;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -89,7 +88,7 @@
     @Override
     public TextSelection suggestSelection(
             @NonNull CharSequence text, int selectionStartIndex, int selectionEndIndex,
-            LocaleList defaultLocales) {
+            @Nullable LocaleList defaultLocales) {
         validateInput(text, selectionStartIndex, selectionEndIndex);
         try {
             if (text.length() > 0) {
@@ -128,7 +127,8 @@
 
     @Override
     public TextClassificationResult getTextClassificationResult(
-            @NonNull CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
+            @NonNull CharSequence text, int startIndex, int endIndex,
+            @Nullable LocaleList defaultLocales) {
         validateInput(text, startIndex, endIndex);
         try {
             if (text.length() > 0) {
@@ -156,7 +156,8 @@
     }
 
     @Override
-    public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
+    public LinksInfo getLinks(
+            @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales) {
         Preconditions.checkArgument(text != null);
         try {
             return LinksInfoFactory.create(
@@ -199,12 +200,11 @@
     @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
     @Nullable
     private Locale findBestSupportedLocaleLocked(LocaleList localeList) {
-        final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(
-                new StringJoiner(",")
-                        // Specified localeList takes priority over the system default
-                        .add(localeList.toLanguageTags())
-                        .add(LocaleList.getDefault().toLanguageTags())
-                        .toString());
+        // Specified localeList takes priority over the system default, so it is listed first.
+        final String languages = localeList.isEmpty()
+                ? LocaleList.getDefault().toLanguageTags()
+                : localeList.toLanguageTags() + "," + LocaleList.getDefault().toLanguageTags();
+        final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(languages);
         return Locale.lookup(languageRangeList, loadModelFilePathsLocked().keySet());
     }
 
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 06d4868..6df76fa 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -151,8 +151,8 @@
             mShowRevokeUI = showRevokeUI;
             mPackageName = packageName;
 
-            ImageView permGrpIcon = (ImageView) findViewById(R.id.perm_icon);
-            TextView permNameView = (TextView) findViewById(R.id.perm_name);
+            ImageView permGrpIcon = findViewById(R.id.perm_icon);
+            TextView permNameView = findViewById(R.id.perm_name);
 
             PackageManager pm = getContext().getPackageManager();
             Drawable icon = null;
diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java
index 09e09b7..09ba553 100644
--- a/core/java/android/widget/Button.java
+++ b/core/java/android/widget/Button.java
@@ -37,7 +37,7 @@
  *
  *         setContentView(R.layout.content_layout_id);
  *
- *         final Button button = (Button) findViewById(R.id.button_id);
+ *         final Button button = findViewById(R.id.button_id);
  *         button.setOnClickListener(new View.OnClickListener() {
  *             public void onClick(View v) {
  *                 // Perform action on click
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index 6c6079f..d11c03a 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -17,11 +17,13 @@
 package android.widget;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.TypedArray;
 import android.icu.text.MeasureFormat;
 import android.icu.text.MeasureFormat.FormatWidth;
 import android.icu.util.Measure;
 import android.icu.util.MeasureUnit;
+import android.net.Uri;
 import android.os.SystemClock;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
@@ -148,6 +150,22 @@
     }
 
     /**
+     * @return whether this is the final countdown
+     */
+    public boolean isTheFinalCountDown() {
+        try {
+            getContext().startActivity(
+                    new Intent(Intent.ACTION_VIEW, Uri.parse("https://youtu.be/9jK-NcRmVcw"))
+                            .addCategory(Intent.CATEGORY_BROWSABLE)
+                            .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT
+                                    | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT));
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
      * Set the time that the count-up timer is in reference to.
      *
      * @param base Use the {@link SystemClock#elapsedRealtime} time base.
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 0f0e6c3..be0967f 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -124,13 +124,13 @@
             addView(child);
         }
 
-        mPrevButton = (ImageButton) findViewById(R.id.prev);
+        mPrevButton = findViewById(R.id.prev);
         mPrevButton.setOnClickListener(mOnClickListener);
 
-        mNextButton = (ImageButton) findViewById(R.id.next);
+        mNextButton = findViewById(R.id.next);
         mNextButton.setOnClickListener(mOnClickListener);
 
-        mViewPager = (ViewPager) findViewById(R.id.day_picker_view_pager);
+        mViewPager = findViewById(R.id.day_picker_view_pager);
         mViewPager.setAdapter(mAdapter);
         mViewPager.setOnPageChangeListener(mOnPageChangedListener);
 
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 4fb7b19..0d3baa8 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -146,7 +146,7 @@
     private static final String UNDO_OWNER_TAG = "Editor";
 
     // Ordering constants used to place the Action Mode or context menu items in their menu.
-    private static final int MENU_ITEM_ORDER_ASSIST = 1;
+    private static final int MENU_ITEM_ORDER_ASSIST = 0;
     private static final int MENU_ITEM_ORDER_UNDO = 2;
     private static final int MENU_ITEM_ORDER_REDO = 3;
     private static final int MENU_ITEM_ORDER_CUT = 4;
@@ -156,8 +156,8 @@
     private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 8;
     private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
     private static final int MENU_ITEM_ORDER_REPLACE = 10;
-    private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 11;
-    private static final int MENU_ITEM_ORDER_AUTOFILL = 12;
+    private static final int MENU_ITEM_ORDER_AUTOFILL = 11;
+    private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 100;
 
     // Each Editor manages its own undo stack.
     private final UndoManager mUndoManager = new UndoManager();
@@ -6322,9 +6322,10 @@
          * Adds "PROCESS_TEXT" menu items to the specified menu.
          */
         public void onInitializeMenu(Menu menu) {
-            int i = 0;
+            final int size = mSupportedActivities.size();
             loadSupportedActivities();
-            for (ResolveInfo resolveInfo : mSupportedActivities) {
+            for (int i = 0; i < size; i++) {
+                final ResolveInfo resolveInfo = mSupportedActivities.get(i);
                 menu.add(Menu.NONE, Menu.NONE,
                         Editor.MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i++,
                         getLabel(resolveInfo))
diff --git a/core/java/android/widget/MultiAutoCompleteTextView.java b/core/java/android/widget/MultiAutoCompleteTextView.java
index 2152e43..f348d73 100644
--- a/core/java/android/widget/MultiAutoCompleteTextView.java
+++ b/core/java/android/widget/MultiAutoCompleteTextView.java
@@ -43,7 +43,7 @@
  *
  *         ArrayAdapter&lt;String&gt; adapter = new ArrayAdapter&lt;String&gt;(this,
  *                 android.R.layout.simple_dropdown_item_1line, COUNTRIES);
- *         MultiAutoCompleteTextView textView = (MultiAutoCompleteTextView) findViewById(R.id.edit);
+ *         MultiAutoCompleteTextView textView = findViewById(R.id.edit);
  *         textView.setAdapter(adapter);
  *         textView.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());
  *     }
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 662e640..7bdd6da 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -706,7 +706,7 @@
 
         // increment button
         if (!mHasSelectorWheel) {
-            mIncrementButton = (ImageButton) findViewById(R.id.increment);
+            mIncrementButton = findViewById(R.id.increment);
             mIncrementButton.setOnClickListener(onClickListener);
             mIncrementButton.setOnLongClickListener(onLongClickListener);
         } else {
@@ -715,7 +715,7 @@
 
         // decrement button
         if (!mHasSelectorWheel) {
-            mDecrementButton = (ImageButton) findViewById(R.id.decrement);
+            mDecrementButton = findViewById(R.id.decrement);
             mDecrementButton.setOnClickListener(onClickListener);
             mDecrementButton.setOnLongClickListener(onLongClickListener);
         } else {
@@ -723,7 +723,7 @@
         }
 
         // input text
-        mInputText = (EditText) findViewById(R.id.numberpicker_input);
+        mInputText = findViewById(R.id.numberpicker_input);
         mInputText.setOnFocusChangeListener(new OnFocusChangeListener() {
             public void onFocusChange(View v, boolean hasFocus) {
                 if (hasFocus) {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5505f2f..9245134 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1787,7 +1787,7 @@
 
         @Override
         public Action initActionAsync(ViewTree root, ViewGroup rootParent, OnClickHandler handler) {
-            final TextView target = (TextView) root.findViewById(viewId);
+            final TextView target = root.findViewById(viewId);
             if (target == null) return ACTION_NOOP;
 
             TextViewDrawableAction copy = useIcons ?
@@ -3688,12 +3688,12 @@
             createTree();
         }
 
-        public View findViewById(int id) {
+        public <T extends View> T findViewById(int id) {
             if (mChildren == null) {
                 return mRoot.findViewById(id);
             }
             ViewTree tree = findViewTreeById(id);
-            return tree == null ? null : tree.mRoot;
+            return tree == null ? null : (T) tree.mRoot;
         }
 
         public void addChild(ViewTree child) {
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 7e2cadf..8de17c0 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -136,7 +136,7 @@
 mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
       */
     public void setup() {
-        mTabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+        mTabWidget = findViewById(com.android.internal.R.id.tabs);
         if (mTabWidget == null) {
             throw new RuntimeException(
                     "Your TabHost must have a TabWidget whose id attribute is 'android.R.id.tabs'");
@@ -171,7 +171,7 @@
             }
         });
 
-        mTabContent = (FrameLayout) findViewById(com.android.internal.R.id.tabcontent);
+        mTabContent = findViewById(com.android.internal.R.id.tabcontent);
         if (mTabContent == null) {
             throw new RuntimeException(
                     "Your TabHost must have a FrameLayout whose id attribute is "
diff --git a/core/java/android/widget/TextInputTimePickerView.java b/core/java/android/widget/TextInputTimePickerView.java
index 0183343..11b7514d 100644
--- a/core/java/android/widget/TextInputTimePickerView.java
+++ b/core/java/android/widget/TextInputTimePickerView.java
@@ -76,12 +76,12 @@
 
         inflate(context, R.layout.time_picker_text_input_material, this);
 
-        mHourEditText = (EditText) findViewById(R.id.input_hour);
-        mMinuteEditText = (EditText) findViewById(R.id.input_minute);
-        mInputSeparatorView = (TextView) findViewById(R.id.input_separator);
-        mErrorLabel = (TextView) findViewById(R.id.label_error);
-        mHourLabel = (TextView) findViewById(R.id.label_hour);
-        mMinuteLabel = (TextView) findViewById(R.id.label_minute);
+        mHourEditText = findViewById(R.id.input_hour);
+        mMinuteEditText = findViewById(R.id.input_minute);
+        mInputSeparatorView = findViewById(R.id.input_separator);
+        mErrorLabel = findViewById(R.id.label_error);
+        mHourLabel = findViewById(R.id.label_hour);
+        mMinuteLabel = findViewById(R.id.label_minute);
 
         mHourEditText.addTextChangedListener(new TextWatcher() {
             @Override
@@ -109,7 +109,7 @@
             }
         });
 
-        mAmPmSpinner = (Spinner) findViewById(R.id.am_pm_spinner);
+        mAmPmSpinner = findViewById(R.id.am_pm_spinner);
         final String[] amPmStrings = TimePicker.getAmPmStrings(context);
         ArrayAdapter<CharSequence> adapter =
                 new ArrayAdapter<CharSequence>(context, R.layout.simple_spinner_dropdown_item);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9a8131e..f1a3ff5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -16,7 +16,6 @@
 
 package android.widget;
 
-import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
@@ -59,6 +58,7 @@
 import android.graphics.fonts.FontVariationAxis;
 import android.icu.text.DecimalFormatSymbols;
 import android.os.AsyncTask;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
@@ -408,7 +408,7 @@
 
         public Drawables(Context context) {
             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
-            mIsRtlCompatibilityMode = targetSdkVersion < JELLY_BEAN_MR1
+            mIsRtlCompatibilityMode = targetSdkVersion < VERSION_CODES.JELLY_BEAN_MR1
                     || !context.getApplicationInfo().hasRtlSupport();
             mOverride = false;
         }
@@ -1363,7 +1363,7 @@
                 == (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD);
 
         mUseInternationalizedInput =
-                context.getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O;
+                context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.O;
 
         if (inputMethod != null) {
             Class<?> c;
@@ -1408,7 +1408,7 @@
         } else if (numeric != 0) {
             createEditorIfNeeded();
             mEditor.mKeyListener = DigitsKeyListener.getInstance(
-                    mUseInternationalizedInput ? getTextLocale() : null,
+                    null,  // locale
                     (numeric & SIGNED) != 0,
                     (numeric & DECIMAL) != 0);
             inputType = mEditor.mKeyListener.getInputType();
@@ -3400,11 +3400,14 @@
         return mTextPaint.getTextLocales();
     }
 
-    private void changeListenerLocaleTo(@NonNull Locale locale) {
+    private void changeListenerLocaleTo(@Nullable Locale locale) {
         if (mListenerChanged) {
             // If a listener has been explicitly set, don't change it. We may break something.
             return;
         }
+        // The following null check is not absolutely necessary since all calling points of
+        // changeListenerLocaleTo() guarantee a non-null mEditor at the moment. But this is left
+        // here in case others would want to call this method in the future.
         if (mEditor != null) {
             KeyListener listener = mEditor.mKeyListener;
             if (listener instanceof DigitsKeyListener) {
@@ -3418,8 +3421,17 @@
             } else {
                 return;
             }
+            final boolean wasPasswordType = isPasswordInputType(mEditor.mInputType);
             setKeyListenerOnly(listener);
             setInputTypeFromEditor();
+            if (wasPasswordType) {
+                final int newInputClass = mEditor.mInputType & EditorInfo.TYPE_MASK_CLASS;
+                if (newInputClass == EditorInfo.TYPE_CLASS_TEXT) {
+                    mEditor.mInputType |= EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
+                } else if (newInputClass == EditorInfo.TYPE_CLASS_NUMBER) {
+                    mEditor.mInputType |= EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD;
+                }
+            }
         }
     }
 
@@ -3434,7 +3446,6 @@
     public void setTextLocale(@NonNull Locale locale) {
         mLocalesChanged = true;
         mTextPaint.setTextLocale(locale);
-        changeListenerLocaleTo(locale);
         if (mLayout != null) {
             nullLayouts();
             requestLayout();
@@ -3456,7 +3467,6 @@
     public void setTextLocales(@NonNull @Size(min = 1) LocaleList locales) {
         mLocalesChanged = true;
         mTextPaint.setTextLocales(locales);
-        changeListenerLocaleTo(locales.get(0));
         if (mLayout != null) {
             nullLayouts();
             requestLayout();
@@ -3468,9 +3478,7 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         if (!mLocalesChanged) {
-            final LocaleList locales = LocaleList.getDefault();
-            mTextPaint.setTextLocales(locales);
-            changeListenerLocaleTo(locales.get(0));
+            mTextPaint.setTextLocales(LocaleList.getDefault());
             if (mLayout != null) {
                 nullLayouts();
                 requestLayout();
@@ -5586,6 +5594,29 @@
         mEditor.mInputType = type;
     }
 
+    /**
+     * @return {@code null} if the key listener should use pre-O (locale-independent). Otherwise
+     *         a {@code Locale} object that can be used to customize key various listeners.
+     * @see DateKeyListener#getInstance(Locale)
+     * @see DateTimeKeyListener#getInstance(Locale)
+     * @see DigitsKeyListener#getInstance(Locale)
+     * @see TimeKeyListener#getInstance(Locale)
+     */
+    @Nullable
+    private Locale getCustomLocaleForKeyListenerOrNull() {
+        if (!mUseInternationalizedInput) {
+            // If the application does not target O, stick to the previous behavior.
+            return null;
+        }
+        final LocaleList locales = getImeHintLocales();
+        if (locales == null) {
+            // If the application does not explicitly specify IME hint locale, also stick to the
+            // previous behavior.
+            return null;
+        }
+        return locales.get(0);
+    }
+
     private void setInputType(int type, boolean direct) {
         final int cls = type & EditorInfo.TYPE_MASK_CLASS;
         KeyListener input;
@@ -5603,15 +5634,26 @@
             }
             input = TextKeyListener.getInstance(autotext, cap);
         } else if (cls == EditorInfo.TYPE_CLASS_NUMBER) {
+            final Locale locale = getCustomLocaleForKeyListenerOrNull();
             input = DigitsKeyListener.getInstance(
-                    mUseInternationalizedInput ? getTextLocale() : null,
+                    locale,
                     (type & EditorInfo.TYPE_NUMBER_FLAG_SIGNED) != 0,
                     (type & EditorInfo.TYPE_NUMBER_FLAG_DECIMAL) != 0);
-            if (mUseInternationalizedInput) {
-                type = input.getInputType(); // Override type, if necessary for i18n.
+            if (locale != null) {
+                // Override type, if necessary for i18n.
+                int newType = input.getInputType();
+                final int newClass = newType & EditorInfo.TYPE_MASK_CLASS;
+                if (newClass != EditorInfo.TYPE_CLASS_NUMBER) {
+                    // The class is different from the original class. So we need to override
+                    // 'type'. But we want to keep the password flag if it's there.
+                    if ((type & EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD) != 0) {
+                        newType |= EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
+                    }
+                    type = newType;
+                }
             }
         } else if (cls == EditorInfo.TYPE_CLASS_DATETIME) {
-            final Locale locale = mUseInternationalizedInput ? getTextLocale() : null;
+            final Locale locale = getCustomLocaleForKeyListenerOrNull();
             switch (type & EditorInfo.TYPE_MASK_VARIATION) {
                 case EditorInfo.TYPE_DATETIME_VARIATION_DATE:
                     input = DateKeyListener.getInstance(locale);
@@ -5884,6 +5926,9 @@
      * Change "hint" locales associated with the text view, which will be reported to an IME with
      * {@link EditorInfo#hintLocales} when it has focus.
      *
+     * Starting with Android O, this also causes internationalized listeners to be created (or
+     * change locale) based on the first locale in the input locale list.
+     *
      * <p><strong>Note:</strong> If you want new "hint" to take effect immediately you need to
      * call {@link InputMethodManager#restartInput(View)}.</p>
      * @param hintLocales List of the languages that the user is supposed to switch to no matter
@@ -5895,6 +5940,9 @@
         createEditorIfNeeded();
         mEditor.createInputContentTypeIfNeeded();
         mEditor.mInputContentType.imeHintLocales = hintLocales;
+        if (mUseInternationalizedInput) {
+            changeListenerLocaleTo(hintLocales == null ? null : hintLocales.get(0));
+        }
     }
 
     /**
@@ -8148,9 +8196,11 @@
         mTempTextPaint.set(getPaint());
         mTempTextPaint.setTextSize(suggestedSizeInPx);
 
+        final int availableWidth = mHorizontallyScrolling
+                ? VERY_WIDE
+                : getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
         final StaticLayout.Builder layoutBuilder = StaticLayout.Builder.obtain(
-                text, 0, text.length(),  mTempTextPaint,
-                getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight());
+                text, 0, text.length(),  mTempTextPaint, availableWidth);
 
         layoutBuilder.setAlignment(getLayoutAlignment())
                 .setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier())
diff --git a/core/java/android/widget/TwoLineListItem.java b/core/java/android/widget/TwoLineListItem.java
index 0445ebd..553b86e 100644
--- a/core/java/android/widget/TwoLineListItem.java
+++ b/core/java/android/widget/TwoLineListItem.java
@@ -70,8 +70,8 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mText1 = (TextView) findViewById(com.android.internal.R.id.text1);
-        mText2 = (TextView) findViewById(com.android.internal.R.id.text2);
+        mText1 = findViewById(com.android.internal.R.id.text1);
+        mText2 = findViewById(com.android.internal.R.id.text2);
     }
 
     /**
diff --git a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
index ee5d339..b9ed963 100644
--- a/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
+++ b/core/java/com/android/internal/app/AccessibilityButtonChooserActivity.java
@@ -34,6 +34,7 @@
 import android.widget.TextView;
 
 import com.android.internal.R;
+import com.android.internal.widget.ResolverDrawerLayout;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -56,16 +57,21 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.accessibility_button_chooser);
 
+        final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
+        if (rdl != null) {
+            rdl.setOnDismissedListener(this::finish);
+        }
+
         String component = Settings.Secure.getString(getContentResolver(),
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
         if (TextUtils.isEmpty(component)) {
-            TextView prompt = (TextView) findViewById(R.id.accessibility_button_prompt);
+            TextView prompt = findViewById(R.id.accessibility_button_prompt);
             prompt.setVisibility(View.VISIBLE);
         }
 
         mMagnificationTarget = new AccessibilityButtonTarget(this, MAGNIFICATION_COMPONENT_ID,
                 R.string.accessibility_magnification_chooser_text,
-                R.drawable.resolver_icon_placeholder);
+                R.drawable.ic_accessibility_magnification);
 
         mTargets = getServiceAccessibilityButtonTargets(this);
         if (Settings.Secure.getInt(getContentResolver(),
@@ -78,7 +84,7 @@
             finish();
         }
 
-        GridView gridview = (GridView) findViewById(R.id.accessibility_button_chooser_grid);
+        GridView gridview = findViewById(R.id.accessibility_button_chooser_grid);
         gridview.setAdapter(new TargetAdapter());
         gridview.setOnItemClickListener((parent, view, position, id) -> {
             onTargetSelected(mTargets.get(position));
diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java
index 35ffa71..999a908 100644
--- a/core/java/com/android/internal/app/AlertActivity.java
+++ b/core/java/com/android/internal/app/AlertActivity.java
@@ -67,10 +67,15 @@
 
     @Override
     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        event.setClassName(Dialog.class.getName());
-        event.setPackageName(getPackageName());
+        return dispatchPopulateAccessibilityEvent(this, event);
+    }
 
-        ViewGroup.LayoutParams params = getWindow().getAttributes();
+    public static boolean dispatchPopulateAccessibilityEvent(Activity act,
+            AccessibilityEvent event) {
+        event.setClassName(Dialog.class.getName());
+        event.setPackageName(act.getPackageName());
+
+        ViewGroup.LayoutParams params = act.getWindow().getAttributes();
         boolean isFullScreen = (params.width == ViewGroup.LayoutParams.MATCH_PARENT) &&
                 (params.height == ViewGroup.LayoutParams.MATCH_PARENT);
         event.setFullScreen(isFullScreen);
@@ -86,8 +91,7 @@
      * @see #mAlertParams
      */
     protected void setupAlert() {
-        mAlertParams.apply(mAlert);
-        mAlert.installContent();
+        mAlert.installContent(mAlertParams);
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 95c291a..46cb546 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -247,6 +247,11 @@
         return false;
     }
 
+    public void installContent(AlertParams params) {
+        params.apply(this);
+        installContent();
+    }
+
     public void installContent() {
         int contentView = selectContentView();
         mWindow.setContentView(contentView);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 622b708..b596678 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -287,7 +287,7 @@
             return;
         }
 
-        final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel);
+        final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
         if (rdl != null) {
             rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
                 @Override
@@ -922,10 +922,10 @@
         }
 
 
-        mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
+        mAdapterView = findViewById(R.id.resolver_list);
 
         if (count == 0 && mAdapter.mPlaceholderCount == 0) {
-            final TextView emptyView = (TextView) findViewById(R.id.empty);
+            final TextView emptyView = findViewById(R.id.empty);
             emptyView.setVisibility(View.VISIBLE);
             mAdapterView.setVisibility(View.GONE);
         } else {
@@ -959,7 +959,7 @@
 
     public void setTitleAndIcon() {
         if (mAdapter.getCount() == 0 && mAdapter.mPlaceholderCount == 0) {
-            final TextView titleView = (TextView) findViewById(R.id.title);
+            final TextView titleView = findViewById(R.id.title);
             if (titleView != null) {
                 titleView.setVisibility(View.GONE);
             }
@@ -970,14 +970,14 @@
                 : getTitleForAction(getTargetIntent().getAction(), mDefaultTitleResId);
 
         if (!TextUtils.isEmpty(title)) {
-            final TextView titleView = (TextView) findViewById(R.id.title);
+            final TextView titleView = findViewById(R.id.title);
             if (titleView != null) {
                 titleView.setText(title);
             }
             setTitle(title);
 
             // Try to initialize the title icon if we have a view for it and a title to match
-            final ImageView titleIcon = (ImageView) findViewById(R.id.title_icon);
+            final ImageView titleIcon = findViewById(R.id.title_icon);
             if (titleIcon != null) {
                 ApplicationInfo ai = null;
                 try {
@@ -994,7 +994,7 @@
             }
         }
 
-        final ImageView iconView = (ImageView) findViewById(R.id.icon);
+        final ImageView iconView = findViewById(R.id.icon);
         final DisplayResolveInfo iconInfo = mAdapter.getFilteredItem();
         if (iconView != null && iconInfo != null) {
             new LoadIconIntoViewTask(iconInfo, iconView).execute();
@@ -1003,7 +1003,7 @@
 
     public void resetAlwaysOrOnceButtonBar() {
         if (mSupportsAlwaysUseOption) {
-            final ViewGroup buttonLayout = (ViewGroup) findViewById(R.id.button_bar);
+            final ViewGroup buttonLayout = findViewById(R.id.button_bar);
             if (buttonLayout != null) {
                 buttonLayout.setVisibility(View.VISIBLE);
                 mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index cb2b019..46f47a3 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -16,6 +16,10 @@
 
 package com.android.internal.app;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -57,6 +61,10 @@
     private final boolean mCountryMode;
     private LayoutInflater mInflater;
 
+    private Locale mDisplayLocale = null;
+    // used to potentially cache a modified Context that uses mDisplayLocale
+    private Context mContextOverride = null;
+
     public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) {
         mCountryMode = countryMode;
         mLocaleOptions = new ArrayList<>(localeOptions.size());
@@ -126,6 +134,31 @@
         return position;
     }
 
+    /**
+     * Overrides the locale used to display localized labels. Setting the locale to null will reset
+     * the Adapter to use the default locale for the labels.
+     */
+    public void setDisplayLocale(@NonNull Context context, @Nullable Locale locale) {
+        if (locale == null) {
+            mDisplayLocale = null;
+            mContextOverride = null;
+        } else if (!locale.equals(mDisplayLocale)) {
+            mDisplayLocale = locale;
+            final Configuration configOverride = new Configuration();
+            configOverride.setLocale(locale);
+            mContextOverride = context.createConfigurationContext(configOverride);
+        }
+    }
+
+    private void setTextTo(@NonNull TextView textView, int resId) {
+        if (mContextOverride == null) {
+            textView.setText(resId);
+        } else {
+            textView.setText(mContextOverride.getText(resId));
+            // If mContextOverride is not null, mDisplayLocale can't be null either.
+        }
+    }
+
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
         if (convertView == null && mInflater == null) {
@@ -143,15 +176,16 @@
                 }
                 TextView textView = (TextView) convertView;
                 if (itemType == TYPE_HEADER_SUGGESTED) {
-                    textView.setText(R.string.language_picker_section_suggested);
+                    setTextTo(textView, R.string.language_picker_section_suggested);
                 } else {
                     if (mCountryMode) {
-                        textView.setText(R.string.region_picker_section_all);
+                        setTextTo(textView, R.string.region_picker_section_all);
                     } else {
-                        textView.setText(R.string.language_picker_section_all);
+                        setTextTo(textView, R.string.language_picker_section_all);
                     }
                 }
-                textView.setTextLocale(Locale.getDefault());
+                textView.setTextLocale(
+                        mDisplayLocale != null ? mDisplayLocale : Locale.getDefault());
                 break;
             default:
                 // Covers both null, and "reusing" a wrong kind of view
diff --git a/core/java/com/android/internal/graphics/ColorUtils.java b/core/java/com/android/internal/graphics/ColorUtils.java
new file mode 100644
index 0000000..6c1efa4
--- /dev/null
+++ b/core/java/com/android/internal/graphics/ColorUtils.java
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.graphics;
+
+import android.annotation.ColorInt;
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.graphics.Color;
+
+/**
+ * Copied from: frameworks/support/core-utils/java/android/support/v4/graphics/ColorUtils.java
+ *
+ * A set of color-related utility methods, building upon those available in {@code Color}.
+ */
+public final class ColorUtils {
+
+    private static final double XYZ_WHITE_REFERENCE_X = 95.047;
+    private static final double XYZ_WHITE_REFERENCE_Y = 100;
+    private static final double XYZ_WHITE_REFERENCE_Z = 108.883;
+    private static final double XYZ_EPSILON = 0.008856;
+    private static final double XYZ_KAPPA = 903.3;
+
+    private static final int MIN_ALPHA_SEARCH_MAX_ITERATIONS = 10;
+    private static final int MIN_ALPHA_SEARCH_PRECISION = 1;
+
+    private static final ThreadLocal<double[]> TEMP_ARRAY = new ThreadLocal<>();
+
+    private ColorUtils() {}
+
+    /**
+     * Composite two potentially translucent colors over each other and returns the result.
+     */
+    public static int compositeColors(@ColorInt int foreground, @ColorInt int background) {
+        int bgAlpha = Color.alpha(background);
+        int fgAlpha = Color.alpha(foreground);
+        int a = compositeAlpha(fgAlpha, bgAlpha);
+
+        int r = compositeComponent(Color.red(foreground), fgAlpha,
+                Color.red(background), bgAlpha, a);
+        int g = compositeComponent(Color.green(foreground), fgAlpha,
+                Color.green(background), bgAlpha, a);
+        int b = compositeComponent(Color.blue(foreground), fgAlpha,
+                Color.blue(background), bgAlpha, a);
+
+        return Color.argb(a, r, g, b);
+    }
+
+    private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) {
+        return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF);
+    }
+
+    private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) {
+        if (a == 0) return 0;
+        return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF);
+    }
+
+    /**
+     * Returns the luminance of a color as a float between {@code 0.0} and {@code 1.0}.
+     * <p>Defined as the Y component in the XYZ representation of {@code color}.</p>
+     */
+    @FloatRange(from = 0.0, to = 1.0)
+    public static double calculateLuminance(@ColorInt int color) {
+        final double[] result = getTempDouble3Array();
+        colorToXYZ(color, result);
+        // Luminance is the Y component
+        return result[1] / 100;
+    }
+
+    /**
+     * Returns the contrast ratio between {@code foreground} and {@code background}.
+     * {@code background} must be opaque.
+     * <p>
+     * Formula defined
+     * <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef">here</a>.
+     */
+    public static double calculateContrast(@ColorInt int foreground, @ColorInt int background) {
+        if (Color.alpha(background) != 255) {
+            throw new IllegalArgumentException("background can not be translucent: #"
+                    + Integer.toHexString(background));
+        }
+        if (Color.alpha(foreground) < 255) {
+            // If the foreground is translucent, composite the foreground over the background
+            foreground = compositeColors(foreground, background);
+        }
+
+        final double luminance1 = calculateLuminance(foreground) + 0.05;
+        final double luminance2 = calculateLuminance(background) + 0.05;
+
+        // Now return the lighter luminance divided by the darker luminance
+        return Math.max(luminance1, luminance2) / Math.min(luminance1, luminance2);
+    }
+
+    /**
+     * Calculates the minimum alpha value which can be applied to {@code foreground} so that would
+     * have a contrast value of at least {@code minContrastRatio} when compared to
+     * {@code background}.
+     *
+     * @param foreground       the foreground color
+     * @param background       the opaque background color
+     * @param minContrastRatio the minimum contrast ratio
+     * @return the alpha value in the range 0-255, or -1 if no value could be calculated
+     */
+    public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background,
+            float minContrastRatio) {
+        if (Color.alpha(background) != 255) {
+            throw new IllegalArgumentException("background can not be translucent: #"
+                    + Integer.toHexString(background));
+        }
+
+        // First lets check that a fully opaque foreground has sufficient contrast
+        int testForeground = setAlphaComponent(foreground, 255);
+        double testRatio = calculateContrast(testForeground, background);
+        if (testRatio < minContrastRatio) {
+            // Fully opaque foreground does not have sufficient contrast, return error
+            return -1;
+        }
+
+        // Binary search to find a value with the minimum value which provides sufficient contrast
+        int numIterations = 0;
+        int minAlpha = 0;
+        int maxAlpha = 255;
+
+        while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS &&
+                (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) {
+            final int testAlpha = (minAlpha + maxAlpha) / 2;
+
+            testForeground = setAlphaComponent(foreground, testAlpha);
+            testRatio = calculateContrast(testForeground, background);
+
+            if (testRatio < minContrastRatio) {
+                minAlpha = testAlpha;
+            } else {
+                maxAlpha = testAlpha;
+            }
+
+            numIterations++;
+        }
+
+        // Conservatively return the max of the range of possible alphas, which is known to pass.
+        return maxAlpha;
+    }
+
+    /**
+     * Convert RGB components to HSL (hue-saturation-lightness).
+     * <ul>
+     * <li>outHsl[0] is Hue [0 .. 360)</li>
+     * <li>outHsl[1] is Saturation [0...1]</li>
+     * <li>outHsl[2] is Lightness [0...1]</li>
+     * </ul>
+     *
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outHsl 3-element array which holds the resulting HSL components
+     */
+    public static void RGBToHSL(@IntRange(from = 0x0, to = 0xFF) int r,
+            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+            @NonNull float[] outHsl) {
+        final float rf = r / 255f;
+        final float gf = g / 255f;
+        final float bf = b / 255f;
+
+        final float max = Math.max(rf, Math.max(gf, bf));
+        final float min = Math.min(rf, Math.min(gf, bf));
+        final float deltaMaxMin = max - min;
+
+        float h, s;
+        float l = (max + min) / 2f;
+
+        if (max == min) {
+            // Monochromatic
+            h = s = 0f;
+        } else {
+            if (max == rf) {
+                h = ((gf - bf) / deltaMaxMin) % 6f;
+            } else if (max == gf) {
+                h = ((bf - rf) / deltaMaxMin) + 2f;
+            } else {
+                h = ((rf - gf) / deltaMaxMin) + 4f;
+            }
+
+            s = deltaMaxMin / (1f - Math.abs(2f * l - 1f));
+        }
+
+        h = (h * 60f) % 360f;
+        if (h < 0) {
+            h += 360f;
+        }
+
+        outHsl[0] = constrain(h, 0f, 360f);
+        outHsl[1] = constrain(s, 0f, 1f);
+        outHsl[2] = constrain(l, 0f, 1f);
+    }
+
+    /**
+     * Convert the ARGB color to its HSL (hue-saturation-lightness) components.
+     * <ul>
+     * <li>outHsl[0] is Hue [0 .. 360)</li>
+     * <li>outHsl[1] is Saturation [0...1]</li>
+     * <li>outHsl[2] is Lightness [0...1]</li>
+     * </ul>
+     *
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outHsl 3-element array which holds the resulting HSL components
+     */
+    public static void colorToHSL(@ColorInt int color, @NonNull float[] outHsl) {
+        RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), outHsl);
+    }
+
+    /**
+     * Convert HSL (hue-saturation-lightness) components to a RGB color.
+     * <ul>
+     * <li>hsl[0] is Hue [0 .. 360)</li>
+     * <li>hsl[1] is Saturation [0...1]</li>
+     * <li>hsl[2] is Lightness [0...1]</li>
+     * </ul>
+     * If hsv values are out of range, they are pinned.
+     *
+     * @param hsl 3-element array which holds the input HSL components
+     * @return the resulting RGB color
+     */
+    @ColorInt
+    public static int HSLToColor(@NonNull float[] hsl) {
+        final float h = hsl[0];
+        final float s = hsl[1];
+        final float l = hsl[2];
+
+        final float c = (1f - Math.abs(2 * l - 1f)) * s;
+        final float m = l - 0.5f * c;
+        final float x = c * (1f - Math.abs((h / 60f % 2f) - 1f));
+
+        final int hueSegment = (int) h / 60;
+
+        int r = 0, g = 0, b = 0;
+
+        switch (hueSegment) {
+            case 0:
+                r = Math.round(255 * (c + m));
+                g = Math.round(255 * (x + m));
+                b = Math.round(255 * m);
+                break;
+            case 1:
+                r = Math.round(255 * (x + m));
+                g = Math.round(255 * (c + m));
+                b = Math.round(255 * m);
+                break;
+            case 2:
+                r = Math.round(255 * m);
+                g = Math.round(255 * (c + m));
+                b = Math.round(255 * (x + m));
+                break;
+            case 3:
+                r = Math.round(255 * m);
+                g = Math.round(255 * (x + m));
+                b = Math.round(255 * (c + m));
+                break;
+            case 4:
+                r = Math.round(255 * (x + m));
+                g = Math.round(255 * m);
+                b = Math.round(255 * (c + m));
+                break;
+            case 5:
+            case 6:
+                r = Math.round(255 * (c + m));
+                g = Math.round(255 * m);
+                b = Math.round(255 * (x + m));
+                break;
+        }
+
+        r = constrain(r, 0, 255);
+        g = constrain(g, 0, 255);
+        b = constrain(b, 0, 255);
+
+        return Color.rgb(r, g, b);
+    }
+
+    /**
+     * Set the alpha component of {@code color} to be {@code alpha}.
+     */
+    @ColorInt
+    public static int setAlphaComponent(@ColorInt int color,
+            @IntRange(from = 0x0, to = 0xFF) int alpha) {
+        if (alpha < 0 || alpha > 255) {
+            throw new IllegalArgumentException("alpha must be between 0 and 255.");
+        }
+        return (color & 0x00ffffff) | (alpha << 24);
+    }
+
+    /**
+     * Convert the ARGB color to its CIE Lab representative components.
+     *
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outLab 3-element array which holds the resulting LAB components
+     */
+    public static void colorToLAB(@ColorInt int color, @NonNull double[] outLab) {
+        RGBToLAB(Color.red(color), Color.green(color), Color.blue(color), outLab);
+    }
+
+    /**
+     * Convert RGB components to its CIE Lab representative components.
+     *
+     * <ul>
+     * <li>outLab[0] is L [0 ...1)</li>
+     * <li>outLab[1] is a [-128...127)</li>
+     * <li>outLab[2] is b [-128...127)</li>
+     * </ul>
+     *
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outLab 3-element array which holds the resulting LAB components
+     */
+    public static void RGBToLAB(@IntRange(from = 0x0, to = 0xFF) int r,
+            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+            @NonNull double[] outLab) {
+        // First we convert RGB to XYZ
+        RGBToXYZ(r, g, b, outLab);
+        // outLab now contains XYZ
+        XYZToLAB(outLab[0], outLab[1], outLab[2], outLab);
+        // outLab now contains LAB representation
+    }
+
+    /**
+     * Convert the ARGB color to its CIE XYZ representative components.
+     *
+     * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
+     * </ul>
+     *
+     * @param color  the ARGB color to convert. The alpha component is ignored
+     * @param outXyz 3-element array which holds the resulting LAB components
+     */
+    public static void colorToXYZ(@ColorInt int color, @NonNull double[] outXyz) {
+        RGBToXYZ(Color.red(color), Color.green(color), Color.blue(color), outXyz);
+    }
+
+    /**
+     * Convert RGB components to its CIE XYZ representative components.
+     *
+     * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
+     * </ul>
+     *
+     * @param r      red component value [0..255]
+     * @param g      green component value [0..255]
+     * @param b      blue component value [0..255]
+     * @param outXyz 3-element array which holds the resulting XYZ components
+     */
+    public static void RGBToXYZ(@IntRange(from = 0x0, to = 0xFF) int r,
+            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+            @NonNull double[] outXyz) {
+        if (outXyz.length != 3) {
+            throw new IllegalArgumentException("outXyz must have a length of 3.");
+        }
+
+        double sr = r / 255.0;
+        sr = sr < 0.04045 ? sr / 12.92 : Math.pow((sr + 0.055) / 1.055, 2.4);
+        double sg = g / 255.0;
+        sg = sg < 0.04045 ? sg / 12.92 : Math.pow((sg + 0.055) / 1.055, 2.4);
+        double sb = b / 255.0;
+        sb = sb < 0.04045 ? sb / 12.92 : Math.pow((sb + 0.055) / 1.055, 2.4);
+
+        outXyz[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805);
+        outXyz[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722);
+        outXyz[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505);
+    }
+
+    /**
+     * Converts a color from CIE XYZ to CIE Lab representation.
+     *
+     * <p>This method expects the XYZ representation to use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outLab[0] is L [0 ...1)</li>
+     * <li>outLab[1] is a [-128...127)</li>
+     * <li>outLab[2] is b [-128...127)</li>
+     * </ul>
+     *
+     * @param x      X component value [0...95.047)
+     * @param y      Y component value [0...100)
+     * @param z      Z component value [0...108.883)
+     * @param outLab 3-element array which holds the resulting Lab components
+     */
+    public static void XYZToLAB(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
+            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
+            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z,
+            @NonNull double[] outLab) {
+        if (outLab.length != 3) {
+            throw new IllegalArgumentException("outLab must have a length of 3.");
+        }
+        x = pivotXyzComponent(x / XYZ_WHITE_REFERENCE_X);
+        y = pivotXyzComponent(y / XYZ_WHITE_REFERENCE_Y);
+        z = pivotXyzComponent(z / XYZ_WHITE_REFERENCE_Z);
+        outLab[0] = Math.max(0, 116 * y - 16);
+        outLab[1] = 500 * (x - y);
+        outLab[2] = 200 * (y - z);
+    }
+
+    /**
+     * Converts a color from CIE Lab to CIE XYZ representation.
+     *
+     * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * <ul>
+     * <li>outXyz[0] is X [0 ...95.047)</li>
+     * <li>outXyz[1] is Y [0...100)</li>
+     * <li>outXyz[2] is Z [0...108.883)</li>
+     * </ul>
+     *
+     * @param l      L component value [0...100)
+     * @param a      A component value [-128...127)
+     * @param b      B component value [-128...127)
+     * @param outXyz 3-element array which holds the resulting XYZ components
+     */
+    public static void LABToXYZ(@FloatRange(from = 0f, to = 100) final double l,
+            @FloatRange(from = -128, to = 127) final double a,
+            @FloatRange(from = -128, to = 127) final double b,
+            @NonNull double[] outXyz) {
+        final double fy = (l + 16) / 116;
+        final double fx = a / 500 + fy;
+        final double fz = fy - b / 200;
+
+        double tmp = Math.pow(fx, 3);
+        final double xr = tmp > XYZ_EPSILON ? tmp : (116 * fx - 16) / XYZ_KAPPA;
+        final double yr = l > XYZ_KAPPA * XYZ_EPSILON ? Math.pow(fy, 3) : l / XYZ_KAPPA;
+
+        tmp = Math.pow(fz, 3);
+        final double zr = tmp > XYZ_EPSILON ? tmp : (116 * fz - 16) / XYZ_KAPPA;
+
+        outXyz[0] = xr * XYZ_WHITE_REFERENCE_X;
+        outXyz[1] = yr * XYZ_WHITE_REFERENCE_Y;
+        outXyz[2] = zr * XYZ_WHITE_REFERENCE_Z;
+    }
+
+    /**
+     * Converts a color from CIE XYZ to its RGB representation.
+     *
+     * <p>This method expects the XYZ representation to use the D65 illuminant and the CIE
+     * 2° Standard Observer (1931).</p>
+     *
+     * @param x X component value [0...95.047)
+     * @param y Y component value [0...100)
+     * @param z Z component value [0...108.883)
+     * @return int containing the RGB representation
+     */
+    @ColorInt
+    public static int XYZToColor(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
+            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
+            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z) {
+        double r = (x * 3.2406 + y * -1.5372 + z * -0.4986) / 100;
+        double g = (x * -0.9689 + y * 1.8758 + z * 0.0415) / 100;
+        double b = (x * 0.0557 + y * -0.2040 + z * 1.0570) / 100;
+
+        r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
+        g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
+        b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
+
+        return Color.rgb(
+                constrain((int) Math.round(r * 255), 0, 255),
+                constrain((int) Math.round(g * 255), 0, 255),
+                constrain((int) Math.round(b * 255), 0, 255));
+    }
+
+    /**
+     * Converts a color from CIE Lab to its RGB representation.
+     *
+     * @param l L component value [0...100]
+     * @param a A component value [-128...127]
+     * @param b B component value [-128...127]
+     * @return int containing the RGB representation
+     */
+    @ColorInt
+    public static int LABToColor(@FloatRange(from = 0f, to = 100) final double l,
+            @FloatRange(from = -128, to = 127) final double a,
+            @FloatRange(from = -128, to = 127) final double b) {
+        final double[] result = getTempDouble3Array();
+        LABToXYZ(l, a, b, result);
+        return XYZToColor(result[0], result[1], result[2]);
+    }
+
+    /**
+     * Returns the euclidean distance between two LAB colors.
+     */
+    public static double distanceEuclidean(@NonNull double[] labX, @NonNull double[] labY) {
+        return Math.sqrt(Math.pow(labX[0] - labY[0], 2)
+                + Math.pow(labX[1] - labY[1], 2)
+                + Math.pow(labX[2] - labY[2], 2));
+    }
+
+    private static float constrain(float amount, float low, float high) {
+        return amount < low ? low : (amount > high ? high : amount);
+    }
+
+    private static int constrain(int amount, int low, int high) {
+        return amount < low ? low : (amount > high ? high : amount);
+    }
+
+    private static double pivotXyzComponent(double component) {
+        return component > XYZ_EPSILON
+                ? Math.pow(component, 1 / 3.0)
+                : (XYZ_KAPPA * component + 16) / 116;
+    }
+
+    /**
+     * Blend between two ARGB colors using the given ratio.
+     *
+     * <p>A blend ratio of 0.0 will result in {@code color1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code color2}.</p>
+     *
+     * @param color1 the first ARGB color
+     * @param color2 the second ARGB color
+     * @param ratio  the blend ratio of {@code color1} to {@code color2}
+     */
+    @ColorInt
+    public static int blendARGB(@ColorInt int color1, @ColorInt int color2,
+            @FloatRange(from = 0.0, to = 1.0) float ratio) {
+        final float inverseRatio = 1 - ratio;
+        float a = Color.alpha(color1) * inverseRatio + Color.alpha(color2) * ratio;
+        float r = Color.red(color1) * inverseRatio + Color.red(color2) * ratio;
+        float g = Color.green(color1) * inverseRatio + Color.green(color2) * ratio;
+        float b = Color.blue(color1) * inverseRatio + Color.blue(color2) * ratio;
+        return Color.argb((int) a, (int) r, (int) g, (int) b);
+    }
+
+    /**
+     * Blend between {@code hsl1} and {@code hsl2} using the given ratio. This will interpolate
+     * the hue using the shortest angle.
+     *
+     * <p>A blend ratio of 0.0 will result in {@code hsl1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code hsl2}.</p>
+     *
+     * @param hsl1      3-element array which holds the first HSL color
+     * @param hsl2      3-element array which holds the second HSL color
+     * @param ratio     the blend ratio of {@code hsl1} to {@code hsl2}
+     * @param outResult 3-element array which holds the resulting HSL components
+     */
+    public static void blendHSL(@NonNull float[] hsl1, @NonNull float[] hsl2,
+            @FloatRange(from = 0.0, to = 1.0) float ratio, @NonNull float[] outResult) {
+        if (outResult.length != 3) {
+            throw new IllegalArgumentException("result must have a length of 3.");
+        }
+        final float inverseRatio = 1 - ratio;
+        // Since hue is circular we will need to interpolate carefully
+        outResult[0] = circularInterpolate(hsl1[0], hsl2[0], ratio);
+        outResult[1] = hsl1[1] * inverseRatio + hsl2[1] * ratio;
+        outResult[2] = hsl1[2] * inverseRatio + hsl2[2] * ratio;
+    }
+
+    /**
+     * Blend between two CIE-LAB colors using the given ratio.
+     *
+     * <p>A blend ratio of 0.0 will result in {@code lab1}, 0.5 will give an even blend,
+     * 1.0 will result in {@code lab2}.</p>
+     *
+     * @param lab1      3-element array which holds the first LAB color
+     * @param lab2      3-element array which holds the second LAB color
+     * @param ratio     the blend ratio of {@code lab1} to {@code lab2}
+     * @param outResult 3-element array which holds the resulting LAB components
+     */
+    public static void blendLAB(@NonNull double[] lab1, @NonNull double[] lab2,
+            @FloatRange(from = 0.0, to = 1.0) double ratio, @NonNull double[] outResult) {
+        if (outResult.length != 3) {
+            throw new IllegalArgumentException("outResult must have a length of 3.");
+        }
+        final double inverseRatio = 1 - ratio;
+        outResult[0] = lab1[0] * inverseRatio + lab2[0] * ratio;
+        outResult[1] = lab1[1] * inverseRatio + lab2[1] * ratio;
+        outResult[2] = lab1[2] * inverseRatio + lab2[2] * ratio;
+    }
+
+    static float circularInterpolate(float a, float b, float f) {
+        if (Math.abs(b - a) > 180) {
+            if (b > a) {
+                a += 360;
+            } else {
+                b += 360;
+            }
+        }
+        return (a + ((b - a) * f)) % 360;
+    }
+
+    private static double[] getTempDouble3Array() {
+        double[] result = TEMP_ARRAY.get();
+        if (result == null) {
+            result = new double[3];
+            TEMP_ARRAY.set(result);
+        }
+        return result;
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java b/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
new file mode 100644
index 0000000..2d0ad66
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/ColorCutQuantizer.java
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.graphics.palette;
+
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.graphics.Color;
+import android.util.TimingLogger;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.PriorityQueue;
+
+import com.android.internal.graphics.ColorUtils;
+import com.android.internal.graphics.palette.Palette.Swatch;
+
+/**
+ * Copied from: frameworks/support/v7/palette/src/main/java/android/support/v7/
+ * graphics/ColorCutQuantizer.java
+ *
+ * An color quantizer based on the Median-cut algorithm, but optimized for picking out distinct
+ * colors rather than representation colors.
+ *
+ * The color space is represented as a 3-dimensional cube with each dimension being an RGB
+ * component. The cube is then repeatedly divided until we have reduced the color space to the
+ * requested number of colors. An average color is then generated from each cube.
+ *
+ * What makes this different to median-cut is that median-cut divided cubes so that all of the cubes
+ * have roughly the same population, where this quantizer divides boxes based on their color volume.
+ * This means that the color space is divided into distinct colors, rather than representative
+ * colors.
+ */
+final class ColorCutQuantizer {
+
+    private static final String LOG_TAG = "ColorCutQuantizer";
+    private static final boolean LOG_TIMINGS = false;
+
+    static final int COMPONENT_RED = -3;
+    static final int COMPONENT_GREEN = -2;
+    static final int COMPONENT_BLUE = -1;
+
+    private static final int QUANTIZE_WORD_WIDTH = 5;
+    private static final int QUANTIZE_WORD_MASK = (1 << QUANTIZE_WORD_WIDTH) - 1;
+
+    final int[] mColors;
+    final int[] mHistogram;
+    final List<Swatch> mQuantizedColors;
+    final TimingLogger mTimingLogger;
+    final Palette.Filter[] mFilters;
+
+    private final float[] mTempHsl = new float[3];
+
+    /**
+     * Constructor.
+     *
+     * @param pixels histogram representing an image's pixel data
+     * @param maxColors The maximum number of colors that should be in the result palette.
+     * @param filters Set of filters to use in the quantization stage
+     */
+    ColorCutQuantizer(final int[] pixels, final int maxColors, final Palette.Filter[] filters) {
+        mTimingLogger = LOG_TIMINGS ? new TimingLogger(LOG_TAG, "Creation") : null;
+        mFilters = filters;
+
+        final int[] hist = mHistogram = new int[1 << (QUANTIZE_WORD_WIDTH * 3)];
+        for (int i = 0; i < pixels.length; i++) {
+            final int quantizedColor = quantizeFromRgb888(pixels[i]);
+            // Now update the pixel value to the quantized value
+            pixels[i] = quantizedColor;
+            // And update the histogram
+            hist[quantizedColor]++;
+        }
+
+        if (LOG_TIMINGS) {
+            mTimingLogger.addSplit("Histogram created");
+        }
+
+        // Now let's count the number of distinct colors
+        int distinctColorCount = 0;
+        for (int color = 0; color < hist.length; color++) {
+            if (hist[color] > 0 && shouldIgnoreColor(color)) {
+                // If we should ignore the color, set the population to 0
+                hist[color] = 0;
+            }
+            if (hist[color] > 0) {
+                // If the color has population, increase the distinct color count
+                distinctColorCount++;
+            }
+        }
+
+        if (LOG_TIMINGS) {
+            mTimingLogger.addSplit("Filtered colors and distinct colors counted");
+        }
+
+        // Now lets go through create an array consisting of only distinct colors
+        final int[] colors = mColors = new int[distinctColorCount];
+        int distinctColorIndex = 0;
+        for (int color = 0; color < hist.length; color++) {
+            if (hist[color] > 0) {
+                colors[distinctColorIndex++] = color;
+            }
+        }
+
+        if (LOG_TIMINGS) {
+            mTimingLogger.addSplit("Distinct colors copied into array");
+        }
+
+        if (distinctColorCount <= maxColors) {
+            // The image has fewer colors than the maximum requested, so just return the colors
+            mQuantizedColors = new ArrayList<>();
+            for (int color : colors) {
+                mQuantizedColors.add(new Swatch(approximateToRgb888(color), hist[color]));
+            }
+
+            if (LOG_TIMINGS) {
+                mTimingLogger.addSplit("Too few colors present. Copied to Swatches");
+                mTimingLogger.dumpToLog();
+            }
+        } else {
+            // We need use quantization to reduce the number of colors
+            mQuantizedColors = quantizePixels(maxColors);
+
+            if (LOG_TIMINGS) {
+                mTimingLogger.addSplit("Quantized colors computed");
+                mTimingLogger.dumpToLog();
+            }
+        }
+    }
+
+    /**
+     * @return the list of quantized colors
+     */
+    List<Swatch> getQuantizedColors() {
+        return mQuantizedColors;
+    }
+
+    private List<Swatch> quantizePixels(int maxColors) {
+        // Create the priority queue which is sorted by volume descending. This means we always
+        // split the largest box in the queue
+        final PriorityQueue<Vbox> pq = new PriorityQueue<>(maxColors, VBOX_COMPARATOR_VOLUME);
+
+        // To start, offer a box which contains all of the colors
+        pq.offer(new Vbox(0, mColors.length - 1));
+
+        // Now go through the boxes, splitting them until we have reached maxColors or there are no
+        // more boxes to split
+        splitBoxes(pq, maxColors);
+
+        // Finally, return the average colors of the color boxes
+        return generateAverageColors(pq);
+    }
+
+    /**
+     * Iterate through the {@link java.util.Queue}, popping
+     * {@link ColorCutQuantizer.Vbox} objects from the queue
+     * and splitting them. Once split, the new box and the remaining box are offered back to the
+     * queue.
+     *
+     * @param queue {@link java.util.PriorityQueue} to poll for boxes
+     * @param maxSize Maximum amount of boxes to split
+     */
+    private void splitBoxes(final PriorityQueue<Vbox> queue, final int maxSize) {
+        while (queue.size() < maxSize) {
+            final Vbox vbox = queue.poll();
+
+            if (vbox != null && vbox.canSplit()) {
+                // First split the box, and offer the result
+                queue.offer(vbox.splitBox());
+
+                if (LOG_TIMINGS) {
+                    mTimingLogger.addSplit("Box split");
+                }
+                // Then offer the box back
+                queue.offer(vbox);
+            } else {
+                if (LOG_TIMINGS) {
+                    mTimingLogger.addSplit("All boxes split");
+                }
+                // If we get here then there are no more boxes to split, so return
+                return;
+            }
+        }
+    }
+
+    private List<Swatch> generateAverageColors(Collection<Vbox> vboxes) {
+        ArrayList<Swatch> colors = new ArrayList<>(vboxes.size());
+        for (Vbox vbox : vboxes) {
+            Swatch swatch = vbox.getAverageColor();
+            if (!shouldIgnoreColor(swatch)) {
+                // As we're averaging a color box, we can still get colors which we do not want, so
+                // we check again here
+                colors.add(swatch);
+            }
+        }
+        return colors;
+    }
+
+    /**
+     * Represents a tightly fitting box around a color space.
+     */
+    private class Vbox {
+        // lower and upper index are inclusive
+        private int mLowerIndex;
+        private int mUpperIndex;
+        // Population of colors within this box
+        private int mPopulation;
+
+        private int mMinRed, mMaxRed;
+        private int mMinGreen, mMaxGreen;
+        private int mMinBlue, mMaxBlue;
+
+        Vbox(int lowerIndex, int upperIndex) {
+            mLowerIndex = lowerIndex;
+            mUpperIndex = upperIndex;
+            fitBox();
+        }
+
+        final int getVolume() {
+            return (mMaxRed - mMinRed + 1) * (mMaxGreen - mMinGreen + 1) *
+                    (mMaxBlue - mMinBlue + 1);
+        }
+
+        final boolean canSplit() {
+            return getColorCount() > 1;
+        }
+
+        final int getColorCount() {
+            return 1 + mUpperIndex - mLowerIndex;
+        }
+
+        /**
+         * Recomputes the boundaries of this box to tightly fit the colors within the box.
+         */
+        final void fitBox() {
+            final int[] colors = mColors;
+            final int[] hist = mHistogram;
+
+            // Reset the min and max to opposite values
+            int minRed, minGreen, minBlue;
+            minRed = minGreen = minBlue = Integer.MAX_VALUE;
+            int maxRed, maxGreen, maxBlue;
+            maxRed = maxGreen = maxBlue = Integer.MIN_VALUE;
+            int count = 0;
+
+            for (int i = mLowerIndex; i <= mUpperIndex; i++) {
+                final int color = colors[i];
+                count += hist[color];
+
+                final int r = quantizedRed(color);
+                final int g = quantizedGreen(color);
+                final int b = quantizedBlue(color);
+                if (r > maxRed) {
+                    maxRed = r;
+                }
+                if (r < minRed) {
+                    minRed = r;
+                }
+                if (g > maxGreen) {
+                    maxGreen = g;
+                }
+                if (g < minGreen) {
+                    minGreen = g;
+                }
+                if (b > maxBlue) {
+                    maxBlue = b;
+                }
+                if (b < minBlue) {
+                    minBlue = b;
+                }
+            }
+
+            mMinRed = minRed;
+            mMaxRed = maxRed;
+            mMinGreen = minGreen;
+            mMaxGreen = maxGreen;
+            mMinBlue = minBlue;
+            mMaxBlue = maxBlue;
+            mPopulation = count;
+        }
+
+        /**
+         * Split this color box at the mid-point along its longest dimension
+         *
+         * @return the new ColorBox
+         */
+        final Vbox splitBox() {
+            if (!canSplit()) {
+                throw new IllegalStateException("Can not split a box with only 1 color");
+            }
+
+            // find median along the longest dimension
+            final int splitPoint = findSplitPoint();
+
+            Vbox newBox = new Vbox(splitPoint + 1, mUpperIndex);
+
+            // Now change this box's upperIndex and recompute the color boundaries
+            mUpperIndex = splitPoint;
+            fitBox();
+
+            return newBox;
+        }
+
+        /**
+         * @return the dimension which this box is largest in
+         */
+        final int getLongestColorDimension() {
+            final int redLength = mMaxRed - mMinRed;
+            final int greenLength = mMaxGreen - mMinGreen;
+            final int blueLength = mMaxBlue - mMinBlue;
+
+            if (redLength >= greenLength && redLength >= blueLength) {
+                return COMPONENT_RED;
+            } else if (greenLength >= redLength && greenLength >= blueLength) {
+                return COMPONENT_GREEN;
+            } else {
+                return COMPONENT_BLUE;
+            }
+        }
+
+        /**
+         * Finds the point within this box's lowerIndex and upperIndex index of where to split.
+         *
+         * This is calculated by finding the longest color dimension, and then sorting the
+         * sub-array based on that dimension value in each color. The colors are then iterated over
+         * until a color is found with at least the midpoint of the whole box's dimension midpoint.
+         *
+         * @return the index of the colors array to split from
+         */
+        final int findSplitPoint() {
+            final int longestDimension = getLongestColorDimension();
+            final int[] colors = mColors;
+            final int[] hist = mHistogram;
+
+            // We need to sort the colors in this box based on the longest color dimension.
+            // As we can't use a Comparator to define the sort logic, we modify each color so that
+            // its most significant is the desired dimension
+            modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex);
+
+            // Now sort... Arrays.sort uses a exclusive toIndex so we need to add 1
+            Arrays.sort(colors, mLowerIndex, mUpperIndex + 1);
+
+            // Now revert all of the colors so that they are packed as RGB again
+            modifySignificantOctet(colors, longestDimension, mLowerIndex, mUpperIndex);
+
+            final int midPoint = mPopulation / 2;
+            for (int i = mLowerIndex, count = 0; i <= mUpperIndex; i++)  {
+                count += hist[colors[i]];
+                if (count >= midPoint) {
+                    return i;
+                }
+            }
+
+            return mLowerIndex;
+        }
+
+        /**
+         * @return the average color of this box.
+         */
+        final Swatch getAverageColor() {
+            final int[] colors = mColors;
+            final int[] hist = mHistogram;
+            int redSum = 0;
+            int greenSum = 0;
+            int blueSum = 0;
+            int totalPopulation = 0;
+
+            for (int i = mLowerIndex; i <= mUpperIndex; i++) {
+                final int color = colors[i];
+                final int colorPopulation = hist[color];
+
+                totalPopulation += colorPopulation;
+                redSum += colorPopulation * quantizedRed(color);
+                greenSum += colorPopulation * quantizedGreen(color);
+                blueSum += colorPopulation * quantizedBlue(color);
+            }
+
+            final int redMean = Math.round(redSum / (float) totalPopulation);
+            final int greenMean = Math.round(greenSum / (float) totalPopulation);
+            final int blueMean = Math.round(blueSum / (float) totalPopulation);
+
+            return new Swatch(approximateToRgb888(redMean, greenMean, blueMean), totalPopulation);
+        }
+    }
+
+    /**
+     * Modify the significant octet in a packed color int. Allows sorting based on the value of a
+     * single color component. This relies on all components being the same word size.
+     *
+     * @see Vbox#findSplitPoint()
+     */
+    static void modifySignificantOctet(final int[] a, final int dimension,
+            final int lower, final int upper) {
+        switch (dimension) {
+            case COMPONENT_RED:
+                // Already in RGB, no need to do anything
+                break;
+            case COMPONENT_GREEN:
+                // We need to do a RGB to GRB swap, or vice-versa
+                for (int i = lower; i <= upper; i++) {
+                    final int color = a[i];
+                    a[i] = quantizedGreen(color) << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)
+                            | quantizedRed(color) << QUANTIZE_WORD_WIDTH
+                            | quantizedBlue(color);
+                }
+                break;
+            case COMPONENT_BLUE:
+                // We need to do a RGB to BGR swap, or vice-versa
+                for (int i = lower; i <= upper; i++) {
+                    final int color = a[i];
+                    a[i] = quantizedBlue(color) << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)
+                            | quantizedGreen(color) << QUANTIZE_WORD_WIDTH
+                            | quantizedRed(color);
+                }
+                break;
+        }
+    }
+
+    private boolean shouldIgnoreColor(int color565) {
+        final int rgb = approximateToRgb888(color565);
+        ColorUtils.colorToHSL(rgb, mTempHsl);
+        return shouldIgnoreColor(rgb, mTempHsl);
+    }
+
+    private boolean shouldIgnoreColor(Swatch color) {
+        return shouldIgnoreColor(color.getRgb(), color.getHsl());
+    }
+
+    private boolean shouldIgnoreColor(int rgb, float[] hsl) {
+        if (mFilters != null && mFilters.length > 0) {
+            for (int i = 0, count = mFilters.length; i < count; i++) {
+                if (!mFilters[i].isAllowed(rgb, hsl)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Comparator which sorts {@link Vbox} instances based on their volume, in descending order
+     */
+    private static final Comparator<Vbox> VBOX_COMPARATOR_VOLUME = new Comparator<Vbox>() {
+        @Override
+        public int compare(Vbox lhs, Vbox rhs) {
+            return rhs.getVolume() - lhs.getVolume();
+        }
+    };
+
+    /**
+     * Quantized a RGB888 value to have a word width of {@value #QUANTIZE_WORD_WIDTH}.
+     */
+    private static int quantizeFromRgb888(int color) {
+        int r = modifyWordWidth(Color.red(color), 8, QUANTIZE_WORD_WIDTH);
+        int g = modifyWordWidth(Color.green(color), 8, QUANTIZE_WORD_WIDTH);
+        int b = modifyWordWidth(Color.blue(color), 8, QUANTIZE_WORD_WIDTH);
+        return r << (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH) | g << QUANTIZE_WORD_WIDTH | b;
+    }
+
+    /**
+     * Quantized RGB888 values to have a word width of {@value #QUANTIZE_WORD_WIDTH}.
+     */
+    static int approximateToRgb888(int r, int g, int b) {
+        return Color.rgb(modifyWordWidth(r, QUANTIZE_WORD_WIDTH, 8),
+                modifyWordWidth(g, QUANTIZE_WORD_WIDTH, 8),
+                modifyWordWidth(b, QUANTIZE_WORD_WIDTH, 8));
+    }
+
+    private static int approximateToRgb888(int color) {
+        return approximateToRgb888(quantizedRed(color), quantizedGreen(color), quantizedBlue(color));
+    }
+
+    /**
+     * @return red component of the quantized color
+     */
+    static int quantizedRed(int color) {
+        return (color >> (QUANTIZE_WORD_WIDTH + QUANTIZE_WORD_WIDTH)) & QUANTIZE_WORD_MASK;
+    }
+
+    /**
+     * @return green component of a quantized color
+     */
+    static int quantizedGreen(int color) {
+        return (color >> QUANTIZE_WORD_WIDTH) & QUANTIZE_WORD_MASK;
+    }
+
+    /**
+     * @return blue component of a quantized color
+     */
+    static int quantizedBlue(int color) {
+        return color & QUANTIZE_WORD_MASK;
+    }
+
+    private static int modifyWordWidth(int value, int currentWidth, int targetWidth) {
+        final int newValue;
+        if (targetWidth > currentWidth) {
+            // If we're approximating up in word width, we'll shift up
+            newValue = value << (targetWidth - currentWidth);
+        } else {
+            // Else, we will just shift and keep the MSB
+            newValue = value >> (currentWidth - targetWidth);
+        }
+        return newValue & ((1 << targetWidth) - 1);
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/graphics/palette/Palette.java b/core/java/com/android/internal/graphics/palette/Palette.java
new file mode 100644
index 0000000..9f1504a
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/Palette.java
@@ -0,0 +1,990 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.graphics.palette;
+
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.os.AsyncTask;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.SparseBooleanArray;
+import android.util.TimingLogger;
+
+import com.android.internal.graphics.ColorUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Copied from: /frameworks/support/v7/palette/src/main/java/android/support/v7/
+ * graphics/Palette.java
+ *
+ * A helper class to extract prominent colors from an image.
+ * <p>
+ * A number of colors with different profiles are extracted from the image:
+ * <ul>
+ *     <li>Vibrant</li>
+ *     <li>Vibrant Dark</li>
+ *     <li>Vibrant Light</li>
+ *     <li>Muted</li>
+ *     <li>Muted Dark</li>
+ *     <li>Muted Light</li>
+ * </ul>
+ * These can be retrieved from the appropriate getter method.
+ *
+ * <p>
+ * Instances are created with a {@link Palette.Builder} which supports several options to tweak the
+ * generated Palette. See that class' documentation for more information.
+ * <p>
+ * Generation should always be completed on a background thread, ideally the one in
+ * which you load your image on. {@link Palette.Builder} supports both synchronous and asynchronous
+ * generation:
+ *
+ * <pre>
+ * // Synchronous
+ * Palette p = Palette.from(bitmap).generate();
+ *
+ * // Asynchronous
+ * Palette.from(bitmap).generate(new PaletteAsyncListener() {
+ *     public void onGenerated(Palette p) {
+ *         // Use generated instance
+ *     }
+ * });
+ * </pre>
+ */
+public final class Palette {
+
+    /**
+     * Listener to be used with {@link #generateAsync(Bitmap, Palette.PaletteAsyncListener)} or
+     * {@link #generateAsync(Bitmap, int, Palette.PaletteAsyncListener)}
+     */
+    public interface PaletteAsyncListener {
+
+        /**
+         * Called when the {@link Palette} has been generated.
+         */
+        void onGenerated(Palette palette);
+    }
+
+    static final int DEFAULT_RESIZE_BITMAP_AREA = 112 * 112;
+    static final int DEFAULT_CALCULATE_NUMBER_COLORS = 16;
+
+    static final float MIN_CONTRAST_TITLE_TEXT = 3.0f;
+    static final float MIN_CONTRAST_BODY_TEXT = 4.5f;
+
+    static final String LOG_TAG = "Palette";
+    static final boolean LOG_TIMINGS = false;
+
+    /**
+     * Start generating a {@link Palette} with the returned {@link Palette.Builder} instance.
+     */
+    public static Palette.Builder from(Bitmap bitmap) {
+        return new Palette.Builder(bitmap);
+    }
+
+    /**
+     * Generate a {@link Palette} from the pre-generated list of {@link Palette.Swatch} swatches.
+     * This is useful for testing, or if you want to resurrect a {@link Palette} instance from a
+     * list of swatches. Will return null if the {@code swatches} is null.
+     */
+    public static Palette from(List<Palette.Swatch> swatches) {
+        return new Palette.Builder(swatches).generate();
+    }
+
+    /**
+     * @deprecated Use {@link Palette.Builder} to generate the Palette.
+     */
+    @Deprecated
+    public static Palette generate(Bitmap bitmap) {
+        return from(bitmap).generate();
+    }
+
+    /**
+     * @deprecated Use {@link Palette.Builder} to generate the Palette.
+     */
+    @Deprecated
+    public static Palette generate(Bitmap bitmap, int numColors) {
+        return from(bitmap).maximumColorCount(numColors).generate();
+    }
+
+    /**
+     * @deprecated Use {@link Palette.Builder} to generate the Palette.
+     */
+    @Deprecated
+    public static AsyncTask<Bitmap, Void, Palette> generateAsync(
+            Bitmap bitmap, Palette.PaletteAsyncListener listener) {
+        return from(bitmap).generate(listener);
+    }
+
+    /**
+     * @deprecated Use {@link Palette.Builder} to generate the Palette.
+     */
+    @Deprecated
+    public static AsyncTask<Bitmap, Void, Palette> generateAsync(
+            final Bitmap bitmap, final int numColors, final Palette.PaletteAsyncListener listener) {
+        return from(bitmap).maximumColorCount(numColors).generate(listener);
+    }
+
+    private final List<Palette.Swatch> mSwatches;
+    private final List<Target> mTargets;
+
+    private final Map<Target, Palette.Swatch> mSelectedSwatches;
+    private final SparseBooleanArray mUsedColors;
+
+    private final Palette.Swatch mDominantSwatch;
+
+    Palette(List<Palette.Swatch> swatches, List<Target> targets) {
+        mSwatches = swatches;
+        mTargets = targets;
+
+        mUsedColors = new SparseBooleanArray();
+        mSelectedSwatches = new ArrayMap<>();
+
+        mDominantSwatch = findDominantSwatch();
+    }
+
+    /**
+     * Returns all of the swatches which make up the palette.
+     */
+    @NonNull
+    public List<Palette.Swatch> getSwatches() {
+        return Collections.unmodifiableList(mSwatches);
+    }
+
+    /**
+     * Returns the targets used to generate this palette.
+     */
+    @NonNull
+    public List<Target> getTargets() {
+        return Collections.unmodifiableList(mTargets);
+    }
+
+    /**
+     * Returns the most vibrant swatch in the palette. Might be null.
+     *
+     * @see Target#VIBRANT
+     */
+    @Nullable
+    public Palette.Swatch getVibrantSwatch() {
+        return getSwatchForTarget(Target.VIBRANT);
+    }
+
+    /**
+     * Returns a light and vibrant swatch from the palette. Might be null.
+     *
+     * @see Target#LIGHT_VIBRANT
+     */
+    @Nullable
+    public Palette.Swatch getLightVibrantSwatch() {
+        return getSwatchForTarget(Target.LIGHT_VIBRANT);
+    }
+
+    /**
+     * Returns a dark and vibrant swatch from the palette. Might be null.
+     *
+     * @see Target#DARK_VIBRANT
+     */
+    @Nullable
+    public Palette.Swatch getDarkVibrantSwatch() {
+        return getSwatchForTarget(Target.DARK_VIBRANT);
+    }
+
+    /**
+     * Returns a muted swatch from the palette. Might be null.
+     *
+     * @see Target#MUTED
+     */
+    @Nullable
+    public Palette.Swatch getMutedSwatch() {
+        return getSwatchForTarget(Target.MUTED);
+    }
+
+    /**
+     * Returns a muted and light swatch from the palette. Might be null.
+     *
+     * @see Target#LIGHT_MUTED
+     */
+    @Nullable
+    public Palette.Swatch getLightMutedSwatch() {
+        return getSwatchForTarget(Target.LIGHT_MUTED);
+    }
+
+    /**
+     * Returns a muted and dark swatch from the palette. Might be null.
+     *
+     * @see Target#DARK_MUTED
+     */
+    @Nullable
+    public Palette.Swatch getDarkMutedSwatch() {
+        return getSwatchForTarget(Target.DARK_MUTED);
+    }
+
+    /**
+     * Returns the most vibrant color in the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getVibrantSwatch()
+     */
+    @ColorInt
+    public int getVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.VIBRANT, defaultColor);
+    }
+
+    /**
+     * Returns a light and vibrant color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getLightVibrantSwatch()
+     */
+    @ColorInt
+    public int getLightVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.LIGHT_VIBRANT, defaultColor);
+    }
+
+    /**
+     * Returns a dark and vibrant color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getDarkVibrantSwatch()
+     */
+    @ColorInt
+    public int getDarkVibrantColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.DARK_VIBRANT, defaultColor);
+    }
+
+    /**
+     * Returns a muted color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getMutedSwatch()
+     */
+    @ColorInt
+    public int getMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.MUTED, defaultColor);
+    }
+
+    /**
+     * Returns a muted and light color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getLightMutedSwatch()
+     */
+    @ColorInt
+    public int getLightMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.LIGHT_MUTED, defaultColor);
+    }
+
+    /**
+     * Returns a muted and dark color from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getDarkMutedSwatch()
+     */
+    @ColorInt
+    public int getDarkMutedColor(@ColorInt final int defaultColor) {
+        return getColorForTarget(Target.DARK_MUTED, defaultColor);
+    }
+
+    /**
+     * Returns the selected swatch for the given target from the palette, or {@code null} if one
+     * could not be found.
+     */
+    @Nullable
+    public Palette.Swatch getSwatchForTarget(@NonNull final Target target) {
+        return mSelectedSwatches.get(target);
+    }
+
+    /**
+     * Returns the selected color for the given target from the palette as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     */
+    @ColorInt
+    public int getColorForTarget(@NonNull final Target target, @ColorInt final int defaultColor) {
+        Palette.Swatch swatch = getSwatchForTarget(target);
+        return swatch != null ? swatch.getRgb() : defaultColor;
+    }
+
+    /**
+     * Returns the dominant swatch from the palette.
+     *
+     * <p>The dominant swatch is defined as the swatch with the greatest population (frequency)
+     * within the palette.</p>
+     */
+    @Nullable
+    public Palette.Swatch getDominantSwatch() {
+        return mDominantSwatch;
+    }
+
+    /**
+     * Returns the color of the dominant swatch from the palette, as an RGB packed int.
+     *
+     * @param defaultColor value to return if the swatch isn't available
+     * @see #getDominantSwatch()
+     */
+    @ColorInt
+    public int getDominantColor(@ColorInt int defaultColor) {
+        return mDominantSwatch != null ? mDominantSwatch.getRgb() : defaultColor;
+    }
+
+    void generate() {
+        // We need to make sure that the scored targets are generated first. This is so that
+        // inherited targets have something to inherit from
+        for (int i = 0, count = mTargets.size(); i < count; i++) {
+            final Target target = mTargets.get(i);
+            target.normalizeWeights();
+            mSelectedSwatches.put(target, generateScoredTarget(target));
+        }
+        // We now clear out the used colors
+        mUsedColors.clear();
+    }
+
+    private Palette.Swatch generateScoredTarget(final Target target) {
+        final Palette.Swatch maxScoreSwatch = getMaxScoredSwatchForTarget(target);
+        if (maxScoreSwatch != null && target.isExclusive()) {
+            // If we have a swatch, and the target is exclusive, add the color to the used list
+            mUsedColors.append(maxScoreSwatch.getRgb(), true);
+        }
+        return maxScoreSwatch;
+    }
+
+    private Palette.Swatch getMaxScoredSwatchForTarget(final Target target) {
+        float maxScore = 0;
+        Palette.Swatch maxScoreSwatch = null;
+        for (int i = 0, count = mSwatches.size(); i < count; i++) {
+            final Palette.Swatch swatch = mSwatches.get(i);
+            if (shouldBeScoredForTarget(swatch, target)) {
+                final float score = generateScore(swatch, target);
+                if (maxScoreSwatch == null || score > maxScore) {
+                    maxScoreSwatch = swatch;
+                    maxScore = score;
+                }
+            }
+        }
+        return maxScoreSwatch;
+    }
+
+    private boolean shouldBeScoredForTarget(final Palette.Swatch swatch, final Target target) {
+        // Check whether the HSL values are within the correct ranges, and this color hasn't
+        // been used yet.
+        final float hsl[] = swatch.getHsl();
+        return hsl[1] >= target.getMinimumSaturation() && hsl[1] <= target.getMaximumSaturation()
+                && hsl[2] >= target.getMinimumLightness() && hsl[2] <= target.getMaximumLightness()
+                && !mUsedColors.get(swatch.getRgb());
+    }
+
+    private float generateScore(Palette.Swatch swatch, Target target) {
+        final float[] hsl = swatch.getHsl();
+
+        float saturationScore = 0;
+        float luminanceScore = 0;
+        float populationScore = 0;
+
+        final int maxPopulation = mDominantSwatch != null ? mDominantSwatch.getPopulation() : 1;
+
+        if (target.getSaturationWeight() > 0) {
+            saturationScore = target.getSaturationWeight()
+                    * (1f - Math.abs(hsl[1] - target.getTargetSaturation()));
+        }
+        if (target.getLightnessWeight() > 0) {
+            luminanceScore = target.getLightnessWeight()
+                    * (1f - Math.abs(hsl[2] - target.getTargetLightness()));
+        }
+        if (target.getPopulationWeight() > 0) {
+            populationScore = target.getPopulationWeight()
+                    * (swatch.getPopulation() / (float) maxPopulation);
+        }
+
+        return saturationScore + luminanceScore + populationScore;
+    }
+
+    private Palette.Swatch findDominantSwatch() {
+        int maxPop = Integer.MIN_VALUE;
+        Palette.Swatch maxSwatch = null;
+        for (int i = 0, count = mSwatches.size(); i < count; i++) {
+            Palette.Swatch swatch = mSwatches.get(i);
+            if (swatch.getPopulation() > maxPop) {
+                maxSwatch = swatch;
+                maxPop = swatch.getPopulation();
+            }
+        }
+        return maxSwatch;
+    }
+
+    private static float[] copyHslValues(Palette.Swatch color) {
+        final float[] newHsl = new float[3];
+        System.arraycopy(color.getHsl(), 0, newHsl, 0, 3);
+        return newHsl;
+    }
+
+    /**
+     * Represents a color swatch generated from an image's palette. The RGB color can be retrieved
+     * by calling {@link #getRgb()}.
+     */
+    public static final class Swatch {
+        private final int mRed, mGreen, mBlue;
+        private final int mRgb;
+        private final int mPopulation;
+
+        private boolean mGeneratedTextColors;
+        private int mTitleTextColor;
+        private int mBodyTextColor;
+
+        private float[] mHsl;
+
+        public Swatch(@ColorInt int color, int population) {
+            mRed = Color.red(color);
+            mGreen = Color.green(color);
+            mBlue = Color.blue(color);
+            mRgb = color;
+            mPopulation = population;
+        }
+
+        Swatch(int red, int green, int blue, int population) {
+            mRed = red;
+            mGreen = green;
+            mBlue = blue;
+            mRgb = Color.rgb(red, green, blue);
+            mPopulation = population;
+        }
+
+        Swatch(float[] hsl, int population) {
+            this(ColorUtils.HSLToColor(hsl), population);
+            mHsl = hsl;
+        }
+
+        /**
+         * @return this swatch's RGB color value
+         */
+        @ColorInt
+        public int getRgb() {
+            return mRgb;
+        }
+
+        /**
+         * Return this swatch's HSL values.
+         *     hsv[0] is Hue [0 .. 360)
+         *     hsv[1] is Saturation [0...1]
+         *     hsv[2] is Lightness [0...1]
+         */
+        public float[] getHsl() {
+            if (mHsl == null) {
+                mHsl = new float[3];
+            }
+            ColorUtils.RGBToHSL(mRed, mGreen, mBlue, mHsl);
+            return mHsl;
+        }
+
+        /**
+         * @return the number of pixels represented by this swatch
+         */
+        public int getPopulation() {
+            return mPopulation;
+        }
+
+        /**
+         * Returns an appropriate color to use for any 'title' text which is displayed over this
+         * {@link Palette.Swatch}'s color. This color is guaranteed to have sufficient contrast.
+         */
+        @ColorInt
+        public int getTitleTextColor() {
+            ensureTextColorsGenerated();
+            return mTitleTextColor;
+        }
+
+        /**
+         * Returns an appropriate color to use for any 'body' text which is displayed over this
+         * {@link Palette.Swatch}'s color. This color is guaranteed to have sufficient contrast.
+         */
+        @ColorInt
+        public int getBodyTextColor() {
+            ensureTextColorsGenerated();
+            return mBodyTextColor;
+        }
+
+        private void ensureTextColorsGenerated() {
+            if (!mGeneratedTextColors) {
+                // First check white, as most colors will be dark
+                final int lightBodyAlpha = ColorUtils.calculateMinimumAlpha(
+                        Color.WHITE, mRgb, MIN_CONTRAST_BODY_TEXT);
+                final int lightTitleAlpha = ColorUtils.calculateMinimumAlpha(
+                        Color.WHITE, mRgb, MIN_CONTRAST_TITLE_TEXT);
+
+                if (lightBodyAlpha != -1 && lightTitleAlpha != -1) {
+                    // If we found valid light values, use them and return
+                    mBodyTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha);
+                    mTitleTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha);
+                    mGeneratedTextColors = true;
+                    return;
+                }
+
+                final int darkBodyAlpha = ColorUtils.calculateMinimumAlpha(
+                        Color.BLACK, mRgb, MIN_CONTRAST_BODY_TEXT);
+                final int darkTitleAlpha = ColorUtils.calculateMinimumAlpha(
+                        Color.BLACK, mRgb, MIN_CONTRAST_TITLE_TEXT);
+
+                if (darkBodyAlpha != -1 && darkTitleAlpha != -1) {
+                    // If we found valid dark values, use them and return
+                    mBodyTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha);
+                    mTitleTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha);
+                    mGeneratedTextColors = true;
+                    return;
+                }
+
+                // If we reach here then we can not find title and body values which use the same
+                // lightness, we need to use mismatched values
+                mBodyTextColor = lightBodyAlpha != -1
+                        ? ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha)
+                        : ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha);
+                mTitleTextColor = lightTitleAlpha != -1
+                        ? ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha)
+                        : ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha);
+                mGeneratedTextColors = true;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder(getClass().getSimpleName())
+                    .append(" [RGB: #").append(Integer.toHexString(getRgb())).append(']')
+                    .append(" [HSL: ").append(Arrays.toString(getHsl())).append(']')
+                    .append(" [Population: ").append(mPopulation).append(']')
+                    .append(" [Title Text: #").append(Integer.toHexString(getTitleTextColor()))
+                    .append(']')
+                    .append(" [Body Text: #").append(Integer.toHexString(getBodyTextColor()))
+                    .append(']').toString();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            Palette.Swatch
+                    swatch = (Palette.Swatch) o;
+            return mPopulation == swatch.mPopulation && mRgb == swatch.mRgb;
+        }
+
+        @Override
+        public int hashCode() {
+            return 31 * mRgb + mPopulation;
+        }
+    }
+
+    /**
+     * Builder class for generating {@link Palette} instances.
+     */
+    public static final class Builder {
+        private final List<Palette.Swatch> mSwatches;
+        private final Bitmap mBitmap;
+
+        private final List<Target> mTargets = new ArrayList<>();
+
+        private int mMaxColors = DEFAULT_CALCULATE_NUMBER_COLORS;
+        private int mResizeArea = DEFAULT_RESIZE_BITMAP_AREA;
+        private int mResizeMaxDimension = -1;
+
+        private final List<Palette.Filter> mFilters = new ArrayList<>();
+        private Rect mRegion;
+
+        /**
+         * Construct a new {@link Palette.Builder} using a source {@link Bitmap}
+         */
+        public Builder(Bitmap bitmap) {
+            if (bitmap == null || bitmap.isRecycled()) {
+                throw new IllegalArgumentException("Bitmap is not valid");
+            }
+            mFilters.add(DEFAULT_FILTER);
+            mBitmap = bitmap;
+            mSwatches = null;
+
+            // Add the default targets
+            mTargets.add(Target.LIGHT_VIBRANT);
+            mTargets.add(Target.VIBRANT);
+            mTargets.add(Target.DARK_VIBRANT);
+            mTargets.add(Target.LIGHT_MUTED);
+            mTargets.add(Target.MUTED);
+            mTargets.add(Target.DARK_MUTED);
+        }
+
+        /**
+         * Construct a new {@link Palette.Builder} using a list of {@link Palette.Swatch} instances.
+         * Typically only used for testing.
+         */
+        public Builder(List<Palette.Swatch> swatches) {
+            if (swatches == null || swatches.isEmpty()) {
+                throw new IllegalArgumentException("List of Swatches is not valid");
+            }
+            mFilters.add(DEFAULT_FILTER);
+            mSwatches = swatches;
+            mBitmap = null;
+        }
+
+        /**
+         * Set the maximum number of colors to use in the quantization step when using a
+         * {@link android.graphics.Bitmap} as the source.
+         * <p>
+         * Good values for depend on the source image type. For landscapes, good values are in
+         * the range 10-16. For images which are largely made up of people's faces then this
+         * value should be increased to ~24.
+         */
+        @NonNull
+        public Palette.Builder maximumColorCount(int colors) {
+            mMaxColors = colors;
+            return this;
+        }
+
+        /**
+         * Set the resize value when using a {@link android.graphics.Bitmap} as the source.
+         * If the bitmap's largest dimension is greater than the value specified, then the bitmap
+         * will be resized so that its largest dimension matches {@code maxDimension}. If the
+         * bitmap is smaller or equal, the original is used as-is.
+         *
+         * @deprecated Using {@link #resizeBitmapArea(int)} is preferred since it can handle
+         * abnormal aspect ratios more gracefully.
+         *
+         * @param maxDimension the number of pixels that the max dimension should be scaled down to,
+         *                     or any value <= 0 to disable resizing.
+         */
+        @NonNull
+        @Deprecated
+        public Palette.Builder resizeBitmapSize(final int maxDimension) {
+            mResizeMaxDimension = maxDimension;
+            mResizeArea = -1;
+            return this;
+        }
+
+        /**
+         * Set the resize value when using a {@link android.graphics.Bitmap} as the source.
+         * If the bitmap's area is greater than the value specified, then the bitmap
+         * will be resized so that its area matches {@code area}. If the
+         * bitmap is smaller or equal, the original is used as-is.
+         * <p>
+         * This value has a large effect on the processing time. The larger the resized image is,
+         * the greater time it will take to generate the palette. The smaller the image is, the
+         * more detail is lost in the resulting image and thus less precision for color selection.
+         *
+         * @param area the number of pixels that the intermediary scaled down Bitmap should cover,
+         *             or any value <= 0 to disable resizing.
+         */
+        @NonNull
+        public Palette.Builder resizeBitmapArea(final int area) {
+            mResizeArea = area;
+            mResizeMaxDimension = -1;
+            return this;
+        }
+
+        /**
+         * Clear all added filters. This includes any default filters added automatically by
+         * {@link Palette}.
+         */
+        @NonNull
+        public Palette.Builder clearFilters() {
+            mFilters.clear();
+            return this;
+        }
+
+        /**
+         * Add a filter to be able to have fine grained control over which colors are
+         * allowed in the resulting palette.
+         *
+         * @param filter filter to add.
+         */
+        @NonNull
+        public Palette.Builder addFilter(
+                Palette.Filter filter) {
+            if (filter != null) {
+                mFilters.add(filter);
+            }
+            return this;
+        }
+
+        /**
+         * Set a region of the bitmap to be used exclusively when calculating the palette.
+         * <p>This only works when the original input is a {@link Bitmap}.</p>
+         *
+         * @param left The left side of the rectangle used for the region.
+         * @param top The top of the rectangle used for the region.
+         * @param right The right side of the rectangle used for the region.
+         * @param bottom The bottom of the rectangle used for the region.
+         */
+        @NonNull
+        public Palette.Builder setRegion(int left, int top, int right, int bottom) {
+            if (mBitmap != null) {
+                if (mRegion == null) mRegion = new Rect();
+                // Set the Rect to be initially the whole Bitmap
+                mRegion.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+                // Now just get the intersection with the region
+                if (!mRegion.intersect(left, top, right, bottom)) {
+                    throw new IllegalArgumentException("The given region must intersect with "
+                            + "the Bitmap's dimensions.");
+                }
+            }
+            return this;
+        }
+
+        /**
+         * Clear any previously region set via {@link #setRegion(int, int, int, int)}.
+         */
+        @NonNull
+        public Palette.Builder clearRegion() {
+            mRegion = null;
+            return this;
+        }
+
+        /**
+         * Add a target profile to be generated in the palette.
+         *
+         * <p>You can retrieve the result via {@link Palette#getSwatchForTarget(Target)}.</p>
+         */
+        @NonNull
+        public Palette.Builder addTarget(@NonNull final Target target) {
+            if (!mTargets.contains(target)) {
+                mTargets.add(target);
+            }
+            return this;
+        }
+
+        /**
+         * Clear all added targets. This includes any default targets added automatically by
+         * {@link Palette}.
+         */
+        @NonNull
+        public Palette.Builder clearTargets() {
+            if (mTargets != null) {
+                mTargets.clear();
+            }
+            return this;
+        }
+
+        /**
+         * Generate and return the {@link Palette} synchronously.
+         */
+        @NonNull
+        public Palette generate() {
+            final TimingLogger logger = LOG_TIMINGS
+                    ? new TimingLogger(LOG_TAG, "Generation")
+                    : null;
+
+            List<Palette.Swatch> swatches;
+
+            if (mBitmap != null) {
+                // We have a Bitmap so we need to use quantization to reduce the number of colors
+
+                // First we'll scale down the bitmap if needed
+                final Bitmap bitmap = scaleBitmapDown(mBitmap);
+
+                if (logger != null) {
+                    logger.addSplit("Processed Bitmap");
+                }
+
+                final Rect region = mRegion;
+                if (bitmap != mBitmap && region != null) {
+                    // If we have a scaled bitmap and a selected region, we need to scale down the
+                    // region to match the new scale
+                    final double scale = bitmap.getWidth() / (double) mBitmap.getWidth();
+                    region.left = (int) Math.floor(region.left * scale);
+                    region.top = (int) Math.floor(region.top * scale);
+                    region.right = Math.min((int) Math.ceil(region.right * scale),
+                            bitmap.getWidth());
+                    region.bottom = Math.min((int) Math.ceil(region.bottom * scale),
+                            bitmap.getHeight());
+                }
+
+                // Now generate a quantizer from the Bitmap
+                final ColorCutQuantizer quantizer = new ColorCutQuantizer(
+                        getPixelsFromBitmap(bitmap),
+                        mMaxColors,
+                        mFilters.isEmpty() ? null : mFilters.toArray(new Palette.Filter[mFilters.size()]));
+
+                // If created a new bitmap, recycle it
+                if (bitmap != mBitmap) {
+                    bitmap.recycle();
+                }
+
+                swatches = quantizer.getQuantizedColors();
+
+                if (logger != null) {
+                    logger.addSplit("Color quantization completed");
+                }
+            } else {
+                // Else we're using the provided swatches
+                swatches = mSwatches;
+            }
+
+            // Now create a Palette instance
+            final Palette p = new Palette(swatches, mTargets);
+            // And make it generate itself
+            p.generate();
+
+            if (logger != null) {
+                logger.addSplit("Created Palette");
+                logger.dumpToLog();
+            }
+
+            return p;
+        }
+
+        /**
+         * Generate the {@link Palette} asynchronously. The provided listener's
+         * {@link Palette.PaletteAsyncListener#onGenerated} method will be called with the palette when
+         * generated.
+         */
+        @NonNull
+        public AsyncTask<Bitmap, Void, Palette> generate(final Palette.PaletteAsyncListener listener) {
+            if (listener == null) {
+                throw new IllegalArgumentException("listener can not be null");
+            }
+
+            return new AsyncTask<Bitmap, Void, Palette>() {
+                @Override
+                protected Palette doInBackground(Bitmap... params) {
+                    try {
+                        return generate();
+                    } catch (Exception e) {
+                        Log.e(LOG_TAG, "Exception thrown during async generate", e);
+                        return null;
+                    }
+                }
+
+                @Override
+                protected void onPostExecute(Palette colorExtractor) {
+                    listener.onGenerated(colorExtractor);
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, mBitmap);
+        }
+
+        private int[] getPixelsFromBitmap(Bitmap bitmap) {
+            final int bitmapWidth = bitmap.getWidth();
+            final int bitmapHeight = bitmap.getHeight();
+            final int[] pixels = new int[bitmapWidth * bitmapHeight];
+            bitmap.getPixels(pixels, 0, bitmapWidth, 0, 0, bitmapWidth, bitmapHeight);
+
+            if (mRegion == null) {
+                // If we don't have a region, return all of the pixels
+                return pixels;
+            } else {
+                // If we do have a region, lets create a subset array containing only the region's
+                // pixels
+                final int regionWidth = mRegion.width();
+                final int regionHeight = mRegion.height();
+                // pixels contains all of the pixels, so we need to iterate through each row and
+                // copy the regions pixels into a new smaller array
+                final int[] subsetPixels = new int[regionWidth * regionHeight];
+                for (int row = 0; row < regionHeight; row++) {
+                    System.arraycopy(pixels, ((row + mRegion.top) * bitmapWidth) + mRegion.left,
+                            subsetPixels, row * regionWidth, regionWidth);
+                }
+                return subsetPixels;
+            }
+        }
+
+        /**
+         * Scale the bitmap down as needed.
+         */
+        private Bitmap scaleBitmapDown(final Bitmap bitmap) {
+            double scaleRatio = -1;
+
+            if (mResizeArea > 0) {
+                final int bitmapArea = bitmap.getWidth() * bitmap.getHeight();
+                if (bitmapArea > mResizeArea) {
+                    scaleRatio = Math.sqrt(mResizeArea / (double) bitmapArea);
+                }
+            } else if (mResizeMaxDimension > 0) {
+                final int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight());
+                if (maxDimension > mResizeMaxDimension) {
+                    scaleRatio = mResizeMaxDimension / (double) maxDimension;
+                }
+            }
+
+            if (scaleRatio <= 0) {
+                // Scaling has been disabled or not needed so just return the Bitmap
+                return bitmap;
+            }
+
+            return Bitmap.createScaledBitmap(bitmap,
+                    (int) Math.ceil(bitmap.getWidth() * scaleRatio),
+                    (int) Math.ceil(bitmap.getHeight() * scaleRatio),
+                    false);
+        }
+    }
+
+    /**
+     * A Filter provides a mechanism for exercising fine-grained control over which colors
+     * are valid within a resulting {@link Palette}.
+     */
+    public interface Filter {
+        /**
+         * Hook to allow clients to be able filter colors from resulting palette.
+         *
+         * @param rgb the color in RGB888.
+         * @param hsl HSL representation of the color.
+         *
+         * @return true if the color is allowed, false if not.
+         *
+         * @see Palette.Builder#addFilter(Palette.Filter)
+         */
+        boolean isAllowed(int rgb, float[] hsl);
+    }
+
+    /**
+     * The default filter.
+     */
+    static final Palette.Filter
+            DEFAULT_FILTER = new Palette.Filter() {
+        private static final float BLACK_MAX_LIGHTNESS = 0.05f;
+        private static final float WHITE_MIN_LIGHTNESS = 0.95f;
+
+        @Override
+        public boolean isAllowed(int rgb, float[] hsl) {
+            return !isWhite(hsl) && !isBlack(hsl) && !isNearRedILine(hsl);
+        }
+
+        /**
+         * @return true if the color represents a color which is close to black.
+         */
+        private boolean isBlack(float[] hslColor) {
+            return hslColor[2] <= BLACK_MAX_LIGHTNESS;
+        }
+
+        /**
+         * @return true if the color represents a color which is close to white.
+         */
+        private boolean isWhite(float[] hslColor) {
+            return hslColor[2] >= WHITE_MIN_LIGHTNESS;
+        }
+
+        /**
+         * @return true if the color lies close to the red side of the I line.
+         */
+        private boolean isNearRedILine(float[] hslColor) {
+            return hslColor[0] >= 10f && hslColor[0] <= 37f && hslColor[1] <= 0.82f;
+        }
+    };
+}
diff --git a/core/java/com/android/internal/graphics/palette/Target.java b/core/java/com/android/internal/graphics/palette/Target.java
new file mode 100644
index 0000000..0540d80
--- /dev/null
+++ b/core/java/com/android/internal/graphics/palette/Target.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.graphics.palette;
+
+/*
+ * 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.
+ */
+
+import android.annotation.FloatRange;
+
+/**
+ * Copied from: frameworks/support/v7/palette/src/main/java/android/support/v7/graphics/Target.java
+ *
+ * A class which allows custom selection of colors in a {@link Palette}'s generation. Instances
+ * can be created via the {@link android.support.v7.graphics.Target.Builder} class.
+ *
+ * <p>To use the target, use the {@link Palette.Builder#addTarget(Target)} API when building a
+ * Palette.</p>
+ */
+public final class Target {
+
+    private static final float TARGET_DARK_LUMA = 0.26f;
+    private static final float MAX_DARK_LUMA = 0.45f;
+
+    private static final float MIN_LIGHT_LUMA = 0.55f;
+    private static final float TARGET_LIGHT_LUMA = 0.74f;
+
+    private static final float MIN_NORMAL_LUMA = 0.3f;
+    private static final float TARGET_NORMAL_LUMA = 0.5f;
+    private static final float MAX_NORMAL_LUMA = 0.7f;
+
+    private static final float TARGET_MUTED_SATURATION = 0.3f;
+    private static final float MAX_MUTED_SATURATION = 0.4f;
+
+    private static final float TARGET_VIBRANT_SATURATION = 1f;
+    private static final float MIN_VIBRANT_SATURATION = 0.35f;
+
+    private static final float WEIGHT_SATURATION = 0.24f;
+    private static final float WEIGHT_LUMA = 0.52f;
+    private static final float WEIGHT_POPULATION = 0.24f;
+
+    static final int INDEX_MIN = 0;
+    static final int INDEX_TARGET = 1;
+    static final int INDEX_MAX = 2;
+
+    static final int INDEX_WEIGHT_SAT = 0;
+    static final int INDEX_WEIGHT_LUMA = 1;
+    static final int INDEX_WEIGHT_POP = 2;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is light in luminance.
+     */
+    public static final Target LIGHT_VIBRANT;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is neither light or dark.
+     */
+    public static final Target VIBRANT;
+
+    /**
+     * A target which has the characteristics of a vibrant color which is dark in luminance.
+     */
+    public static final Target DARK_VIBRANT;
+
+    /**
+     * A target which has the characteristics of a muted color which is light in luminance.
+     */
+    public static final Target LIGHT_MUTED;
+
+    /**
+     * A target which has the characteristics of a muted color which is neither light or dark.
+     */
+    public static final Target MUTED;
+
+    /**
+     * A target which has the characteristics of a muted color which is dark in luminance.
+     */
+    public static final Target DARK_MUTED;
+
+    static {
+        LIGHT_VIBRANT = new Target();
+        setDefaultLightLightnessValues(LIGHT_VIBRANT);
+        setDefaultVibrantSaturationValues(LIGHT_VIBRANT);
+
+        VIBRANT = new Target();
+        setDefaultNormalLightnessValues(VIBRANT);
+        setDefaultVibrantSaturationValues(VIBRANT);
+
+        DARK_VIBRANT = new Target();
+        setDefaultDarkLightnessValues(DARK_VIBRANT);
+        setDefaultVibrantSaturationValues(DARK_VIBRANT);
+
+        LIGHT_MUTED = new Target();
+        setDefaultLightLightnessValues(LIGHT_MUTED);
+        setDefaultMutedSaturationValues(LIGHT_MUTED);
+
+        MUTED = new Target();
+        setDefaultNormalLightnessValues(MUTED);
+        setDefaultMutedSaturationValues(MUTED);
+
+        DARK_MUTED = new Target();
+        setDefaultDarkLightnessValues(DARK_MUTED);
+        setDefaultMutedSaturationValues(DARK_MUTED);
+    }
+
+    final float[] mSaturationTargets = new float[3];
+    final float[] mLightnessTargets = new float[3];
+    final float[] mWeights = new float[3];
+    boolean mIsExclusive = true; // default to true
+
+    Target() {
+        setTargetDefaultValues(mSaturationTargets);
+        setTargetDefaultValues(mLightnessTargets);
+        setDefaultWeights();
+    }
+
+    Target(Target from) {
+        System.arraycopy(from.mSaturationTargets, 0, mSaturationTargets, 0,
+                mSaturationTargets.length);
+        System.arraycopy(from.mLightnessTargets, 0, mLightnessTargets, 0,
+                mLightnessTargets.length);
+        System.arraycopy(from.mWeights, 0, mWeights, 0, mWeights.length);
+    }
+
+    /**
+     * The minimum saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMinimumSaturation() {
+        return mSaturationTargets[INDEX_MIN];
+    }
+
+    /**
+     * The target saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getTargetSaturation() {
+        return mSaturationTargets[INDEX_TARGET];
+    }
+
+    /**
+     * The maximum saturation value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMaximumSaturation() {
+        return mSaturationTargets[INDEX_MAX];
+    }
+
+    /**
+     * The minimum lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMinimumLightness() {
+        return mLightnessTargets[INDEX_MIN];
+    }
+
+    /**
+     * The target lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getTargetLightness() {
+        return mLightnessTargets[INDEX_TARGET];
+    }
+
+    /**
+     * The maximum lightness value for this target.
+     */
+    @FloatRange(from = 0, to = 1)
+    public float getMaximumLightness() {
+        return mLightnessTargets[INDEX_MAX];
+    }
+
+    /**
+     * Returns the weight of importance that this target places on a color's saturation within
+     * the image.
+     *
+     * <p>The larger the weight, relative to the other weights, the more important that a color
+     * being close to the target value has on selection.</p>
+     *
+     * @see #getTargetSaturation()
+     */
+    public float getSaturationWeight() {
+        return mWeights[INDEX_WEIGHT_SAT];
+    }
+
+    /**
+     * Returns the weight of importance that this target places on a color's lightness within
+     * the image.
+     *
+     * <p>The larger the weight, relative to the other weights, the more important that a color
+     * being close to the target value has on selection.</p>
+     *
+     * @see #getTargetLightness()
+     */
+    public float getLightnessWeight() {
+        return mWeights[INDEX_WEIGHT_LUMA];
+    }
+
+    /**
+     * Returns the weight of importance that this target places on a color's population within
+     * the image.
+     *
+     * <p>The larger the weight, relative to the other weights, the more important that a
+     * color's population being close to the most populous has on selection.</p>
+     */
+    public float getPopulationWeight() {
+        return mWeights[INDEX_WEIGHT_POP];
+    }
+
+    /**
+     * Returns whether any color selected for this target is exclusive for this target only.
+     *
+     * <p>If false, then the color can be selected for other targets.</p>
+     */
+    public boolean isExclusive() {
+        return mIsExclusive;
+    }
+
+    private static void setTargetDefaultValues(final float[] values) {
+        values[INDEX_MIN] = 0f;
+        values[INDEX_TARGET] = 0.5f;
+        values[INDEX_MAX] = 1f;
+    }
+
+    private void setDefaultWeights() {
+        mWeights[INDEX_WEIGHT_SAT] = WEIGHT_SATURATION;
+        mWeights[INDEX_WEIGHT_LUMA] = WEIGHT_LUMA;
+        mWeights[INDEX_WEIGHT_POP] = WEIGHT_POPULATION;
+    }
+
+    void normalizeWeights() {
+        float sum = 0;
+        for (int i = 0, z = mWeights.length; i < z; i++) {
+            float weight = mWeights[i];
+            if (weight > 0) {
+                sum += weight;
+            }
+        }
+        if (sum != 0) {
+            for (int i = 0, z = mWeights.length; i < z; i++) {
+                if (mWeights[i] > 0) {
+                    mWeights[i] /= sum;
+                }
+            }
+        }
+    }
+
+    private static void setDefaultDarkLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_DARK_LUMA;
+        target.mLightnessTargets[INDEX_MAX] = MAX_DARK_LUMA;
+    }
+
+    private static void setDefaultNormalLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_MIN] = MIN_NORMAL_LUMA;
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_NORMAL_LUMA;
+        target.mLightnessTargets[INDEX_MAX] = MAX_NORMAL_LUMA;
+    }
+
+    private static void setDefaultLightLightnessValues(Target target) {
+        target.mLightnessTargets[INDEX_MIN] = MIN_LIGHT_LUMA;
+        target.mLightnessTargets[INDEX_TARGET] = TARGET_LIGHT_LUMA;
+    }
+
+    private static void setDefaultVibrantSaturationValues(Target target) {
+        target.mSaturationTargets[INDEX_MIN] = MIN_VIBRANT_SATURATION;
+        target.mSaturationTargets[INDEX_TARGET] = TARGET_VIBRANT_SATURATION;
+    }
+
+    private static void setDefaultMutedSaturationValues(Target target) {
+        target.mSaturationTargets[INDEX_TARGET] = TARGET_MUTED_SATURATION;
+        target.mSaturationTargets[INDEX_MAX] = MAX_MUTED_SATURATION;
+    }
+
+    /**
+     * Builder class for generating custom {@link Target} instances.
+     */
+    public final static class Builder {
+        private final Target mTarget;
+
+        /**
+         * Create a new {@link Target} builder from scratch.
+         */
+        public Builder() {
+            mTarget = new Target();
+        }
+
+        /**
+         * Create a new builder based on an existing {@link Target}.
+         */
+        public Builder(Target target) {
+            mTarget = new Target(target);
+        }
+
+        /**
+         * Set the minimum saturation value for this target.
+         */
+        public Target.Builder setMinimumSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_MIN] = value;
+            return this;
+        }
+
+        /**
+         * Set the target/ideal saturation value for this target.
+         */
+        public Target.Builder setTargetSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_TARGET] = value;
+            return this;
+        }
+
+        /**
+         * Set the maximum saturation value for this target.
+         */
+        public Target.Builder setMaximumSaturation(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mSaturationTargets[INDEX_MAX] = value;
+            return this;
+        }
+
+        /**
+         * Set the minimum lightness value for this target.
+         */
+        public Target.Builder setMinimumLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_MIN] = value;
+            return this;
+        }
+
+        /**
+         * Set the target/ideal lightness value for this target.
+         */
+        public Target.Builder setTargetLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_TARGET] = value;
+            return this;
+        }
+
+        /**
+         * Set the maximum lightness value for this target.
+         */
+        public Target.Builder setMaximumLightness(@FloatRange(from = 0, to = 1) float value) {
+            mTarget.mLightnessTargets[INDEX_MAX] = value;
+            return this;
+        }
+
+        /**
+         * Set the weight of importance that this target will place on saturation values.
+         *
+         * <p>The larger the weight, relative to the other weights, the more important that a color
+         * being close to the target value has on selection.</p>
+         *
+         * <p>A weight of 0 means that it has no weight, and thus has no
+         * bearing on the selection.</p>
+         *
+         * @see #setTargetSaturation(float)
+         */
+        public Target.Builder setSaturationWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_SAT] = weight;
+            return this;
+        }
+
+        /**
+         * Set the weight of importance that this target will place on lightness values.
+         *
+         * <p>The larger the weight, relative to the other weights, the more important that a color
+         * being close to the target value has on selection.</p>
+         *
+         * <p>A weight of 0 means that it has no weight, and thus has no
+         * bearing on the selection.</p>
+         *
+         * @see #setTargetLightness(float)
+         */
+        public Target.Builder setLightnessWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_LUMA] = weight;
+            return this;
+        }
+
+        /**
+         * Set the weight of importance that this target will place on a color's population within
+         * the image.
+         *
+         * <p>The larger the weight, relative to the other weights, the more important that a
+         * color's population being close to the most populous has on selection.</p>
+         *
+         * <p>A weight of 0 means that it has no weight, and thus has no
+         * bearing on the selection.</p>
+         */
+        public Target.Builder setPopulationWeight(@FloatRange(from = 0) float weight) {
+            mTarget.mWeights[INDEX_WEIGHT_POP] = weight;
+            return this;
+        }
+
+        /**
+         * Set whether any color selected for this target is exclusive to this target only.
+         * Defaults to true.
+         *
+         * @param exclusive true if any the color is exclusive to this target, or false is the
+         *                  color can be selected for other targets.
+         */
+        public Target.Builder setExclusive(boolean exclusive) {
+            mTarget.mIsExclusive = exclusive;
+            return this;
+        }
+
+        /**
+         * Builds and returns the resulting {@link Target}.
+         */
+        public Target build() {
+            return mTarget;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
new file mode 100644
index 0000000..4ce6f60
--- /dev/null
+++ b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.notification;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+public final class NotificationAccessConfirmationActivityContract {
+    private static final ComponentName COMPONENT_NAME = new ComponentName(
+            "com.android.settings",
+            "com.android.settings.notification.NotificationAccessConfirmationActivity");
+    public static final String EXTRA_USER_ID = "user_id";
+    public static final String EXTRA_COMPONENT_NAME = "component_name";
+    public static final String EXTRA_PACKAGE_TITLE = "package_title";
+
+    public static Intent launcherIntent(int userId, ComponentName component, String packageTitle) {
+        return new Intent()
+                .setComponent(COMPONENT_NAME)
+                .putExtra(EXTRA_USER_ID, userId)
+                .putExtra(EXTRA_COMPONENT_NAME, component)
+                .putExtra(EXTRA_PACKAGE_TITLE, packageTitle);
+    }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fe38605..7fbfb8b 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -114,7 +114,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 153 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 154 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -5463,7 +5463,6 @@
 
         LongSamplingCounter mUserCpuTime;
         LongSamplingCounter mSystemCpuTime;
-        LongSamplingCounter mCpuPower;
         LongSamplingCounter[][] mCpuClusterSpeed;
 
         /**
@@ -5474,7 +5473,7 @@
         /**
          * The statistics we have collected for this uid's syncs.
          */
-        final OverflowArrayMap<StopwatchTimer> mSyncStats;
+        final OverflowArrayMap<DualTimer> mSyncStats;
 
         /**
          * The statistics we have collected for this uid's jobs.
@@ -5511,17 +5510,16 @@
 
             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
-            mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
 
             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
                 @Override public Wakelock instantiateObject() {
                     return new Wakelock(mBsi, Uid.this);
                 }
             };
-            mSyncStats = mBsi.new OverflowArrayMap<StopwatchTimer>(uid) {
-                @Override public StopwatchTimer instantiateObject() {
-                    return new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null,
-                            mBsi.mOnBatteryTimeBase);
+            mSyncStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
+                @Override public DualTimer instantiateObject() {
+                    return new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
+                            mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
                 }
             };
             mJobStats = mBsi.new OverflowArrayMap<DualTimer>(uid) {
@@ -6162,11 +6160,6 @@
         }
 
         @Override
-        public long getCpuPowerMaUs(int which) {
-            return mCpuPower.getCountLocked(which);
-        }
-
-        @Override
         public long getTimeAtCpuSpeed(int cluster, int step, int which) {
             if (mCpuClusterSpeed != null) {
                 if (cluster >= 0 && cluster < mCpuClusterSpeed.length) {
@@ -6311,7 +6304,6 @@
 
             mUserCpuTime.reset(false);
             mSystemCpuTime.reset(false);
-            mCpuPower.reset(false);
 
             if (mCpuClusterSpeed != null) {
                 for (LongSamplingCounter[] speeds : mCpuClusterSpeed) {
@@ -6338,9 +6330,9 @@
                 }
             }
             mWakelockStats.cleanup();
-            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
+            final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
             for (int is=syncStats.size()-1; is>=0; is--) {
-                StopwatchTimer timer = syncStats.valueAt(is);
+                DualTimer timer = syncStats.valueAt(is);
                 if (timer.reset(false)) {
                     syncStats.removeAt(is);
                     timer.detach();
@@ -6477,7 +6469,6 @@
 
                 mUserCpuTime.detach();
                 mSystemCpuTime.detach();
-                mCpuPower.detach();
 
                 if (mCpuClusterSpeed != null) {
                     for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
@@ -6510,12 +6501,12 @@
                 wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
             }
 
-            final ArrayMap<String, StopwatchTimer> syncStats = mSyncStats.getMap();
+            final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap();
             int NS = syncStats.size();
             out.writeInt(NS);
             for (int is=0; is<NS; is++) {
                 out.writeString(syncStats.keyAt(is));
-                StopwatchTimer timer = syncStats.valueAt(is);
+                DualTimer timer = syncStats.valueAt(is);
                 Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
             }
 
@@ -6677,7 +6668,6 @@
 
             mUserCpuTime.writeToParcel(out);
             mSystemCpuTime.writeToParcel(out);
-            mCpuPower.writeToParcel(out);
 
             if (mCpuClusterSpeed != null) {
                 out.writeInt(1);
@@ -6734,8 +6724,8 @@
             for (int j = 0; j < numSyncs; j++) {
                 String syncName = in.readString();
                 if (in.readInt() != 0) {
-                    mSyncStats.add(syncName,
-                            new StopwatchTimer(mBsi.mClocks, Uid.this, SYNC, null, timeBase, in));
+                    mSyncStats.add(syncName, new DualTimer(mBsi.mClocks, Uid.this, SYNC, null,
+                            mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in));
                 }
             }
 
@@ -6913,7 +6903,6 @@
 
             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
-            mCpuPower = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
 
             if (in.readInt() != 0) {
                 int numCpuClusters = in.readInt();
@@ -8002,7 +7991,7 @@
         }
 
         public void readSyncSummaryFromParcelLocked(String name, Parcel in) {
-            StopwatchTimer timer = mSyncStats.instantiateObject();
+            DualTimer timer = mSyncStats.instantiateObject();
             timer.readSummaryFromParcelLocked(in);
             mSyncStats.add(name, timer);
         }
@@ -8055,14 +8044,14 @@
         }
 
         public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
-            StopwatchTimer t = mSyncStats.startObject(name);
+            DualTimer t = mSyncStats.startObject(name);
             if (t != null) {
                 t.startRunningLocked(elapsedRealtimeMs);
             }
         }
 
         public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
-            StopwatchTimer t = mSyncStats.stopObject(name);
+            DualTimer t = mSyncStats.stopObject(name);
             if (t != null) {
                 t.stopRunningLocked(elapsedRealtimeMs);
             }
@@ -9705,8 +9694,7 @@
         mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
                 new KernelUidCpuTimeReader.Callback() {
                     @Override
-                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs,
-                                             long powerMaUs) {
+                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
                         final Uid u = getUidStatsLocked(mapUid(uid));
 
                         // Accumulate the total system and user time.
@@ -9720,7 +9708,7 @@
                             TimeUtils.formatDuration(userTimeUs / 1000, sb);
                             sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeUs / 1000, sb);
-                            sb.append(" p=").append(powerMaUs / 1000).append("mAms\n");
+                            sb.append("\n");
                         }
 
                         if (numWakelocksF > 0) {
@@ -9736,13 +9724,11 @@
                             TimeUtils.formatDuration(userTimeUs / 1000, sb);
                             sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeUs / 1000, sb);
-                            sb.append(" p=").append(powerMaUs / 1000).append("mAms");
                             Slog.d(TAG, sb.toString());
                         }
 
                         u.mUserCpuTime.addCountLocked(userTimeUs);
                         u.mSystemCpuTime.addCountLocked(systemTimeUs);
-                        u.mCpuPower.addCountLocked(powerMaUs);
 
                         // Add the cpu speeds to this UID. These are used as a ratio
                         // for computing the power this UID used.
@@ -11036,7 +11022,6 @@
 
             u.mUserCpuTime.readSummaryFromParcelLocked(in);
             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
-            u.mCpuPower.readSummaryFromParcelLocked(in);
 
             if (in.readInt() != 0) {
                 final int numClusters = in.readInt();
@@ -11432,7 +11417,6 @@
 
             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
-            u.mCpuPower.writeSummaryFromParcelLocked(out);
 
             if (u.mCpuClusterSpeed != null) {
                 out.writeInt(1);
@@ -11503,7 +11487,7 @@
                 }
             }
 
-            final ArrayMap<String, StopwatchTimer> syncStats = u.mSyncStats.getMap();
+            final ArrayMap<String, DualTimer> syncStats = u.mSyncStats.getMap();
             int NS = syncStats.size();
             out.writeInt(NS);
             for (int is=0; is<NS; is++) {
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index e8919ed..181e1ac 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -50,14 +50,12 @@
          * @param uid UID of the app
          * @param userTimeUs time spent executing in user space in microseconds
          * @param systemTimeUs time spent executing in kernel space in microseconds
-         * @param powerMaUs power consumed executing, in milli-ampere microseconds
          */
-        void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs, long powerMaUs);
+        void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs);
     }
 
     private SparseLongArray mLastUserTimeUs = new SparseLongArray();
     private SparseLongArray mLastSystemTimeUs = new SparseLongArray();
-    private SparseLongArray mLastPowerMaUs = new SparseLongArray();
     private long mLastTimeReadUs = 0;
 
     /**
@@ -77,26 +75,18 @@
                 final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10);
                 final long userTimeUs = Long.parseLong(splitter.next(), 10);
                 final long systemTimeUs = Long.parseLong(splitter.next(), 10);
-                final long powerMaUs;
-                if (splitter.hasNext()) {
-                    powerMaUs = Long.parseLong(splitter.next(), 10) / 1000;
-                } else {
-                    powerMaUs = 0;
-                }
 
                 // Only report if there is a callback and if this is not the first read.
                 if (callback != null && mLastTimeReadUs != 0) {
                     long userTimeDeltaUs = userTimeUs;
                     long systemTimeDeltaUs = systemTimeUs;
-                    long powerDeltaMaUs = powerMaUs;
                     int index = mLastUserTimeUs.indexOfKey(uid);
                     if (index >= 0) {
                         userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
                         systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index);
-                        powerDeltaMaUs -= mLastPowerMaUs.valueAt(index);
 
                         final long timeDiffUs = nowUs - mLastTimeReadUs;
-                        if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || powerDeltaMaUs < 0) {
+                        if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0) {
                             StringBuilder sb = new StringBuilder("Malformed cpu data for UID=");
                             sb.append(uid).append("!\n");
                             sb.append("Time between reads: ");
@@ -106,36 +96,28 @@
                             TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb);
                             sb.append(" s=");
                             TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb);
-                            sb.append(" p=").append(mLastPowerMaUs.valueAt(index) / 1000);
-                            sb.append("mAms\n");
 
-                            sb.append("Current times: u=");
+                            sb.append("\nCurrent times: u=");
                             TimeUtils.formatDuration(userTimeUs / 1000, sb);
                             sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeUs / 1000, sb);
-                            sb.append(" p=").append(powerMaUs / 1000);
-                            sb.append("mAms\n");
-                            sb.append("Delta: u=");
+                            sb.append("\nDelta: u=");
                             TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb);
                             sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
-                            sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms");
                             Slog.e(TAG, sb.toString());
 
                             userTimeDeltaUs = 0;
                             systemTimeDeltaUs = 0;
-                            powerDeltaMaUs = 0;
                         }
                     }
 
-                    if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0 || powerDeltaMaUs != 0) {
-                        callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs,
-                                powerDeltaMaUs);
+                    if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0) {
+                        callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs);
                     }
                 }
                 mLastUserTimeUs.put(uid, userTimeUs);
                 mLastSystemTimeUs.put(uid, systemTimeUs);
-                mLastPowerMaUs.put(uid, powerMaUs);
             }
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read uid_cputime: " + e.getMessage());
@@ -152,7 +134,6 @@
         if (index >= 0) {
             mLastUserTimeUs.removeAt(index);
             mLastSystemTimeUs.removeAt(index);
-            mLastPowerMaUs.removeAt(index);
         }
 
         try (FileWriter writer = new FileWriter(sRemoveUidProcFile)) {
diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java
index 1d26df0..89a4e17 100644
--- a/core/java/com/android/internal/os/RoSystemProperties.java
+++ b/core/java/com/android/internal/os/RoSystemProperties.java
@@ -33,6 +33,8 @@
     // ------ ro.config.* -------- //
     public static final boolean CONFIG_LOW_RAM =
             SystemProperties.getBoolean("ro.config.low_ram", false);
+    public static final boolean CONFIG_SMALL_BATTERY =
+            SystemProperties.getBoolean("ro.config.small_battery", false);
 
     // ------ ro.fw.* ------------ //
     public static final boolean FW_SYSTEM_USER_SPLIT =
diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java
index cc3f58c..e28079f 100644
--- a/core/java/com/android/internal/os/WebViewZygoteInit.java
+++ b/core/java/com/android/internal/os/WebViewZygoteInit.java
@@ -70,6 +70,7 @@
         @Override
         protected boolean handlePreloadPackage(String packagePath, String libsPath,
                                                String cacheKey) {
+            Log.i(TAG, "Beginning package preload");
             // Ask ApplicationLoaders to create and cache a classloader for the WebView APK so that
             // our children will reuse the same classloader instead of creating their own.
             // This enables us to preload Java and native code in the webview zygote process and
@@ -97,6 +98,7 @@
                      IllegalAccessException | InvocationTargetException e) {
                 Log.e(TAG, "Exception while preloading package", e);
             }
+            Log.i(TAG, "Package preload done");
             return false;
         }
     }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 44fa99d..142effb 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -186,8 +186,8 @@
 
     private static void preloadOpenGL() {
         String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
-        if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) ||
-                driverPackageName == null || driverPackageName.isEmpty()) {
+        if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
+                (driverPackageName == null || driverPackageName.isEmpty())) {
             EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
         }
     }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index c4540f5..80b6b08 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -82,6 +82,7 @@
 
 import static android.app.ActivityManager.StackId;
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -1688,7 +1689,7 @@
                     }
                 };
             } else {
-                ViewStub stub = (ViewStub) findViewById(R.id.action_mode_bar_stub);
+                ViewStub stub = findViewById(R.id.action_mode_bar_stub);
                 if (stub != null) {
                     mPrimaryActionModeView = (ActionBarContextView) stub.inflate();
                     mPrimaryActionModePopup = null;
@@ -2182,19 +2183,22 @@
         final boolean wasAdjustedForStack = mElevationAdjustedForStack;
         // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null)
         // since the shadow is bound to the content size and not the target size.
-        if (StackId.hasWindowShadow(mStackId) && !isResizing()) {
+        if ((mStackId == FREEFORM_WORKSPACE_STACK_ID) && !isResizing()) {
             elevation = hasWindowFocus() ?
                     DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
             // Add a maximum shadow height value to the top level view.
             // Note that pinned stack doesn't have focus
             // so maximum shadow height adjustment isn't needed.
             // TODO(skuhne): Remove this if clause once b/22668382 got fixed.
-            if (!mAllowUpdateElevation && mStackId != PINNED_STACK_ID) {
+            if (!mAllowUpdateElevation) {
                 elevation = DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
             }
             // Convert the DP elevation into physical pixels.
             elevation = dipToPx(elevation);
             mElevationAdjustedForStack = true;
+        } else if (mStackId == PINNED_STACK_ID) {
+            elevation = dipToPx(DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP);
+            mElevationAdjustedForStack = true;
         } else {
             mElevationAdjustedForStack = false;
         }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 7b966de..243916b 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -1593,7 +1593,7 @@
         if (featureId == FEATURE_PROGRESS || featureId == FEATURE_INDETERMINATE_PROGRESS) {
             updateProgressBars(value);
         } else if (featureId == FEATURE_CUSTOM_TITLE) {
-            FrameLayout titleContainer = (FrameLayout) findViewById(R.id.title_container);
+            FrameLayout titleContainer = findViewById(R.id.title_container);
             if (titleContainer != null) {
                 mLayoutInflater.inflate(value, titleContainer);
             }
@@ -2690,7 +2690,7 @@
                     invalidatePanelMenu(FEATURE_ACTION_BAR);
                 }
             } else {
-                mTitleView = (TextView) findViewById(R.id.title);
+                mTitleView = findViewById(R.id.title);
                 if (mTitleView != null) {
                     if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                         final View titleContainer = findViewById(R.id.title_container);
@@ -2967,7 +2967,7 @@
         if (mContentParent == null && shouldInstallDecor) {
             installDecor();
         }
-        mCircularProgressBar = (ProgressBar) findViewById(R.id.progress_circular);
+        mCircularProgressBar = findViewById(R.id.progress_circular);
         if (mCircularProgressBar != null) {
             mCircularProgressBar.setVisibility(View.INVISIBLE);
         }
@@ -2981,7 +2981,7 @@
         if (mContentParent == null && shouldInstallDecor) {
             installDecor();
         }
-        mHorizontalProgressBar = (ProgressBar) findViewById(R.id.progress_horizontal);
+        mHorizontalProgressBar = findViewById(R.id.progress_horizontal);
         if (mHorizontalProgressBar != null) {
             mHorizontalProgressBar.setVisibility(View.INVISIBLE);
         }
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
index a208ccb..e349f3d 100644
--- a/core/java/com/android/internal/util/BitUtils.java
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -55,4 +55,25 @@
                 && maskedEquals(a.getMostSignificantBits(), b.getMostSignificantBits(),
                     mask.getMostSignificantBits());
     }
+
+    public static int[] unpackBits(long val) {
+        int size = Long.bitCount(val);
+        int[] result = new int[size];
+        int index = 0;
+        int bitPos = 0;
+        while (val > 0) {
+            if ((val & 1) == 1) result[index++] = bitPos;
+            val = val >> 1;
+            bitPos++;
+        }
+        return result;
+    }
+
+    public static long packBits(int[] bits) {
+        long packed = 0;
+        for (int b : bits) {
+            packed |= (1 << b);
+        }
+        return packed;
+    }
 }
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index 287f68c..96b443d 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.util;
 
+import static com.android.internal.util.ArrayUtils.isEmpty;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
@@ -64,7 +66,7 @@
      */
     public static @NonNull <I, O> List<O> map(@Nullable List<I> cur,
             Function<? super I, ? extends O> f) {
-        if (cur == null || cur.isEmpty()) return Collections.emptyList();
+        if (isEmpty(cur)) return Collections.emptyList();
         final ArrayList<O> result = new ArrayList<>();
         for (int i = 0; i < cur.size(); i++) {
             result.add(f.apply(cur.get(i)));
@@ -73,6 +75,30 @@
     }
 
     /**
+     * {@link #map(List, Function)} + {@link #filter(List, java.util.function.Predicate)}
+     *
+     * Calling this is equivalent (but more memory efficient) to:
+     *
+     * {@code
+     *      filter(
+     *          map(cur, f),
+     *          i -> { i != null })
+     * }
+     */
+    public static @NonNull <I, O> List<O> mapNotNull(@Nullable List<I> cur,
+            Function<? super I, ? extends O> f) {
+        if (isEmpty(cur)) return Collections.emptyList();
+        final ArrayList<O> result = new ArrayList<>();
+        for (int i = 0; i < cur.size(); i++) {
+            O transformed = f.apply(cur.get(i));
+            if (transformed != null) {
+                result.add(transformed);
+            }
+        }
+        return result;
+    }
+
+    /**
      * Returns the given list, or an immutable empty list if the provided list is null
      *
      * This can be used to guaranty null-safety without paying the price of extra allocations
@@ -94,7 +120,7 @@
      * Returns the elements of the given list that are of type {@code c}
      */
     public static @NonNull <T> List<T> filter(@Nullable List<?> list, Class<T> c) {
-        if (ArrayUtils.isEmpty(list)) return Collections.emptyList();
+        if (isEmpty(list)) return Collections.emptyList();
         ArrayList<T> result = null;
         for (int i = 0; i < list.size(); i++) {
             final Object item = list.get(i);
@@ -120,11 +146,42 @@
      */
     public static @Nullable <T> T find(@Nullable List<T> items,
             java.util.function.Predicate<T> predicate) {
-        if (ArrayUtils.isEmpty(items)) return null;
+        if (isEmpty(items)) return null;
         for (int i = 0; i < items.size(); i++) {
             final T item = items.get(i);
             if (predicate.test(item)) return item;
         }
         return null;
     }
+
+    /**
+     * Similar to {@link List#add}, but with support for list values of {@code null} and
+     * {@link Collections#emptyList}
+     */
+    public static @NonNull <T> List<T> add(@Nullable List<T> cur, T val) {
+        if (cur == null || cur == Collections.emptyList()) {
+            cur = new ArrayList<>();
+        }
+        cur.add(val);
+        return cur;
+    }
+
+    /**
+     * Similar to {@link List#remove}, but with support for list values of {@code null} and
+     * {@link Collections#emptyList}
+     */
+    public static @NonNull <T> List<T> remove(@Nullable List<T> cur, T val) {
+        if (isEmpty(cur)) {
+            return emptyIfNull(cur);
+        }
+        cur.remove(val);
+        return cur;
+    }
+
+    /**
+     * @return a list that will not be affected by mutations to the given original list.
+     */
+    public static @NonNull <T> List<T> copyOf(@Nullable List<T> cur) {
+        return isEmpty(cur) ? Collections.emptyList() : new ArrayList<>(cur);
+    }
 }
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 4659d3c..ce89501 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -121,12 +121,15 @@
         final String[] pkgs = context.getPackageManager().getPackagesForUid(uid);
         if (pkgs != null) {
             for (String pkg : pkgs) {
-                if (appOps.checkOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid,
-                        pkg) == AppOpsManager.MODE_ALLOWED) {
-                    appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg);
-                    if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
-                                + "android:get_usage_stats access");
-                    return true;
+                switch (appOps.checkOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, uid, pkg)) {
+                    case AppOpsManager.MODE_ALLOWED:
+                        if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
+                                + "android:get_usage_stats allowed");
+                        return true;
+                    case AppOpsManager.MODE_DEFAULT:
+                        if (DEBUG) Slog.v(TAG, "Found package " + pkg + " with "
+                                + "android:get_usage_stats default");
+                        return true;
                 }
             }
         }
diff --git a/core/java/com/android/internal/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java
new file mode 100644
index 0000000..9aeb041
--- /dev/null
+++ b/core/java/com/android/internal/util/FunctionalUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.util.function.Supplier;
+
+/**
+ * Utilities specific to functional programming
+ */
+public class FunctionalUtils {
+    private FunctionalUtils() {}
+
+    /**
+     * An equivalent of {@link Runnable} that allows throwing checked exceptions
+     *
+     * This can be used to specify a lambda argument without forcing all the checked exceptions
+     * to be handled within it
+     */
+    @FunctionalInterface
+    public interface ThrowingRunnable {
+        void run() throws Exception;
+    }
+
+    /**
+     * An equivalent of {@link Supplier} that allows throwing checked exceptions
+     *
+     * This can be used to specify a lambda argument without forcing all the checked exceptions
+     * to be handled within it
+     */
+    @FunctionalInterface
+    public interface ThrowingSupplier<T> {
+        T get() throws Exception;
+    }
+}
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index 4e6857a..e5d5716 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -49,6 +49,23 @@
     }
 
     /**
+     * Ensures that an expression checking an argument is true.
+     *
+     * @param expression the expression to check
+     * @param messageTemplate a printf-style message template to use if the check fails; will
+     *     be converted to a string using {@link String#format(String, Object...)}
+     * @param messageArgs arguments for {@code messageTemplate}
+     * @throws IllegalArgumentException if {@code expression} is false
+     */
+    public static void checkArgument(boolean expression,
+            final String messageTemplate,
+            final Object... messageArgs) {
+        if (!expression) {
+            throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
+        }
+    }
+
+    /**
      * Ensures that an string reference passed as a parameter to the calling
      * method is not empty.
      *
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 919cf99..83a2838 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -89,14 +89,14 @@
         
         setBackgroundDrawable(mBackground);
         
-        mTitleView = (TextView) findViewById(com.android.internal.R.id.title);
+        mTitleView = findViewById(com.android.internal.R.id.title);
         if (mTextAppearance != -1) {
             mTitleView.setTextAppearance(mTextAppearanceContext,
                                          mTextAppearance);
         }
         
-        mShortcutView = (TextView) findViewById(com.android.internal.R.id.shortcut);
-        mSubMenuArrowView = (ImageView) findViewById(com.android.internal.R.id.submenuarrow);
+        mShortcutView = findViewById(com.android.internal.R.id.shortcut);
+        mSubMenuArrowView = findViewById(com.android.internal.R.id.submenuarrow);
         if (mSubMenuArrowView != null) {
             mSubMenuArrowView.setImageDrawable(mSubMenuArrow);
         }
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index c3a7460..65cd4fa2 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -569,10 +569,10 @@
     void pullChildren() {
         if (mContent == null) {
             mContent = findViewById(com.android.internal.R.id.content);
-            mActionBarTop = (ActionBarContainer) findViewById(
+            mActionBarTop = findViewById(
                     com.android.internal.R.id.action_bar_container);
             mDecorToolbar = getDecorToolbar(findViewById(com.android.internal.R.id.action_bar));
-            mActionBarBottom = (ActionBarContainer) findViewById(
+            mActionBarBottom = findViewById(
                     com.android.internal.R.id.split_action_bar);
         }
     }
@@ -707,7 +707,7 @@
                 mDecorToolbar.setSplitToolbar(splitActionBar);
                 mDecorToolbar.setSplitWhenNarrow(splitWhenNarrow);
 
-                final ActionBarContextView cab = (ActionBarContextView) findViewById(
+                final ActionBarContextView cab = findViewById(
                         com.android.internal.R.id.action_context_bar);
                 cab.setSplitView(mActionBarBottom);
                 cab.setSplitToolbar(splitActionBar);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 818cc2c..8c71cf7 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -233,6 +233,7 @@
 
     private void doShow() {
         List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu);
+        tidy(menuItems);
         if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
             mPopup.dismiss();
             mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
@@ -274,6 +275,36 @@
         return menuItems;
     }
 
+    /**
+     * Update the list of menu items to conform to certain requirements.
+     */
+    private void tidy(List<MenuItem> menuItems) {
+        int assistItemIndex = -1;
+        Drawable assistItemDrawable = null;
+
+        final int size = menuItems.size();
+        for (int i = 0; i < size; i++) {
+            final MenuItem menuItem = menuItems.get(i);
+
+            if (menuItem.getItemId() == android.R.id.textAssist) {
+                assistItemIndex = i;
+                assistItemDrawable = menuItem.getIcon();
+            }
+
+            // Remove icons for all menu items with text.
+            if (!TextUtils.isEmpty(menuItem.getTitle())) {
+                menuItem.setIcon(null);
+            }
+        }
+        if (assistItemIndex > -1) {
+            final MenuItem assistMenuItem = menuItems.remove(assistItemIndex);
+            // Ensure the assist menu item preserves its icon.
+            assistMenuItem.setIcon(assistItemDrawable);
+            // Ensure the assist menu item is always the first item.
+            menuItems.add(0, assistMenuItem);
+        }
+    }
+
     private List<Object> getShowingMenuItemsReferences(List<MenuItem> menuItems) {
         List<Object> references = new ArrayList<Object>();
         for (MenuItem menuItem : menuItems) {
diff --git a/core/java/com/android/internal/widget/MediaNotificationView.java b/core/java/com/android/internal/widget/MediaNotificationView.java
index f63afad..afb2a5e 100644
--- a/core/java/com/android/internal/widget/MediaNotificationView.java
+++ b/core/java/com/android/internal/widget/MediaNotificationView.java
@@ -152,7 +152,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mRightIcon = (ImageView) findViewById(com.android.internal.R.id.right_icon);
+        mRightIcon = findViewById(com.android.internal.R.id.right_icon);
         mActions = findViewById(com.android.internal.R.id.media_actions);
         mHeader = findViewById(com.android.internal.R.id.notification_header);
         mMainColumn = findViewById(com.android.internal.R.id.notification_main_column);
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 4a9a2c5..c1f443f 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -35,6 +35,7 @@
 import android.util.Slog;
 import android.util.Xml;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
@@ -89,6 +90,11 @@
 
     // example: fs_stat,/dev/block/platform/soc/by-name/userdata,0x5
     private static final String FS_STAT_PATTERN = "fs_stat,[^,]*/([^/,]+),(0x[0-9a-fA-F]+)";
+    private static final int FS_STAT_FS_FIXED = 0x400; // should match with fs_mgr.cpp:FsStatFlags
+    private static final String FSCK_PASS_PATTERN = "Pass ([1-9]E?):";
+    private static final String FSCK_TREE_OPTIMIZATION_PATTERN =
+            "Inode [0-9]+ extent tree.*could be shorter";
+    private static final String FSCK_FS_MODIFIED = "FILE SYSTEM WAS MODIFIED";
     // ro.boottime.init.mount_all. + postfix for mount_all duration
     private static final String[] MOUNT_DURATION_PROPS_POSTFIX =
             new String[] { "early", "default", "late" };
@@ -334,17 +340,22 @@
 
         String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
         Pattern pattern = Pattern.compile(FS_STAT_PATTERN);
-        for (String line : log.split("\n")) { // should check all lines
-            if (line.contains("FILE SYSTEM WAS MODIFIED")) {
+        String lines[] = log.split("\n");
+        int lineNumber = 0;
+        int lastFsStatLineNumber = 0;
+        for (String line : lines) { // should check all lines
+            if (line.contains(FSCK_FS_MODIFIED)) {
                 uploadNeeded = true;
             } else if (line.contains("fs_stat")){
                 Matcher matcher = pattern.matcher(line);
                 if (matcher.find()) {
-                    handleFsckFsStat(matcher);
+                    handleFsckFsStat(matcher, lines, lastFsStatLineNumber, lineNumber);
+                    lastFsStatLineNumber = lineNumber;
                 } else {
                     Slog.w(TAG, "cannot parse fs_stat:" + line);
                 }
             }
+            lineNumber++;
         }
 
         if (uploadEnabled && uploadNeeded ) {
@@ -403,7 +414,88 @@
         }
     }
 
-    private static void handleFsckFsStat(Matcher match) {
+    /**
+     * Fix fs_stat from e2fsck.
+     * For now, only handle the case of quota warning caused by tree optimization. Clear fs fix
+     * flag (=0x400) caused by that.
+     *
+     * @param partition partition name
+     * @param statOrg original stat reported from e2fsck log
+     * @param lines e2fsck logs broken down into lines
+     * @param startLineNumber start line to parse
+     * @param endLineNumber end line. exclusive.
+     * @return updated fs_stat. For tree optimization, will clear bit 0x400.
+     */
+    @VisibleForTesting
+    public static int fixFsckFsStat(String partition, int statOrg, String[] lines,
+            int startLineNumber, int endLineNumber) {
+        int stat = statOrg;
+        if ((stat & FS_STAT_FS_FIXED) != 0) {
+            // fs was fixed. should check if quota warning was caused by tree optimization.
+            // This is not a real fix but optimization, so should not be counted as a fs fix.
+            Pattern passPattern = Pattern.compile(FSCK_PASS_PATTERN);
+            Pattern treeOptPattern = Pattern.compile(FSCK_TREE_OPTIMIZATION_PATTERN);
+            String currentPass = "";
+            boolean foundTreeOptimization = false;
+            boolean foundQuotaFix = false;
+            boolean foundOtherFix = false;
+            String otherFixLine = null;
+            for (int i = startLineNumber; i < endLineNumber; i++) {
+                String line = lines[i];
+                if (line.contains(FSCK_FS_MODIFIED)) { // no need to parse above this
+                    break;
+                } else if (line.startsWith("Pass ")) {
+                    Matcher matcher = passPattern.matcher(line);
+                    if (matcher.find()) {
+                        currentPass = matcher.group(1);
+                    }
+                } else if (line.startsWith("Inode ")) {
+                    Matcher matcher = treeOptPattern.matcher(line);
+                    if (matcher.find() && currentPass.equals("1")) {
+                        foundTreeOptimization = true;
+                        Slog.i(TAG, "fs_stat, partition:" + partition + " found tree optimization:"
+                                + line);
+                    } else {
+                        foundOtherFix = true;
+                        otherFixLine = line;
+                        break;
+                    }
+                } else if (line.startsWith("[QUOTA WARNING]") && currentPass.equals("5")) {
+                    Slog.i(TAG, "fs_stat, partition:" + partition + " found quota warning:"
+                            + line);
+                    foundQuotaFix = true;
+                    if (!foundTreeOptimization) { // only quota warning, this is real fix.
+                        otherFixLine = line;
+                        break;
+                    }
+                } else if (line.startsWith("Update quota info") && currentPass.equals("5")) {
+                    // follows "[QUOTA WARNING]", ignore
+                } else {
+                    line = line.trim();
+                    // ignore empty msg or any msg before Pass 1
+                    if (!line.isEmpty() && !currentPass.isEmpty()) {
+                        foundOtherFix = true;
+                        otherFixLine = line;
+                        break;
+                    }
+                }
+            }
+            if (!foundOtherFix && foundTreeOptimization && foundQuotaFix) {
+                // not a real fix, so clear it.
+                Slog.i(TAG, "fs_stat, partition:" + partition +
+                        " quota fix due to tree optimization");
+                stat &= ~FS_STAT_FS_FIXED;
+            } else {
+                if (otherFixLine != null) {
+                    Slog.i(TAG, "fs_stat, partition:" + partition + " fix:" + otherFixLine);
+                }
+            }
+        }
+        return stat;
+    }
+
+    private static void handleFsckFsStat(Matcher match, String[] lines, int startLineNumber,
+            int endLineNumber) {
         String partition = match.group(1);
         int stat;
         try {
@@ -412,9 +504,9 @@
             Slog.w(TAG, "cannot parse fs_stat: partition:" + partition + " stat:" + match.group(2));
             return;
         }
-
+        stat = fixFsckFsStat(partition, stat, lines, startLineNumber, endLineNumber);
         MetricsLogger.histogram(null, "boot_fs_stat_" + partition, stat);
-        Slog.i(TAG, "fs_stat, partition:" + partition + " stat:" + match.group(2));
+        Slog.i(TAG, "fs_stat, partition:" + partition + " stat:0x" + Integer.toHexString(stat));
     }
 
     private static HashMap<String, Long> readTimestamps() {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 33fabfc..96285cd 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -96,6 +96,7 @@
     android_os_SystemProperties.cpp \
     android_os_Trace.cpp \
     android_os_UEventObserver.cpp \
+    android_os_VintfObject.cpp \
     android_net_LocalSocketImpl.cpp \
     android_net_NetUtils.cpp \
     android_net_TrafficStats.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e237ce9..8ca4794 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -159,6 +159,7 @@
 extern int register_android_os_MessageQueue(JNIEnv* env);
 extern int register_android_os_Parcel(JNIEnv* env);
 extern int register_android_os_SELinux(JNIEnv* env);
+extern int register_android_os_VintfObject(JNIEnv *env);
 extern int register_android_os_seccomp(JNIEnv* env);
 extern int register_android_os_SystemProperties(JNIEnv *env);
 extern int register_android_os_SystemClock(JNIEnv* env);
@@ -1302,6 +1303,7 @@
     REG_JNI(register_android_os_HwBlob),
     REG_JNI(register_android_os_HwParcel),
     REG_JNI(register_android_os_HwRemoteBinder),
+    REG_JNI(register_android_os_VintfObject),
     REG_JNI(register_android_nio_utils),
     REG_JNI(register_android_graphics_Canvas),
     REG_JNI(register_android_graphics_Graphics),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 3a03af6..dd5632e4 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -44,14 +44,6 @@
 static jmethodID gBitmap_reinitMethodID;
 static jmethodID gBitmap_getAllocationByteCountMethodID;
 
-static jfieldID gTransferParams_aFieldID;
-static jfieldID gTransferParams_bFieldID;
-static jfieldID gTransferParams_cFieldID;
-static jfieldID gTransferParams_dFieldID;
-static jfieldID gTransferParams_eFieldID;
-static jfieldID gTransferParams_fFieldID;
-static jfieldID gTransferParams_gFieldID;
-
 namespace android {
 
 class BitmapWrapper {
@@ -286,9 +278,7 @@
     if (!localBitmap->valid()) return nullptr;
 
     SkPixelRef& pixelRef = localBitmap->bitmap();
-    pixelRef.lockPixels();
     if (!pixelRef.pixels()) {
-        pixelRef.unlockPixels();
         return nullptr;
     }
     pixelRef.ref();
@@ -306,7 +296,6 @@
 
     SkPixelRef& pixelRef = localBitmap->bitmap();
     pixelRef.notifyPixelsChanged();
-    pixelRef.unlockPixels();
     pixelRef.unref();
     return true;
 }
@@ -446,7 +435,6 @@
 
 bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
         int x, int y, int width, int height, const SkBitmap& dstBitmap) {
-    SkAutoLockPixels alp(dstBitmap);
     void* dst = dstBitmap.getPixels();
     FromColorProc proc = ChooseFromColorProc(dstBitmap);
 
@@ -742,28 +730,8 @@
     if (colorType != kN32_SkColorType || xyzD50 == nullptr || transferParameters == nullptr) {
         colorSpace = GraphicsJNI::colorSpaceForType(colorType);
     } else {
-        SkColorSpaceTransferFn p;
-        p.fA = (float) env->GetDoubleField(transferParameters, gTransferParams_aFieldID);
-        p.fB = (float) env->GetDoubleField(transferParameters, gTransferParams_bFieldID);
-        p.fC = (float) env->GetDoubleField(transferParameters, gTransferParams_cFieldID);
-        p.fD = (float) env->GetDoubleField(transferParameters, gTransferParams_dFieldID);
-        p.fE = (float) env->GetDoubleField(transferParameters, gTransferParams_eFieldID);
-        p.fF = (float) env->GetDoubleField(transferParameters, gTransferParams_fFieldID);
-        p.fG = (float) env->GetDoubleField(transferParameters, gTransferParams_gFieldID);
-
-        SkMatrix44 xyzMatrix(SkMatrix44::kIdentity_Constructor);
-        jfloat* array = env->GetFloatArrayElements(xyzD50, NULL);
-        xyzMatrix.setFloat(0, 0, array[0]);
-        xyzMatrix.setFloat(1, 0, array[1]);
-        xyzMatrix.setFloat(2, 0, array[2]);
-        xyzMatrix.setFloat(0, 1, array[3]);
-        xyzMatrix.setFloat(1, 1, array[4]);
-        xyzMatrix.setFloat(2, 1, array[5]);
-        xyzMatrix.setFloat(0, 2, array[6]);
-        xyzMatrix.setFloat(1, 2, array[7]);
-        xyzMatrix.setFloat(2, 2, array[8]);
-        env->ReleaseFloatArrayElements(xyzD50, array, 0);
-
+        SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
+        SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
         colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
     }
 
@@ -786,11 +754,10 @@
     // Skia does not support copying from kAlpha8 to types that are not alpha only.
     // We will handle this case here.
     if (kAlpha_8_SkColorType == src.colorType() && kAlpha_8_SkColorType != dstCT) {
-        SkAutoPixmapUnlock srcUnlocker;
-        if (!src.requestLock(&srcUnlocker)) {
+        SkPixmap srcPixmap;
+        if (!src.peekPixels(&srcPixmap)) {
             return false;
         }
-        SkPixmap srcPixmap = srcUnlocker.pixmap();
 
         SkImageInfo dstInfo = src.info().makeColorType(dstCT);
         if (dstCT == kRGBA_F16_SkColorType) {
@@ -1086,7 +1053,7 @@
         return NULL;
     }
 
-    SkColorTable* ctable = NULL;
+    sk_sp<SkColorTable> ctable = NULL;
     if (colorType == kIndex_8_SkColorType) {
         int count = p->readInt32();
         if (count < 0 || count > 256) {
@@ -1100,7 +1067,7 @@
             if (src == NULL) {
                 return NULL;
             }
-            ctable = new SkColorTable(src, count);
+            ctable = SkColorTable::Make(src, count);
         }
     }
 
@@ -1109,7 +1076,6 @@
     android::Parcel::ReadableBlob blob;
     android::status_t status = p->readBlob(size, &blob);
     if (status) {
-        SkSafeUnref(ctable);
         doThrowRE(env, "Could not read bitmap blob.");
         return NULL;
     }
@@ -1130,15 +1096,13 @@
         if (dupFd < 0) {
             ALOGE("Error allocating dup fd. Error:%d", errno);
             blob.release();
-            SkSafeUnref(ctable);
             doThrowRE(env, "Could not allocate dup blob fd.");
             return NULL;
         }
 
         // Map the pixels in place and take ownership of the ashmem region.
         nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
-                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
-        SkSafeUnref(ctable);
+                ctable.get(), dupFd, const_cast<void*>(blob.data()), size, !isMutable));
         if (!nativeBitmap) {
             close(dupFd);
             blob.release();
@@ -1164,15 +1128,12 @@
 
         // Copy the pixels into a new buffer.
         nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
-        SkSafeUnref(ctable);
         if (!nativeBitmap) {
             blob.release();
             doThrowRE(env, "Could not allocate java pixel ref.");
             return NULL;
         }
-        bitmap->lockPixels();
         memcpy(bitmap->getPixels(), blob.data(), size);
-        bitmap->unlockPixels();
 
         // Release the blob handle.
         blob.release();
@@ -1218,7 +1179,6 @@
 
     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();
@@ -1265,14 +1225,12 @@
         return JNI_FALSE;
     }
 
-    bitmap.lockPixels();
     const void* pSrc =  bitmap.getPixels();
     if (pSrc == NULL) {
         memset(blob.data(), 0, size);
     } else {
         memcpy(blob.data(), pSrc, size);
     }
-    bitmap.unlockPixels();
 
     blob.release();
     return JNI_TRUE;
@@ -1362,7 +1320,6 @@
         jint x, jint y) {
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
-    SkAutoLockPixels alp(bitmap);
 
     ToColorProc proc = ChooseToColorProc(bitmap);
     if (NULL == proc) {
@@ -1394,7 +1351,6 @@
         jint x, jint y, jint width, jint height) {
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
-    SkAutoLockPixels alp(bitmap);
 
     ToColorProc proc = ChooseToColorProc(bitmap);
     if (NULL == proc) {
@@ -1443,7 +1399,6 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
     SkColor color = static_cast<SkColor>(colorHandle);
-    SkAutoLockPixels alp(bitmap);
     if (NULL == bitmap.getPixels()) {
         return;
     }
@@ -1480,7 +1435,6 @@
                                       jlong bitmapHandle, jobject jbuffer) {
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
-    SkAutoLockPixels alp(bitmap);
     const void* src = bitmap.getPixels();
 
     if (NULL != src) {
@@ -1495,7 +1449,6 @@
                                         jlong bitmapHandle, jobject jbuffer) {
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
-    SkAutoLockPixels alp(bitmap);
     void* dst = bitmap.getPixels();
 
     if (NULL != dst) {
@@ -1530,9 +1483,6 @@
         return JNI_FALSE;
     }
 
-    SkAutoLockPixels alp0(bm0);
-    SkAutoLockPixels alp1(bm1);
-
     // if we can't load the pixels, return false
     if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
         return JNI_FALSE;
@@ -1635,20 +1585,6 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-static jclass make_globalref(JNIEnv* env, const char classname[])
-{
-    jclass c = env->FindClass(classname);
-    SkASSERT(c);
-    return (jclass) env->NewGlobalRef(c);
-}
-
-static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
-                                const char fieldname[], const char type[])
-{
-    jfieldID id = env->GetFieldID(clazz, fieldname, type);
-    SkASSERT(id);
-    return id;
-}
 
 static const JNINativeMethod gBitmapMethods[] = {
     {   "nativeCreate",             "([IIIIIIZ[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;",
@@ -1706,20 +1642,11 @@
 
 int register_android_graphics_Bitmap(JNIEnv* env)
 {
-    jclass transfer_params_class = FindClassOrDie(env, "android/graphics/ColorSpace$Rgb$TransferParameters");
-    gTransferParams_aFieldID = GetFieldIDOrDie(env, transfer_params_class, "a", "D");
-    gTransferParams_bFieldID = GetFieldIDOrDie(env, transfer_params_class, "b", "D");
-    gTransferParams_cFieldID = GetFieldIDOrDie(env, transfer_params_class, "c", "D");
-    gTransferParams_dFieldID = GetFieldIDOrDie(env, transfer_params_class, "d", "D");
-    gTransferParams_eFieldID = GetFieldIDOrDie(env, transfer_params_class, "e", "D");
-    gTransferParams_fFieldID = GetFieldIDOrDie(env, transfer_params_class, "f", "D");
-    gTransferParams_gFieldID = GetFieldIDOrDie(env, transfer_params_class, "g", "D");
-
-    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
-    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
-    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
-    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
-    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
+    gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
+    gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
+    gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
+    gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
+    gBitmap_getAllocationByteCountMethodID = GetMethodIDOrDie(env, gBitmap_class, "getAllocationByteCount", "()I");
     return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
                                          NELEM(gBitmapMethods));
 }
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 2ee4dec..5a25d5e 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -27,6 +27,7 @@
 jfieldID gOptions_justBoundsFieldID;
 jfieldID gOptions_sampleSizeFieldID;
 jfieldID gOptions_configFieldID;
+jfieldID gOptions_colorSpaceFieldID;
 jfieldID gOptions_premultipliedFieldID;
 jfieldID gOptions_mutableFieldID;
 jfieldID gOptions_ditherFieldID;
@@ -51,20 +52,6 @@
 jclass gBitmapConfig_class;
 jmethodID gBitmapConfig_nativeToConfigMethodID;
 
-jclass gColorSpace_class;
-jmethodID gColorSpace_getMethodID;
-jmethodID gColorSpace_matchMethodID;
-
-jclass gColorSpaceRGB_class;
-jmethodID gColorSpaceRGB_constructorMethodID;
-
-jclass gColorSpace_Named_class;
-jfieldID gColorSpace_Named_sRGBFieldID;
-jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID;
-
-jclass gTransferParameters_class;
-jmethodID gTransferParameters_constructorMethodID;
-
 using namespace android;
 
 jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) {
@@ -208,12 +195,8 @@
             return false;
         }
 
-        mBitmap->reconfigure(info, bitmap->rowBytes(), ctable);
+        mBitmap->reconfigure(info, bitmap->rowBytes(), sk_ref_sp(ctable));
         bitmap->setPixelRef(sk_ref_sp(mBitmap), 0, 0);
-
-        // since we're already allocated, we lockPixels right away
-        // HeapAllocator behaves this way too
-        bitmap->lockPixels();
         return true;
     }
 
@@ -242,70 +225,6 @@
            needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
 }
 
-static jobject getColorSpace(JNIEnv* env,
-        sk_sp<SkColorSpace>& decodeColorSpace, SkColorType decodeColorType) {
-    jobject colorSpace = nullptr;
-
-    // No need to match, we know what the output color space will be
-    if (decodeColorType == kRGBA_F16_SkColorType) {
-        jobject linearExtendedSRGB = env->GetStaticObjectField(
-                gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID);
-        colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
-                gColorSpace_getMethodID, linearExtendedSRGB);
-    } else {
-        // Same here, no need to match
-        if (decodeColorSpace->isSRGB()) {
-            jobject sRGB = env->GetStaticObjectField(
-                    gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID);
-            colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
-                    gColorSpace_getMethodID, sRGB);
-        } else if (decodeColorSpace.get() != nullptr) {
-            // Try to match against known RGB color spaces using the CIE XYZ D50
-            // conversion matrix and numerical transfer function parameters
-            SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
-            LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
-
-            SkColorSpaceTransferFn transferParams;
-            // We can only handle numerical transfer functions at the moment
-            LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
-
-            jobject params = env->NewObject(gTransferParameters_class,
-                    gTransferParameters_constructorMethodID,
-                    transferParams.fA, transferParams.fB, transferParams.fC,
-                    transferParams.fD, transferParams.fE, transferParams.fF,
-                    transferParams.fG);
-
-            jfloatArray xyzArray = env->NewFloatArray(9);
-            jfloat xyz[9] = {
-                    xyzMatrix.getFloat(0, 0),
-                    xyzMatrix.getFloat(1, 0),
-                    xyzMatrix.getFloat(2, 0),
-                    xyzMatrix.getFloat(0, 1),
-                    xyzMatrix.getFloat(1, 1),
-                    xyzMatrix.getFloat(2, 1),
-                    xyzMatrix.getFloat(0, 2),
-                    xyzMatrix.getFloat(1, 2),
-                    xyzMatrix.getFloat(2, 2)
-            };
-            env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
-
-            colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
-                    gColorSpace_matchMethodID, xyzArray, params);
-
-            if (colorSpace == nullptr) {
-                // We couldn't find an exact match, let's create a new color space
-                // instance with the 3x3 conversion matrix and transfer function
-                colorSpace = env->NewObject(gColorSpaceRGB_class,
-                        gColorSpaceRGB_constructorMethodID,
-                        env->NewStringUTF("Unknown"), xyzArray, params);
-            }
-
-            env->DeleteLocalRef(xyzArray);
-        }
-    }
-    return colorSpace;
-}
-
 static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
     // This function takes ownership of the input stream.  Since the SkAndroidCodec
     // will take ownership of the stream, we don't necessarily need to take ownership
@@ -322,6 +241,7 @@
     float scale = 1.0f;
     bool requireUnpremultiplied = false;
     jobject javaBitmap = NULL;
+    sk_sp<SkColorSpace> prefColorSpace = nullptr;
 
     // Update with options supplied by the client.
     if (options != NULL) {
@@ -345,6 +265,8 @@
 
         jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
         prefColorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig);
+        jobject jcolorSpace = env->GetObjectField(options, gOptions_colorSpaceFieldID);
+        prefColorSpace = GraphicsJNI::getNativeColorSpace(env, jcolorSpace);
         isHardware = GraphicsJNI::isHardwareConfig(env, jconfig);
         isMutable = env->GetBooleanField(options, gOptions_mutableFieldID);
         requireUnpremultiplied = !env->GetBooleanField(options, gOptions_premultipliedFieldID);
@@ -398,7 +320,8 @@
 
     // Set the decode colorType
     SkColorType decodeColorType = codec->computeOutputColorType(prefColorType);
-    sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace(decodeColorType);
+    sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace(
+            decodeColorType, prefColorSpace);
 
     // Set the options and return if the client only wants the size.
     if (options != NULL) {
@@ -426,7 +349,7 @@
         env->SetObjectField(options, gOptions_outConfigFieldID, config);
 
         env->SetObjectField(options, gOptions_outColorSpaceFieldID,
-                getColorSpace(env, decodeColorSpace, decodeColorType));
+                GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
 
         if (onlyDecodeSize) {
             return nullptr;
@@ -615,7 +538,7 @@
         paint.setBlendMode(SkBlendMode::kSrc);
         paint.setFilterQuality(kLow_SkFilterQuality); // bilinear filtering
 
-        SkCanvas canvas(outputBitmap);
+        SkCanvas canvas(outputBitmap, SkCanvas::ColorBehavior::kLegacy);
         canvas.scale(sx, sy);
         canvas.drawBitmap(decodingBitmap, 0.0f, 0.0f, &paint);
     } else {
@@ -794,6 +717,8 @@
     gOptions_sampleSizeFieldID = GetFieldIDOrDie(env, options_class, "inSampleSize", "I");
     gOptions_configFieldID = GetFieldIDOrDie(env, options_class, "inPreferredConfig",
             "Landroid/graphics/Bitmap$Config;");
+    gOptions_colorSpaceFieldID = GetFieldIDOrDie(env, options_class, "inPreferredColorSpace",
+            "Landroid/graphics/ColorSpace;");
     gOptions_premultipliedFieldID = GetFieldIDOrDie(env, options_class, "inPremultiplied", "Z");
     gOptions_mutableFieldID = GetFieldIDOrDie(env, options_class, "inMutable", "Z");
     gOptions_ditherFieldID = GetFieldIDOrDie(env, options_class, "inDither", "Z");
@@ -826,29 +751,6 @@
     gBitmapConfig_nativeToConfigMethodID = GetStaticMethodIDOrDie(env, gBitmapConfig_class,
             "nativeToConfig", "(I)Landroid/graphics/Bitmap$Config;");
 
-    gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace"));
-    gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class,
-            "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;");
-    gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match",
-            "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;");
-
-    gColorSpaceRGB_class = MakeGlobalRefOrDie(env,
-            FindClassOrDie(env, "android/graphics/ColorSpace$Rgb"));
-    gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
-            "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V");
-
-    gColorSpace_Named_class = MakeGlobalRefOrDie(env,
-            FindClassOrDie(env, "android/graphics/ColorSpace$Named"));
-    gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env,
-            gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;");
-    gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
-            gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
-
-    gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env,
-            "android/graphics/ColorSpace$Rgb$TransferParameters"));
-    gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class,
-            "<init>", "(DDDDDDD)V");
-
     return android::RegisterMethodsOrDie(env, "android/graphics/BitmapFactory",
                                          gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h
index 76db41d..1ee49fa 100644
--- a/core/jni/android/graphics/BitmapFactory.h
+++ b/core/jni/android/graphics/BitmapFactory.h
@@ -8,6 +8,7 @@
 extern jfieldID gOptions_justBoundsFieldID;
 extern jfieldID gOptions_sampleSizeFieldID;
 extern jfieldID gOptions_configFieldID;
+extern jfieldID gOptions_colorSpaceFieldID;
 extern jfieldID gOptions_premultipliedFieldID;
 extern jfieldID gOptions_ditherFieldID;
 extern jfieldID gOptions_purgeableFieldID;
@@ -17,9 +18,14 @@
 extern jfieldID gOptions_widthFieldID;
 extern jfieldID gOptions_heightFieldID;
 extern jfieldID gOptions_mimeFieldID;
+extern jfieldID gOptions_outConfigFieldID;
+extern jfieldID gOptions_outColorSpaceFieldID;
 extern jfieldID gOptions_mCancelID;
 extern jfieldID gOptions_bitmapFieldID;
 
+extern jclass gBitmapConfig_class;
+extern jmethodID gBitmapConfig_nativeToConfigMethodID;
+
 jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format);
 
 jobject decodeBitmap(JNIEnv* env, void* data, size_t size);
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 3247851..9355cfc 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -132,11 +132,14 @@
     bool requireUnpremul = false;
     jobject javaBitmap = NULL;
     bool isHardware = false;
+    sk_sp<SkColorSpace> colorSpace = nullptr;
     // Update the default options with any options supplied by the client.
     if (NULL != options) {
         sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
         jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
         colorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig);
+        jobject jcolorSpace = env->GetObjectField(options, gOptions_colorSpaceFieldID);
+        colorSpace = GraphicsJNI::getNativeColorSpace(env, jcolorSpace);
         isHardware = GraphicsJNI::isHardwareConfig(env, jconfig);
         requireUnpremul = !env->GetBooleanField(options, gOptions_premultipliedFieldID);
         javaBitmap = env->GetObjectField(options, gOptions_bitmapFieldID);
@@ -148,8 +151,16 @@
         env->SetIntField(options, gOptions_widthFieldID, -1);
         env->SetIntField(options, gOptions_heightFieldID, -1);
         env->SetObjectField(options, gOptions_mimeFieldID, 0);
+        env->SetObjectField(options, gOptions_outConfigFieldID, 0);
+        env->SetObjectField(options, gOptions_outColorSpaceFieldID, 0);
     }
 
+    SkBitmapRegionDecoder* brd = reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle);
+
+    SkColorType decodeColorType = brd->computeOutputColorType(colorType);
+    sk_sp<SkColorSpace> decodeColorSpace = brd->computeOutputColorSpace(
+            decodeColorType, colorSpace);
+
     // Recycle a bitmap if possible.
     android::Bitmap* recycledBitmap = nullptr;
     size_t recycledBytes = 0;
@@ -168,17 +179,16 @@
     if (javaBitmap) {
         allocator = &recycleAlloc;
         // We are required to match the color type of the recycled bitmap.
-        colorType = recycledBitmap->info().colorType();
+        decodeColorType = recycledBitmap->info().colorType();
     } else {
         allocator = &heapAlloc;
     }
 
     // Decode the region.
     SkIRect subset = SkIRect::MakeXYWH(inputX, inputY, inputWidth, inputHeight);
-    SkBitmapRegionDecoder* brd =
-            reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle);
     SkBitmap bitmap;
-    if (!brd->decodeRegion(&bitmap, allocator, subset, sampleSize, colorType, requireUnpremul)) {
+    if (!brd->decodeRegion(&bitmap, allocator, subset, sampleSize,
+            decodeColorType, requireUnpremul, decodeColorSpace)) {
         return nullObjectReturn("Failed to decode region.");
     }
 
@@ -186,16 +196,29 @@
     if (NULL != options) {
         env->SetIntField(options, gOptions_widthFieldID, bitmap.width());
         env->SetIntField(options, gOptions_heightFieldID, bitmap.height());
+
         env->SetObjectField(options, gOptions_mimeFieldID,
                 encodedFormatToString(env, (SkEncodedImageFormat)brd->getEncodedFormat()));
         if (env->ExceptionCheck()) {
             return nullObjectReturn("OOM in encodedFormatToString()");
         }
+
+        jint configID = GraphicsJNI::colorTypeToLegacyBitmapConfig(decodeColorType);
+        if (isHardware) {
+            configID = GraphicsJNI::kHardware_LegacyBitmapConfig;
+        }
+        jobject config = env->CallStaticObjectMethod(gBitmapConfig_class,
+                gBitmapConfig_nativeToConfigMethodID, configID);
+        env->SetObjectField(options, gOptions_outConfigFieldID, config);
+
+        env->SetObjectField(options, gOptions_outColorSpaceFieldID,
+                GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
     }
 
     // If we may have reused a bitmap, we need to indicate that the pixels have changed.
     if (javaBitmap) {
         recycleAlloc.copyIfNecessary();
+        bitmap::reinitBitmap(env, javaBitmap, recycledBitmap->info(), !requireUnpremul);
         return javaBitmap;
     }
 
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 3010dc1..fc90fb3 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -45,21 +45,24 @@
 constexpr jint RESOLVE_BY_FONT_TABLE = -1;
 
 struct NativeFamilyBuilder {
+    NativeFamilyBuilder(uint32_t langId, int variant)
+        : langId(langId), variant(variant), allowUnsupportedFont(false) {}
     uint32_t langId;
     int variant;
+    bool allowUnsupportedFont;
     std::vector<minikin::Font> fonts;
     std::vector<minikin::FontVariation> axes;
 };
 
 static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring lang, jint variant) {
-    NativeFamilyBuilder* builder = new NativeFamilyBuilder();
+    NativeFamilyBuilder* builder;
     if (lang != nullptr) {
         ScopedUtfChars str(env, lang);
-        builder->langId = minikin::FontStyle::registerLanguageList(str.c_str());
+        builder = new NativeFamilyBuilder(
+                minikin::FontStyle::registerLanguageList(str.c_str()), variant);
     } else {
-        builder->langId = minikin::FontStyle::registerLanguageList("");
+        builder = new NativeFamilyBuilder(minikin::FontStyle::registerLanguageList(""), variant);
     }
-    builder->variant = variant;
     return reinterpret_cast<jlong>(builder);
 }
 
@@ -67,12 +70,22 @@
     if (builderPtr == 0) {
         return 0;
     }
+    std::unique_ptr<NativeFamilyBuilder> builder(
+            reinterpret_cast<NativeFamilyBuilder*>(builderPtr));
+    std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
+            builder->langId, builder->variant, std::move(builder->fonts));
+    if (family->getCoverage().length() == 0 && !builder->allowUnsupportedFont) {
+        return 0;
+    }
+    return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
+}
+
+static void FontFamily_allowUnsupportedFont(jlong builderPtr) {
+    if (builderPtr == 0) {
+        return;
+    }
     NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    FontFamilyWrapper* family = new FontFamilyWrapper(
-            std::make_shared<minikin::FontFamily>(
-                    builder->langId, builder->variant, std::move(builder->fonts)));
-    delete builder;
-    return reinterpret_cast<jlong>(family);
+    builder->allowUnsupportedFont = true;
 }
 
 static void FontFamily_abort(jlong builderPtr) {
@@ -258,6 +271,7 @@
 static const JNINativeMethod gFontFamilyMethods[] = {
     { "nInitBuilder",          "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
     { "nCreateFamily",         "(J)J", (void*)FontFamily_create },
+    { "nAllowUnsupportedFont", "(J)V", (void*)FontFamily_allowUnsupportedFont },
     { "nAbort",                "(J)V", (void*)FontFamily_abort },
     { "nUnrefFamily",          "(J)V", (void*)FontFamily_unref },
     { "nAddFont",              "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 113bc19..5a2238f 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -6,6 +6,7 @@
 #include "jni.h"
 #include "JNIHelp.h"
 #include "GraphicsJNI.h"
+#include "core_jni_helpers.h"
 
 #include "SkCanvas.h"
 #include "SkMath.h"
@@ -17,6 +18,8 @@
 #include <Caches.h>
 #include <TextureCache.h>
 
+using namespace android;
+
 void doThrowNPE(JNIEnv* env) {
     jniThrowNullPointerException(env, NULL);
 }
@@ -178,6 +181,32 @@
 static jmethodID gVMRuntime_newNonMovableArray;
 static jmethodID gVMRuntime_addressOf;
 
+static jfieldID gTransferParams_aFieldID;
+static jfieldID gTransferParams_bFieldID;
+static jfieldID gTransferParams_cFieldID;
+static jfieldID gTransferParams_dFieldID;
+static jfieldID gTransferParams_eFieldID;
+static jfieldID gTransferParams_fFieldID;
+static jfieldID gTransferParams_gFieldID;
+
+static jclass gColorSpace_class;
+static jfieldID gColorSpace_IlluminantD50FieldID;
+static jmethodID gColorSpace_adaptMethodID;
+static jmethodID gColorSpace_getMethodID;
+static jmethodID gColorSpace_matchMethodID;
+
+static jclass gColorSpaceRGB_class;
+static jmethodID gColorSpaceRGB_getTransferParametersMethodID;
+static jmethodID gColorSpaceRGB_getTransformMethodID;
+static jmethodID gColorSpaceRGB_constructorMethodID;
+
+static jclass gColorSpace_Named_class;
+static jfieldID gColorSpace_Named_sRGBFieldID;
+static jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID;
+
+static jclass gTransferParameters_class;
+static jmethodID gTransferParameters_constructorMethodID;
+
 ///////////////////////////////////////////////////////////////////////////////
 
 void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B)
@@ -328,7 +357,7 @@
 }
 
 void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
-    android::bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
+    bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
 }
 
 SkPixelRef* GraphicsJNI::refSkPixelRef(JNIEnv* env, jobject jbitmap) {
@@ -427,15 +456,11 @@
     // attempting to compute our own.
     const size_t rowBytes = bitmap->rowBytes();
 
-    auto wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable);
+    auto wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, sk_ref_sp(ctable));
     wrapper->getSkBitmap(bitmap);
     if (readOnly) {
         bitmap->pixelRef()->setImmutable();
     }
-    // since we're already allocated, we lockPixels right away
-    // HeapAllocator behaves this way too
-    bitmap->lockPixels();
-
     return wrapper;
 }
 
@@ -464,9 +489,128 @@
     return colorSpace == nullptr || colorSpace->isSRGB();
 }
 
+SkColorSpaceTransferFn GraphicsJNI::getNativeTransferParameters(JNIEnv* env, jobject transferParams) {
+    SkColorSpaceTransferFn p;
+    p.fA = (float) env->GetDoubleField(transferParams, gTransferParams_aFieldID);
+    p.fB = (float) env->GetDoubleField(transferParams, gTransferParams_bFieldID);
+    p.fC = (float) env->GetDoubleField(transferParams, gTransferParams_cFieldID);
+    p.fD = (float) env->GetDoubleField(transferParams, gTransferParams_dFieldID);
+    p.fE = (float) env->GetDoubleField(transferParams, gTransferParams_eFieldID);
+    p.fF = (float) env->GetDoubleField(transferParams, gTransferParams_fFieldID);
+    p.fG = (float) env->GetDoubleField(transferParams, gTransferParams_gFieldID);
+    return p;
+}
+
+SkMatrix44 GraphicsJNI::getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50) {
+    SkMatrix44 xyzMatrix(SkMatrix44::kIdentity_Constructor);
+    jfloat* array = env->GetFloatArrayElements(xyzD50, NULL);
+    xyzMatrix.setFloat(0, 0, array[0]);
+    xyzMatrix.setFloat(1, 0, array[1]);
+    xyzMatrix.setFloat(2, 0, array[2]);
+    xyzMatrix.setFloat(0, 1, array[3]);
+    xyzMatrix.setFloat(1, 1, array[4]);
+    xyzMatrix.setFloat(2, 1, array[5]);
+    xyzMatrix.setFloat(0, 2, array[6]);
+    xyzMatrix.setFloat(1, 2, array[7]);
+    xyzMatrix.setFloat(2, 2, array[8]);
+    env->ReleaseFloatArrayElements(xyzD50, array, 0);
+    return xyzMatrix;
+}
+
+sk_sp<SkColorSpace> GraphicsJNI::getNativeColorSpace(JNIEnv* env, jobject colorSpace) {
+    if (colorSpace == nullptr) return nullptr;
+    if (!env->IsInstanceOf(colorSpace, gColorSpaceRGB_class)) {
+        doThrowIAE(env, "The color space must be an RGB color space");
+    }
+
+    jobject transferParams = env->CallObjectMethod(colorSpace,
+            gColorSpaceRGB_getTransferParametersMethodID);
+    if (transferParams == nullptr) {
+        doThrowIAE(env, "The color space must use an ICC parametric transfer function");
+    }
+
+    jfloatArray illuminantD50 = (jfloatArray) env->GetStaticObjectField(gColorSpace_class,
+            gColorSpace_IlluminantD50FieldID);
+    jobject colorSpaceD50 = env->CallStaticObjectMethod(gColorSpace_class,
+            gColorSpace_adaptMethodID, colorSpace, illuminantD50);
+
+    jfloatArray xyzD50 = (jfloatArray) env->CallObjectMethod(colorSpaceD50,
+            gColorSpaceRGB_getTransformMethodID);
+
+    SkMatrix44 xyzMatrix = getNativeXYZMatrix(env, xyzD50);
+    SkColorSpaceTransferFn transferFunction = getNativeTransferParameters(env, transferParams);
+
+    return SkColorSpace::MakeRGB(transferFunction, xyzMatrix);
+}
+
+
+jobject GraphicsJNI::getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
+        SkColorType decodeColorType) {
+    jobject colorSpace = nullptr;
+
+    // No need to match, we know what the output color space will be
+    if (decodeColorType == kRGBA_F16_SkColorType) {
+        jobject linearExtendedSRGB = env->GetStaticObjectField(
+                gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID);
+        colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+                gColorSpace_getMethodID, linearExtendedSRGB);
+    } else {
+        // Same here, no need to match
+        if (decodeColorSpace->isSRGB()) {
+            jobject sRGB = env->GetStaticObjectField(
+                    gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID);
+            colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+                    gColorSpace_getMethodID, sRGB);
+        } else if (decodeColorSpace.get() != nullptr) {
+            // Try to match against known RGB color spaces using the CIE XYZ D50
+            // conversion matrix and numerical transfer function parameters
+            SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
+            LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
+
+            SkColorSpaceTransferFn transferParams;
+            // We can only handle numerical transfer functions at the moment
+            LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
+
+            jobject params = env->NewObject(gTransferParameters_class,
+                    gTransferParameters_constructorMethodID,
+                    transferParams.fA, transferParams.fB, transferParams.fC,
+                    transferParams.fD, transferParams.fE, transferParams.fF,
+                    transferParams.fG);
+
+            jfloatArray xyzArray = env->NewFloatArray(9);
+            jfloat xyz[9] = {
+                    xyzMatrix.getFloat(0, 0),
+                    xyzMatrix.getFloat(1, 0),
+                    xyzMatrix.getFloat(2, 0),
+                    xyzMatrix.getFloat(0, 1),
+                    xyzMatrix.getFloat(1, 1),
+                    xyzMatrix.getFloat(2, 1),
+                    xyzMatrix.getFloat(0, 2),
+                    xyzMatrix.getFloat(1, 2),
+                    xyzMatrix.getFloat(2, 2)
+            };
+            env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
+
+            colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+                    gColorSpace_matchMethodID, xyzArray, params);
+
+            if (colorSpace == nullptr) {
+                // We couldn't find an exact match, let's create a new color space
+                // instance with the 3x3 conversion matrix and transfer function
+                colorSpace = env->NewObject(gColorSpaceRGB_class,
+                        gColorSpaceRGB_constructorMethodID,
+                        env->NewStringUTF("Unknown"), xyzArray, params);
+            }
+
+            env->DeleteLocalRef(xyzArray);
+        }
+    }
+    return colorSpace;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
-    mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable);
+    mStorage = android::Bitmap::allocateHeapBitmap(bitmap, sk_ref_sp(ctable));
     return !!mStorage;
 }
 
@@ -510,7 +654,11 @@
         // mRecycledBitmap->info() for the SkImageInfo.  According to the
         // specification for BitmapRegionDecoder, we are not allowed to change
         // the SkImageInfo.
-        mRecycledBitmap->reconfigure(mRecycledBitmap->info(), rowBytes, ctable);
+        // We can (must) preserve the color space since it doesn't affect the
+        // storage needs
+        mRecycledBitmap->reconfigure(
+                mRecycledBitmap->info().makeColorSpace(bitmap->refColorSpace()),
+                rowBytes, sk_ref_sp(ctable));
 
         // Give the bitmap the same pixelRef as mRecycledBitmap.
         // skbug.com/4538: We also need to make sure that the rowBytes on the pixel ref
@@ -522,7 +670,6 @@
         mRecycledBitmap->setAlphaType(bitmap->alphaType());
 
         bitmap->notifyPixelsChanged();
-        bitmap->lockPixels();
         mNeedsCopy = false;
 
         // TODO: If the dimensions of the SkBitmap are smaller than those of
@@ -570,80 +717,103 @@
 }
 
 bool AshmemPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
-    mStorage = android::Bitmap::allocateAshmemBitmap(bitmap, ctable);
+    mStorage = android::Bitmap::allocateAshmemBitmap(bitmap, sk_ref_sp(ctable));
     return !!mStorage;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static jclass make_globalref(JNIEnv* env, const char classname[])
-{
-    jclass c = env->FindClass(classname);
-    SkASSERT(c);
-    return (jclass) env->NewGlobalRef(c);
-}
-
-static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
-                                const char fieldname[], const char type[])
-{
-    jfieldID id = env->GetFieldID(clazz, fieldname, type);
-    SkASSERT(id);
-    return id;
-}
-
 int register_android_graphics_Graphics(JNIEnv* env)
 {
     jmethodID m;
     jclass c;
 
-    gRect_class = make_globalref(env, "android/graphics/Rect");
-    gRect_leftFieldID = getFieldIDCheck(env, gRect_class, "left", "I");
-    gRect_topFieldID = getFieldIDCheck(env, gRect_class, "top", "I");
-    gRect_rightFieldID = getFieldIDCheck(env, gRect_class, "right", "I");
-    gRect_bottomFieldID = getFieldIDCheck(env, gRect_class, "bottom", "I");
+    gRect_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Rect"));
+    gRect_leftFieldID = GetFieldIDOrDie(env, gRect_class, "left", "I");
+    gRect_topFieldID = GetFieldIDOrDie(env, gRect_class, "top", "I");
+    gRect_rightFieldID = GetFieldIDOrDie(env, gRect_class, "right", "I");
+    gRect_bottomFieldID = GetFieldIDOrDie(env, gRect_class, "bottom", "I");
 
-    gRectF_class = make_globalref(env, "android/graphics/RectF");
-    gRectF_leftFieldID = getFieldIDCheck(env, gRectF_class, "left", "F");
-    gRectF_topFieldID = getFieldIDCheck(env, gRectF_class, "top", "F");
-    gRectF_rightFieldID = getFieldIDCheck(env, gRectF_class, "right", "F");
-    gRectF_bottomFieldID = getFieldIDCheck(env, gRectF_class, "bottom", "F");
+    gRectF_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/RectF"));
+    gRectF_leftFieldID = GetFieldIDOrDie(env, gRectF_class, "left", "F");
+    gRectF_topFieldID = GetFieldIDOrDie(env, gRectF_class, "top", "F");
+    gRectF_rightFieldID = GetFieldIDOrDie(env, gRectF_class, "right", "F");
+    gRectF_bottomFieldID = GetFieldIDOrDie(env, gRectF_class, "bottom", "F");
 
-    gPoint_class = make_globalref(env, "android/graphics/Point");
-    gPoint_xFieldID = getFieldIDCheck(env, gPoint_class, "x", "I");
-    gPoint_yFieldID = getFieldIDCheck(env, gPoint_class, "y", "I");
+    gPoint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Point"));
+    gPoint_xFieldID = GetFieldIDOrDie(env, gPoint_class, "x", "I");
+    gPoint_yFieldID = GetFieldIDOrDie(env, gPoint_class, "y", "I");
 
-    gPointF_class = make_globalref(env, "android/graphics/PointF");
-    gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F");
-    gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F");
+    gPointF_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/PointF"));
+    gPointF_xFieldID = GetFieldIDOrDie(env, gPointF_class, "x", "F");
+    gPointF_yFieldID = GetFieldIDOrDie(env, gPointF_class, "y", "F");
 
-    gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
-    gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(J)V");
+    gBitmapRegionDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/BitmapRegionDecoder"));
+    gBitmapRegionDecoder_constructorMethodID = GetMethodIDOrDie(env, gBitmapRegionDecoder_class, "<init>", "(J)V");
 
-    gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config");
-    gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class,
-                                                     "nativeInt", "I");
+    gBitmapConfig_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap$Config"));
+    gBitmapConfig_nativeInstanceID = GetFieldIDOrDie(env, gBitmapConfig_class, "nativeInt", "I");
 
-    gCanvas_class = make_globalref(env, "android/graphics/Canvas");
-    gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvasWrapper", "J");
+    gCanvas_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Canvas"));
+    gCanvas_nativeInstanceID = GetFieldIDOrDie(env, gCanvas_class, "mNativeCanvasWrapper", "J");
 
-    gPicture_class = make_globalref(env, "android/graphics/Picture");
-    gPicture_nativeInstanceID = getFieldIDCheck(env, gPicture_class, "mNativePicture", "J");
+    gPicture_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Picture"));
+    gPicture_nativeInstanceID = GetFieldIDOrDie(env, gPicture_class, "mNativePicture", "J");
 
-    gRegion_class = make_globalref(env, "android/graphics/Region");
-    gRegion_nativeInstanceID = getFieldIDCheck(env, gRegion_class, "mNativeRegion", "J");
-    gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>",
-        "(JI)V");
+    gRegion_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Region"));
+    gRegion_nativeInstanceID = GetFieldIDOrDie(env, gRegion_class, "mNativeRegion", "J");
+    gRegion_constructorMethodID = GetMethodIDOrDie(env, gRegion_class, "<init>", "(JI)V");
 
     c = env->FindClass("java/lang/Byte");
     gByte_class = (jclass) env->NewGlobalRef(
         env->GetStaticObjectField(c, env->GetStaticFieldID(c, "TYPE", "Ljava/lang/Class;")));
 
-    gVMRuntime_class = make_globalref(env, "dalvik/system/VMRuntime");
+    gVMRuntime_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "dalvik/system/VMRuntime"));
     m = env->GetStaticMethodID(gVMRuntime_class, "getRuntime", "()Ldalvik/system/VMRuntime;");
     gVMRuntime = env->NewGlobalRef(env->CallStaticObjectMethod(gVMRuntime_class, m));
-    gVMRuntime_newNonMovableArray = env->GetMethodID(gVMRuntime_class, "newNonMovableArray",
+    gVMRuntime_newNonMovableArray = GetMethodIDOrDie(env, gVMRuntime_class, "newNonMovableArray",
                                                      "(Ljava/lang/Class;I)Ljava/lang/Object;");
-    gVMRuntime_addressOf = env->GetMethodID(gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J");
+    gVMRuntime_addressOf = GetMethodIDOrDie(env, gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J");
+
+    jclass transfer_params_class = FindClassOrDie(env, "android/graphics/ColorSpace$Rgb$TransferParameters");
+    gTransferParams_aFieldID = GetFieldIDOrDie(env, transfer_params_class, "a", "D");
+    gTransferParams_bFieldID = GetFieldIDOrDie(env, transfer_params_class, "b", "D");
+    gTransferParams_cFieldID = GetFieldIDOrDie(env, transfer_params_class, "c", "D");
+    gTransferParams_dFieldID = GetFieldIDOrDie(env, transfer_params_class, "d", "D");
+    gTransferParams_eFieldID = GetFieldIDOrDie(env, transfer_params_class, "e", "D");
+    gTransferParams_fFieldID = GetFieldIDOrDie(env, transfer_params_class, "f", "D");
+    gTransferParams_gFieldID = GetFieldIDOrDie(env, transfer_params_class, "g", "D");
+
+    gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace"));
+    gColorSpace_IlluminantD50FieldID = GetStaticFieldIDOrDie(env,
+            gColorSpace_class, "ILLUMINANT_D50", "[F");
+    gColorSpace_adaptMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "adapt",
+            "(Landroid/graphics/ColorSpace;[F)Landroid/graphics/ColorSpace;");
+    gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class,
+            "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;");
+    gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match",
+            "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;");
+
+    gColorSpaceRGB_class = MakeGlobalRefOrDie(env,
+            FindClassOrDie(env, "android/graphics/ColorSpace$Rgb"));
+    gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
+            "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V");
+    gColorSpaceRGB_getTransferParametersMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
+            "getTransferParameters", "()Landroid/graphics/ColorSpace$Rgb$TransferParameters;");
+    gColorSpaceRGB_getTransformMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
+            "getTransform", "()[F");
+
+    gColorSpace_Named_class = MakeGlobalRefOrDie(env,
+            FindClassOrDie(env, "android/graphics/ColorSpace$Named"));
+    gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env,
+            gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;");
+    gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
+            gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
+
+    gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env,
+            "android/graphics/ColorSpace$Rgb$TransferParameters"));
+    gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class,
+            "<init>", "(DDDDDDD)V");
 
     return 0;
 }
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 7d7c881..7fbea25 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -10,6 +10,7 @@
 #include "SkPoint.h"
 #include "SkRect.h"
 #include "SkColorSpace.h"
+#include "SkMatrix44.h"
 #include <jni.h>
 #include <hwui/Canvas.h>
 #include <hwui/Bitmap.h>
@@ -112,6 +113,13 @@
     static sk_sp<SkColorSpace> linearColorSpace();
     static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
     static bool isColorSpaceSRGB(SkColorSpace* colorSpace);
+
+    static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams);
+    static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50);
+    static sk_sp<SkColorSpace> getNativeColorSpace(JNIEnv* env, jobject colorSpace);
+
+    static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
+            SkColorType decodeColorType);
 };
 
 class HeapAllocator : public SkBRDAllocator {
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index d0b07d0..86c97a1 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -42,6 +42,13 @@
     return reinterpret_cast<jlong>(face);
 }
 
+static jlong Typeface_createFromTypefaceWithExactStyle(JNIEnv* env, jobject, jlong nativeInstance,
+        jint weight, jboolean italic) {
+    Typeface* baseTypeface = reinterpret_cast<Typeface*>(nativeInstance);
+    return reinterpret_cast<jlong>(
+            Typeface::createFromTypefaceWithStyle(baseTypeface, weight, italic));
+}
+
 static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
         jobject listOfAxis) {
     std::vector<minikin::FontVariation> variations;
@@ -75,7 +82,13 @@
     return face->fSkiaStyle;
 }
 
-static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) {
+static jint Typeface_getBaseWeight(JNIEnv* env, jobject obj, jlong faceHandle) {
+    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+    return face->fBaseWeight;
+}
+
+static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
+        int weight, int italic) {
     ScopedLongArrayRO families(env, familyArray);
     std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
     familyVec.reserve(families.size());
@@ -83,7 +96,8 @@
         FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
         familyVec.emplace_back(family->family);
     }
-    return reinterpret_cast<jlong>(Typeface::createFromFamilies(std::move(familyVec)));
+    return reinterpret_cast<jlong>(
+            Typeface::createFromFamilies(std::move(familyVec), weight, italic));
 }
 
 static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
@@ -113,12 +127,15 @@
 
 static const JNINativeMethod gTypefaceMethods[] = {
     { "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
+    { "nativeCreateFromTypefaceWithExactStyle", "(JIZ)J",
+            (void*)Typeface_createFromTypefaceWithExactStyle },
     { "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
             (void*)Typeface_createFromTypefaceWithVariation },
     { "nativeCreateWeightAlias",  "(JI)J", (void*)Typeface_createWeightAlias },
     { "nativeUnref",              "(J)V",  (void*)Typeface_unref },
     { "nativeGetStyle",           "(J)I",  (void*)Typeface_getStyle },
-    { "nativeCreateFromArray",    "([J)J",
+    { "nativeGetBaseWeight",      "(J)I",  (void*)Typeface_getBaseWeight },
+    { "nativeCreateFromArray",    "([JII)J",
                                            (void*)Typeface_createFromArray },
     { "nativeSetDefault",         "(J)V",   (void*)Typeface_setDefault },
     { "nativeGetSupportedAxes",   "(J)[I",  (void*)Typeface_getSupportedAxes },
diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp
index 1001c05..33bbdc4 100644
--- a/core/jni/android/graphics/pdf/PdfRenderer.cpp
+++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp
@@ -83,8 +83,6 @@
     SkBitmap skBitmap;
     GraphicsJNI::getSkBitmap(env, jbitmap, &skBitmap);
 
-    SkAutoLockPixels alp(skBitmap);
-
     const int stride = skBitmap.width() * 4;
 
     FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(skBitmap.width(), skBitmap.height(),
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index d4735ec..1370e61 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -739,7 +739,6 @@
     int err = checkFormat(colorType, internalformat, type);
     if (err)
         return err;
-    bitmap.lockPixels();
     const int w = bitmap.width();
     const int h = bitmap.height();
     const void* p = bitmap.getPixels();
@@ -766,7 +765,6 @@
         glTexImage2D(target, level, internalformat, w, h, border, internalformat, type, p);
     }
 error:
-    bitmap.unlockPixels();
     return err;
 }
 
@@ -785,12 +783,10 @@
     int err = checkFormat(colorType, format, type);
     if (err)
         return err;
-    bitmap.lockPixels();
     const int w = bitmap.width();
     const int h = bitmap.height();
     const void* p = bitmap.getPixels();
     glTexSubImage2D(target, level, xoffset, yoffset, w, h, format, type, p);
-    bitmap.unlockPixels();
     return 0;
 }
 
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 520302e..2c7174d 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -24,6 +24,7 @@
 #include <ScopedLocalRef.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <vndk/hardware_buffer.h>
 #include <sensor/Sensor.h>
 #include <sensor/SensorEventQueue.h>
 #include <sensor/SensorManager.h>
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
new file mode 100644
index 0000000..9491a1e
--- /dev/null
+++ b/core/jni/android_os_VintfObject.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "VintfObject"
+//#define LOG_NDEBUG 0
+
+#include <JNIHelp.h>
+#include <vintf/VintfObject.h>
+#include <vintf/parse_xml.h>
+
+#include "core_jni_helpers.h"
+
+namespace android {
+
+using vintf::HalManifest;
+using vintf::RuntimeInfo;
+using vintf::VintfObject;
+using vintf::gHalManifestConverter;
+
+static jstring android_os_VintfObject_getDeviceManifest(JNIEnv* env, jclass clazz)
+{
+    const HalManifest *manifest = VintfObject::GetDeviceHalManifest();
+    if (manifest == nullptr) {
+        return nullptr;
+    }
+    std::string xml = gHalManifestConverter(*manifest);
+    return env->NewStringUTF(xml.c_str());
+}
+
+static jstring android_os_VintfObject_getFrameworkManifest(JNIEnv* env, jclass clazz)
+{
+    const HalManifest *manifest = VintfObject::GetFrameworkHalManifest();
+    if (manifest == nullptr) {
+        return nullptr;
+    }
+    std::string xml = gHalManifestConverter(*manifest);
+    return env->NewStringUTF(xml.c_str());
+}
+
+static jint android_os_VintfObject_verify(JNIEnv *env, jclass clazz, jobjectArray packageInfo) {
+    size_t count = env->GetArrayLength(packageInfo);
+    std::vector<std::string> cPackageInfo{count};
+    for (size_t i = 0; i < count; ++i) {
+        jstring element = (jstring)env->GetObjectArrayElement(packageInfo, i);
+        const char *cString = env->GetStringUTFChars(element, NULL /* isCopy */);
+        cPackageInfo[i] = cString;
+        env->ReleaseStringUTFChars(element, cString);
+    }
+    int32_t status = VintfObject::CheckCompatibility(cPackageInfo);
+    return status;
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod gVintfObjectMethods[] = {
+    {"getDeviceManifest",    "()Ljava/lang/String;",   (void*)android_os_VintfObject_getDeviceManifest},
+    {"getFrameworkManifest", "()Ljava/lang/String;",   (void*)android_os_VintfObject_getFrameworkManifest},
+    {"verify",               "([Ljava/lang/String;)I", (void*)android_os_VintfObject_verify},
+};
+
+const char* const kVintfObjectPathName = "android/os/VintfObject";
+
+int register_android_os_VintfObject(JNIEnv* env)
+{
+    return RegisterMethodsOrDie(env, kVintfObjectPathName, gVintfObjectMethods,
+            NELEM(gVintfObjectMethods));
+}
+
+};
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index abcd1e7..de67c50 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -192,18 +192,12 @@
 
     if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) {
         /*
-         * It's an Error: Reraise the exception, detach this thread, and
-         * wait for the fireworks. Die even more blatantly after a minute
-         * if the gentler attempt doesn't do the trick.
-         *
-         * The GetJavaVM function isn't on the "approved" list of JNI calls
-         * that can be made while an exception is pending, so we want to
-         * get the VM ptr, throw the exception, and then detach the thread.
+         * It's an Error: Reraise the exception and ask the runtime to abort.
          */
         env->Throw(excep);
+        ALOGE("java.lang.Error thrown during binder transaction (stack trace follows) : ");
         env->ExceptionDescribe();
-        ALOGE("Forcefully exiting");
-        exit(1);
+        env->FatalError("java.lang.Error thrown during binder transaction.");
     }
 
 bail:
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index dc365b4..8b82314 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -289,6 +289,14 @@
     }
 }
 
+static void nativeSetRelativeLayer(JNIEnv* env, jclass clazz, jlong nativeObject,
+        jobject relativeTo, jint zorder) {
+    auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    sp<IBinder> handle = ibinderForJavaObject(env, relativeTo);
+
+    ctrl->setRelativeLayer(handle, zorder);
+}
+
 static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat x, jfloat y) {
     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
     status_t err = ctrl->setPosition(x, y);
@@ -774,6 +782,8 @@
             (void*)nativeSetAnimationTransaction },
     {"nativeSetLayer", "(JI)V",
             (void*)nativeSetLayer },
+    {"nativeSetRelativeLayer", "(JLandroid/os/IBinder;I)V",
+            (void*)nativeSetRelativeLayer },
     {"nativeSetPosition", "(JFF)V",
             (void*)nativeSetPosition },
     {"nativeSetGeometryAppliesWithResize", "(J)V",
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 1ac05f9..d0ce192 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -403,7 +403,6 @@
         SkPixelRef* ref = (SkPixelRef*)(_env->GetLongField(surface,
                 gSurface_NativePixelRefFieldID));
         if (ref) {
-            ref->unlockPixels();
             SkSafeUnref(ref);
         }
     }
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index a2f07d9..2042bf62 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -21,10 +21,14 @@
 
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 import "frameworks/base/core/proto/android/service/appwidget.proto";
+import "frameworks/base/core/proto/android/service/battery.proto";
 import "frameworks/base/core/proto/android/service/graphicsstats.proto";
 import "frameworks/base/core/proto/android/service/fingerprint.proto";
+import "frameworks/base/core/proto/android/service/diskstats.proto";
 import "frameworks/base/core/proto/android/service/netstats.proto";
 import "frameworks/base/core/proto/android/service/notification.proto";
+import "frameworks/base/core/proto/android/service/package.proto";
+import "frameworks/base/core/proto/android/service/power.proto";
 import "frameworks/base/core/proto/android/providers/settings.proto";
 
 package android.os;
@@ -57,6 +61,10 @@
     android.service.NetworkStatsServiceDumpProto netstats = 3001;
     android.providers.settings.SettingsServiceDumpProto settings = 3002;
     android.service.appwidget.AppWidgetServiceDumpProto appwidget = 3003;
+    android.service.battery.BatteryServiceDumpProto battery = 3006;
+    android.service.diskstats.DiskStatsServiceDumpProto diskstats = 3007;
     android.service.notification.NotificationServiceDumpProto notification = 3004;
+    android.service.pm.PackageServiceDumpProto package = 3008;
+    android.service.power.PowerServiceDumpProto power = 3009;
     android.service.GraphicsStatsServiceDumpProto graphicsstats = 3005;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3360e33..31586d4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -37,6 +37,7 @@
     <protected-broadcast android:name="android.intent.action.BOOT_COMPLETED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_INSTALL" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_ADDED" />
+    <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_ADDED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_REPLACED" />
     <protected-broadcast android:name="android.intent.action.MY_PACKAGE_REPLACED" />
     <protected-broadcast android:name="android.intent.action.PACKAGE_REMOVED" />
@@ -492,7 +493,9 @@
     <protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
 
     <protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
+    <protected-broadcast android:name="android.accounts.action.ACCOUNT_REMOVED" />
     <protected-broadcast android:name="android.accounts.action.VISIBLE_ACCOUNTS_CHANGED" />
+
     <protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
 
     <protected-broadcast android:name="com.android.phone.SIP_INCOMING_CALL" />
@@ -536,6 +539,7 @@
     <protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT" />
     <protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED" />
     <protected-broadcast android:name="android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
+    <protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
 
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
@@ -1523,6 +1527,16 @@
     <permission android:name="android.permission.DVB_DEVICE"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by carrier state
+         @hide <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"
+        android:protectionLevel="signature|privileged" />
+
+    <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by user state
+         @hide <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"
+        android:protectionLevel="signature|privileged" />
+
     <!-- @SystemApi Allows reading the OEM unlock state
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.READ_OEM_UNLOCK_STATE"
@@ -3563,6 +3577,11 @@
                 android:process=":ui">
         </activity>
 
+        <activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity"
+                  android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"
+                  android:excludeFromRecents="true">
+        </activity>
+
         <receiver android:name="com.android.server.BootReceiver"
                 android:systemUserOnly="true">
             <intent-filter android:priority="1000">
diff --git a/core/res/res/drawable-hdpi/ic_accessibility_magnification.png b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..a91bc6e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_accessibility_magnification.png b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..9ec5107
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..0b3a32e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..3eeb1c9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png
new file mode 100755
index 0000000..7d37612
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/ic_accessibility_magnification.png
Binary files differ
diff --git a/core/res/res/drawable/ic_corp_badge.xml b/core/res/res/drawable/ic_corp_badge.xml
deleted file mode 100644
index 8917431..0000000
--- a/core/res/res/drawable/ic_corp_badge.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="20.0dp"
-        android:height="20.0dp"
-        android:viewportWidth="20.0"
-        android:viewportHeight="20.0">
-    <path
-        android:pathData="M10.0,10.0m-10.0,0.0a10.0,10.0 0.0,1.0 1.0,20.0 0.0a10.0,10.0 0.0,1.0 1.0,-20.0 0.0"
-        android:fillColor="#FF5722"/>
-    <path
-        android:pathData="M15.2,6.2L4.8,6.2c-0.5,0.0 -0.9,0.4 -0.9,1.0L3.9,10.0c0.0,0.5 0.4,1.0 0.9,1.0l3.8,0.0l0.0,-1.0l2.9,0.0l0.0,1.0l3.8,0.0c0.5,0.0 1.0,-0.4 1.0,-1.0L16.3,7.1C16.2,6.6 15.8,6.2 15.2,6.2z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M8.6,12.9l0.0,-1.0L4.3,11.9l0.0,2.4c0.0,0.5 0.4,0.9 0.9,0.9l9.5,0.0c0.5,0.0 0.9,-0.4 0.9,-0.9l0.0,-2.4l-4.3,0.0l0.0,1.0L8.6,12.9z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M7.1,5.2l0.0,1.0 1.0,0.0 0.0,-1.0 3.799999,0.0 0.0,1.0 1.0,0.0 0.0,-1.0 -1.0,-0.9 -3.799999,0.0z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml b/core/res/res/drawable/ic_instant_icon_badge_bolt.xml
similarity index 60%
copy from packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
copy to core/res/res/drawable/ic_instant_icon_badge_bolt.xml
index e267d25..08512b7 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
+++ b/core/res/res/drawable/ic_instant_icon_badge_bolt.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,12 +14,16 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:width="64.0dp"
+        android:height="64.0dp"
+        android:viewportWidth="64.0"
+        android:viewportHeight="64.0">
+
+    <!--
+     The path is similar to ic_corp_icon_badge_case, such that it positions on top of
+     ic_corp_icon_badge_shadow.
+    -->
     <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
+        android:pathData="M43.9 50.9h4v8l6-12h-4v-8l-6 12z"
+        android:fillColor="#757575"/>
 </vector>
diff --git a/core/res/res/drawable/ic_picture_in_picture.xml b/core/res/res/drawable/ic_picture_in_picture.xml
new file mode 100644
index 0000000..e2dda33
--- /dev/null
+++ b/core/res/res/drawable/ic_picture_in_picture.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M19 11h-8v6h8v-6zm4 8V4.98C23 3.88 22.1 3 21 3H3c-1.1 0-2 .88-2 1.98V19c0 1.1 .9
+2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H3V4.97h18v14.05z" />
+    <path
+        android:pathData="M0 0h24v24H0V0z" />
+</vector>
\ No newline at end of file
diff --git a/core/res/res/layout/accessibility_button_chooser.xml b/core/res/res/layout/accessibility_button_chooser.xml
index 0ef785f..480defb 100644
--- a/core/res/res/layout/accessibility_button_chooser.xml
+++ b/core/res/res/layout/accessibility_button_chooser.xml
@@ -19,7 +19,7 @@
 <com.android.internal.widget.ResolverDrawerLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_height="wrap_content"
     android:maxWidth="@dimen/resolver_max_width"
     android:maxCollapsedHeight="256dp"
     android:maxCollapsedHeightSmall="56dp"
@@ -27,11 +27,14 @@
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alwaysShow="true"
         android:orientation="vertical"
         android:background="?attr/colorBackground"
         android:paddingTop="8dp"
-        android:paddingBottom="8dp">
+        android:paddingBottom="8dp"
+        android:paddingStart="?attr/dialogPreferredPadding"
+        android:paddingEnd="?attr/dialogPreferredPadding">
 
         <TextView
             android:layout_width="match_parent"
@@ -41,8 +44,6 @@
             android:text="@string/accessibility_button_prompt_text"
             android:gravity="start|center_vertical"
             android:layout_alignParentStart="true"
-            android:paddingStart="?attr/dialogPreferredPadding"
-            android:paddingEnd="?attr/dialogPreferredPadding"
             android:paddingTop="8dp"
             android:paddingBottom="8dp"/>
 
@@ -55,20 +56,15 @@
             android:verticalSpacing="10dp"
             android:horizontalSpacing="10dp"
             android:stretchMode="columnWidth"
-            android:paddingStart="?attr/dialogPreferredPadding"
-            android:paddingEnd="?attr/dialogPreferredPadding"
             android:gravity="center"/>
 
         <TextView
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:id="@+id/accessibility_button_prompt"
-            android:layout_alwaysShow="true"
             android:textAppearance="?attr/textAppearanceMedium"
             android:text="@string/accessibility_button_instructional_text"
             android:gravity="start|center_vertical"
-            android:paddingStart="?attr/dialogPreferredPadding"
-            android:paddingEnd="?attr/dialogPreferredPadding"
             android:paddingTop="8dp"
             android:paddingBottom="8dp"
             android:visibility="gone"/>
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index 5a835b7..528efca 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -15,6 +15,7 @@
 -->
 
 <FrameLayout  xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/autofill_dataset_picker"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     style="@style/AutofillDatasetPicker">
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 3359b5d..2155c8f 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Inhoud kan nie outomaties ingevul word nie"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Stoor na <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Stoor <xliff:g id="TYPE">%1$s</xliff:g> na <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> in <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Stoor"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nee, dankie"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"wagwoord"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 8e247aeb..41a0153 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ይዘቶች በራስ-ሰር ሊሞሉ አይችሉም"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"ወደ <xliff:g id="LABEL">%1$s</xliff:g> ይቀመጥ?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ወደ <xliff:g id="LABEL">%2$s</xliff:g> ይቀመጥ?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> ወደ <xliff:g id="LABEL">%3$s</xliff:g> ይቀመጡ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g>፣ <xliff:g id="TYPE_2">%3$s</xliff:g> ወደ <xliff:g id="LABEL">%4$s</xliff:g> ይቀመጡ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"አስቀምጥ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"አይ፣ አመሰግናለሁ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"የይለፍ ቃል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9c42197..570e3c4 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1859,10 +1859,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"يتعذر إجراء ملء تلقائي للمحتويات"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"هل تريد الحفظ في <xliff:g id="LABEL">%1$s</xliff:g>؟"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"هل تريد حفظ <xliff:g id="TYPE">%1$s</xliff:g> في <xliff:g id="LABEL">%2$s</xliff:g>؟"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> في <xliff:g id="LABEL">%3$s</xliff:g>؟"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g> في <xliff:g id="LABEL">%4$s</xliff:g>؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"حفظ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"لا، شكرًا"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"كلمة مرور"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index c2a0690..6da988a 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Kontentlər avtomatik olaraq doldurula bilməz"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> etiketində yadda saxlanılsın?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> etiketində yadda saxlanılsın?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> <xliff:g id="LABEL">%3$s</xliff:g> etiketində yadda saxlanılsın?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> <xliff:g id="LABEL">%4$s</xliff:g> etiketində yadda saxlanılsın?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Yadda saxlayın"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Xeyr, çox sağ olun"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"parol"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index a406bcb..86bb518 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1766,10 +1766,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sadržaj ne može automatski da se popuni"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Želite li da sačuvate u: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li da sačuvate stavku <xliff:g id="TYPE">%1$s</xliff:g> u: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> u <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"lozinka"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 10efa13..2702b13 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Для гэтага змесціва аўтазапаўненне немагчымае"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Захаваць у <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Захаваць наступнае: <xliff:g id="TYPE">%1$s</xliff:g> у <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Захаваць <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> у <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Захаваць <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> у <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Захаваць"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, дзякуй"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"пароль"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index ed3fb22..cfb8177 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Съдържанието не може да бъде попълнено автоматично"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Да се запази ли в/ъв „<xliff:g id="LABEL">%1$s</xliff:g>“?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> да се запази ли в/ъв „<xliff:g id="LABEL">%2$s</xliff:g>“?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Искате ли да запазите <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> в/ъв „<xliff:g id="LABEL">%3$s</xliff:g>“?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Искате ли да запазите <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> в/ъв „<xliff:g id="LABEL">%4$s</xliff:g>“?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Запазване"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, благодаря"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"Паролата"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 6dfd7bb..83db42c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1733,8 +1733,7 @@
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"সময় ইনপুট দেওয়ার জন্য পাঠ্য ইনপুট মোডে যান।"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"সময় ইনপুট দেওয়ার জন্য ঘড়ি মোডে যান।"</string>
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"আপনাআপনি পূরণ করার বিকল্পগুলি"</string>
-    <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
-    <skip />
+    <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"বিষয়বস্তুগুলি অটো-ফিল করা যাবে না"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> এ সংরক্ষণ করবেন?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> এ <xliff:g id="TYPE">%1$s</xliff:g> সংরক্ষণ করবেন?"</string>
     <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 9334766..6b8fa78 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1772,10 +1772,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sadržaje nije moguće automatski popuniti"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Želite li sačuvati u: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li sačuvati stavku <xliff:g id="TYPE">%1$s</xliff:g> u: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Želite li <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> sačuvati u <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Želite li <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> sačuvati u <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"lozinka"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index f0b4a08..0a63cdf 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"El contingut no es pot emplenar automàticament"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Vols desar-ho a <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vols desar la informació del camp <xliff:g id="TYPE">%1$s</xliff:g> a <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vols desar la informació dels camps <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vols desar la informació dels camps <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Desa"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gràcies"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"contrasenya"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 306a393..0b9b95d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Obsah nelze automaticky vyplnit"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Uložit do služby <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Uložit položku <xliff:g id="TYPE">%1$s</xliff:g> do služby <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Má se <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> uložit do služby <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Má se <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> uložit do služby <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Uložit"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, děkuji"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"heslo"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 962a089..1708834 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Indhold kan ikke udfyldes automatisk"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Skal indholdet gemmes i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Skal <xliff:g id="TYPE">%1$s</xliff:g> gemmes i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> til <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> til <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gem"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nej tak"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"adgangskode"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f743f7d..6e930ff 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Inhalte können nicht automatisch ausgefüllt werden"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"In <xliff:g id="LABEL">%1$s</xliff:g> speichern?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> in <xliff:g id="LABEL">%2$s</xliff:g> speichern?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"\"<xliff:g id="TYPE_0">%1$s</xliff:g>\" und \"<xliff:g id="TYPE_1">%2$s</xliff:g>\" in \"<xliff:g id="LABEL">%3$s</xliff:g>\" speichern?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"\"<xliff:g id="TYPE_0">%1$s</xliff:g>\", \"<xliff:g id="TYPE_1">%2$s</xliff:g>\" und \"<xliff:g id="TYPE_2">%3$s</xliff:g>\" in \"<xliff:g id="LABEL">%4$s</xliff:g>\" speichern?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Speichern"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nein danke"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"Passwort"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index ec49827..99fa2e5 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Δεν είναι δυνατή η αυτόματη συμπλήρωση των περιεχομένων"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Αποθήκευση σε <xliff:g id="LABEL">%1$s</xliff:g>;"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Αποθήκευση <xliff:g id="TYPE">%1$s</xliff:g> σε <xliff:g id="LABEL">%2$s</xliff:g>;"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> σε <xliff:g id="LABEL">%3$s</xliff:g>;"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> σε <xliff:g id="LABEL">%4$s</xliff:g>;"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Αποθήκευση"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Όχι, ευχαριστώ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"κωδικός πρόσβασης"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index e59892c..0a6a7d5 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Contents can’t be auto-filled"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> to <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> to <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index e59892c..0a6a7d5 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Contents can’t be auto-filled"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> to <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> to <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index e59892c..0a6a7d5 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Contents can’t be auto-filled"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Save to <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Save <xliff:g id="TYPE">%1$s</xliff:g> to <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> to <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> to <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No thanks"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index e764a19..df55b6c 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"El contenido no puede autocompletarse"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"¿Quieres guardar el contenido en <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"¿Quieres guardar el contenido de <xliff:g id="TYPE">%1$s</xliff:g> en <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"contraseña"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 67c5372..c46146d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"El contenido no se puede autocompletar"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"¿Guardar en <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"¿Guardar <xliff:g id="TYPE">%1$s</xliff:g> en <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"contraseña"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index e18f177..4bd9ef8 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sisu ei saa automaatselt täita"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Kas salvestada sildiga <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Kas salvestada <xliff:g id="TYPE">%1$s</xliff:g> sildiga <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Kas salvestada <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> teenusesse <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Kas salvestada <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> teenusesse <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvesta"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Tänan, ei"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"parool"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 5c2d409..5c1b423ca 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -307,7 +307,7 @@
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"birbideratu irteerako deiak"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Irteerako deian markatutako zenbakia ikustea baimentzen die aplikazioei, deia beste zenbaki batera birbideratzeko edo deia bertan behera uzteko aukerarekin."</string>
     <string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"erantzun telefono-deiak"</string>
-    <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"Sarrerako deiak hartzea baimentzen dio aplikazioari."</string>
+    <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"Sarrerako deiak hartzea baimentzen die aplikazioei."</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"jaso testu-mezuak (SMSak)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"jaso testu-mezuak (MMSak)"</string>
@@ -405,9 +405,9 @@
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"irakurri telefonoaren egoera eta identitatea"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Gailuaren telefono-eginbideak atzitzeko baimena ematen die aplikazioei. Baimen horrek aplikazioari telefono-zenbakia eta gailu IDak zein diren, deirik aktibo dagoen eta deia zer zenbakirekin konektatuta dagoen zehazteko baimena ematen die aplikazioei."</string>
     <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"bideratu deiak sistemaren bidez"</string>
-    <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Deiak sistemaren bidez bideratzea baimentzen dio aplikazioari, deien zerbitzua ahal bezain ona izan dadin."</string>
+    <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Deiak sistemaren bidez bideratzea baimentzen die aplikazioei, deien zerbitzua ahal bezain ona izan dadin."</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"irakurri telefono-zenbakiak"</string>
-    <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Gailuaren telefono-zenbakiak atzitzea baimentzen dio aplikazioari."</string>
+    <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Gailuaren telefono-zenbakiak atzitzea baimentzen die aplikazioei."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"eragotzi tableta inaktibo ezartzea"</string>
     <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"eragotzi telebista inaktibo geratzea"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"eragotzi telefonoa inaktibo ezartzea"</string>
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Ezin dira bete automatikoki eremuak"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> zerbitzuan gorde?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> zerbitzuan gorde nahi duzu <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g> gorde nahi dituzu <xliff:g id="LABEL">%3$s</xliff:g> behar denean erabiltzeko?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g> gorde nahi dituzu <xliff:g id="LABEL">%4$s</xliff:g> behar denean erabiltzeko?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gorde"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ez, eskerrik asko"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"pasahitza"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 0cec9f9..7312fa6 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"تکمیل خودکار محتوا ممکن نیست"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"در <xliff:g id="LABEL">%1$s</xliff:g> ذخیره شود؟"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> در <xliff:g id="LABEL">%2$s</xliff:g> ذخیره شود؟"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> در <xliff:g id="LABEL">%3$s</xliff:g> ذخیره شود؟"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g>، <xliff:g id="TYPE_2">%3$s</xliff:g> در <xliff:g id="LABEL">%4$s</xliff:g> ذخیره شود؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ذخیره"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"نه سپاسگزارم"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"گذرواژه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 9384ae5..5d12753 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sisältöä ei voi täyttää automaattisesti."</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Tallennetaanko kohteeseen <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Tallennetaanko <xliff:g id="TYPE">%1$s</xliff:g> kohteeseen <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> palveluun <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> palveluun <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Tallenna"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ei kiitos"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"salasana"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index de4c728..6bcc8ae 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Le contenu ne peut pas être entré automatiquement"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Enregistrer sous <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> sous <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> sous <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> sous <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"mot de passe"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 3db6d83..fdea62a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Le contenu ne peut pas être saisi automatiquement"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Enregistrer dans \"<xliff:g id="LABEL">%1$s</xliff:g>\" ?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Enregistrer \"<xliff:g id="TYPE">%1$s</xliff:g>\" dans \"<xliff:g id="LABEL">%2$s</xliff:g>\" ?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> sur <xliff:g id="LABEL">%3$s</xliff:g> ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> sur <xliff:g id="LABEL">%4$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"mot de passe"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index ee6b7a3..eb220f4 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1186,7 +1186,7 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Mostrando <xliff:g id="NAME">%s</xliff:g> sobre outras aplicacións"</string>
-    <string name="alert_windows_notification_title" msgid="3697657294867638947">"Sobre aplicacións móstrase: <xliff:g id="NAME">%s</xliff:g>"</string>
+    <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> móstrase sobre outras aplicacións"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca para abrir a configuración e desactívaa."</string>
     <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DESACTIVAR"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparando a <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Os contidos non se poden autocompletar"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Queres gardar o contido en: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Queres gardar o contido (<xliff:g id="TYPE">%1$s</xliff:g>) en: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Queres gardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> en: <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Queres gardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> en: <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, grazas"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"contrasinal"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 6b771fd..82481d5 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1733,8 +1733,7 @@
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"સમય દાખલ કરવા માટે ટેક્સ્ટ ઇનપુટ મોડમાં સ્વિચ કરો."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"સમય દાખલ કરવા માટે ઘડિયાળ મોડમાં સ્વિચ કરો."</string>
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"સ્વતઃભરણના વિકલ્પો"</string>
-    <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
-    <skip />
+    <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"કન્ટેન્ટ સ્વતઃ ભરી શકાતું નથી"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> માં સાચવીએ?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ને <xliff:g id="LABEL">%2$s</xliff:g> માં સાચવીએ?"</string>
     <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1febb08..5e7edfa 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"सामग्रियां ऑटोमैटिक रूप से भरी जा सकती हैं"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> में सहेजें?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> को <xliff:g id="LABEL">%2$s</xliff:g> में सहेजें?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> को <xliff:g id="LABEL">%3$s</xliff:g> में सहेजें?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> को <xliff:g id="LABEL">%4$s</xliff:g> में सहेजें?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"सहेजें"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"नहीं, धन्यवाद"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a25c976..d95f8c8 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1766,10 +1766,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Sadržaj se ne može automatski popuniti"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Želi te li to spremiti u aplikaciju <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Želite li spremiti <xliff:g id="TYPE">%1$s</xliff:g> u aplikaciju <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Želite li spremiti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> u <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Želite li spremiti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> u <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Spremi"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"zaporku"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 822f740..9e5c53e 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"A tartalmakat nem lehet automatikusan kitölteni"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Menti ide: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> mentése ide: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Menti a(z) <xliff:g id="LABEL">%3$s</xliff:g> szolgáltatásba a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Menti a(z) <xliff:g id="LABEL">%4$s</xliff:g> szolgáltatásba a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Mentés"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nem, köszönöm"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"jelszó"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 7a91c68..d6a75d57 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Բովանդակության ինքնալրացումը հնարավոր չէ"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Պահե՞լ <xliff:g id="LABEL">%1$s</xliff:g>-ում։"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Պահե՞լ <xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g>-ում։"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Պահե՞լ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> տվյալները <xliff:g id="LABEL">%3$s</xliff:g>-ում։"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Պահե՞լ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> տվյալները <xliff:g id="LABEL">%4$s</xliff:g>-ում։"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Պահել"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ոչ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"գաղտնաբառ"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 91689b8..cd4e63e 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Konten tidak dapat diisi otomatis"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Simpan ke <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ke <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ke <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Lain kali"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"sandi"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 357e5d9..d87725e 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Ekki er hægt að fylla innihald út sjálfkrafa"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Vista í <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vista <xliff:g id="TYPE">%1$s</xliff:g> í <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> á <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> á <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Vista"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nei, takk"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"aðgangsorð"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 05af7cf..06850c8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1185,7 +1185,7 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"App <xliff:g id="NAME">%s</xliff:g> visualizzata sopra altre app"</string>
-    <string name="alert_windows_notification_title" msgid="3697657294867638947">"App <xliff:g id="NAME">%s</xliff:g> visualiz. sopra altre app"</string>
+    <string name="alert_windows_notification_title" msgid="3697657294867638947">"App <xliff:g id="NAME">%s</xliff:g> mostrata sopra altre app"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string>
     <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"DISATTIVA"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"Preparazione della <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Impossibile compilare automaticamente i contenuti"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Salvare in <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvare <xliff:g id="TYPE">%1$s</xliff:g> in <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Salvare <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> su <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Salvare <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> su <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salva"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, grazie"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index fe61600..846ce56 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"לא ניתן למלא את התוכן באופן אוטומטי"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"לשמור ב-<xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"לשמור <xliff:g id="TYPE">%1$s</xliff:g> ב-<xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"לשמור את <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ב-<xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"לשמור את <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ב-<xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"שמור"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"לא, תודה"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"סיסמה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 071bc0b..f627b22 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"コンテンツを自動入力できません"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> に保存しますか?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>を <xliff:g id="LABEL">%2$s</xliff:g> に保存しますか?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>を <xliff:g id="LABEL">%3$s</xliff:g> に保存しますか?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を <xliff:g id="LABEL">%4$s</xliff:g> に保存しますか?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"はい"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"いいえ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"パスワード"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 0fce14b..6157f6b 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"კონტენტის ავტომატური შევსება ვერ მოხერხდება"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"გსურთ „<xliff:g id="LABEL">%1$s</xliff:g>“-ში შენახვა?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"გსურთ, შეინახოთ <xliff:g id="TYPE">%1$s</xliff:g> „<xliff:g id="LABEL">%2$s</xliff:g>“-ში?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"გსურთ, <xliff:g id="LABEL">%3$s</xliff:g>-ში შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"გსურთ, <xliff:g id="LABEL">%4$s</xliff:g>-ში შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"შენახვა"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"არა, გმადლობთ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"პაროლი"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index c3f0b1d..bf7fdf6 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Мазмұндар автотолтырылмайды"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> жүйесінде сақталсын ба?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> деректері <xliff:g id="LABEL">%2$s</xliff:g> жүйесінде сақталсын ба?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> <xliff:g id="LABEL">%3$s</xliff:g> ішіне сақтау керек пе?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> <xliff:g id="LABEL">%4$s</xliff:g> ішіне сақтау керек пе?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сақтау"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Жоқ, рақмет"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"құпия сөз"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 236e201..7e97f95 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1737,10 +1737,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"មិនអាច​បំពេញ​មាតិកា​ដោយស្វ័យប្រវត្តិ​បានទេ"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"រក្សា​ទុក​ទៅ​ក្នុង <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"រក្សាទុក <xliff:g id="TYPE">%1$s</xliff:g> ​ទៅ​ក្នុង <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"រក្សាទុក <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ទៅក្នុង <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"រក្សាទុក <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ទៅក្នុង <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"រក្សាទុក"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ទេ អរគុណ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"ពាក្យ​សម្ងាត់"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index b93f188..94f4df8 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1733,14 +1733,11 @@
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ಸಮಯವನ್ನು ನಮೂದಿಸಲು ಪಠ್ಯದ ನಮೂನೆಗೆ ಬದಲಿಸಿ."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ಸಮಯವನ್ನು ನಮೂದಿಸಲು ಗಡಿಯಾರದ ನಮೂನೆಗೆ ಬದಲಿಸಿ."</string>
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ಸ್ವಯಂತುಂಬುವಿಕೆ ಆಯ್ಕೆಗಳು"</string>
-    <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
-    <skip />
+    <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ವಿಷಯಗಳು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಭರ್ತಿಯಾಗಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> ನಲ್ಲಿ ಉಳಿಸಬೇಕೆ?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು <xliff:g id="LABEL">%2$s</xliff:g> ನಲ್ಲಿ ಉಳಿಸಬೇಕೆ?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು <xliff:g id="LABEL">%3$s</xliff:g>ಗೆ ಉಳಿಸಬೇಕೆ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ಅನ್ನು <xliff:g id="LABEL">%4$s</xliff:g> ಗೆ ಉಳಿಸಬೇಕೆ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ಉಳಿಸಿ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ಬೇಡ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"ಪಾಸ್‌ವರ್ಡ್"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8133d13..a24eb06 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"콘텐츠를 자동완성할 수 없습니다."</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>에 저장하시겠습니까?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>을(를) <xliff:g id="LABEL">%2$s</xliff:g>에 저장하시겠습니까?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="LABEL">%3$s</xliff:g>에 <xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) 저장하시겠습니까?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="LABEL">%4$s</xliff:g>에 <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> 및 <xliff:g id="TYPE_2">%3$s</xliff:g>을(를) 저장하시겠습니까?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"저장"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"사용 안함"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"비밀번호"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index fc9c943..f4d15aa 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Мазмундарды автотолтуруу мүмкүн эмес"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> кызматында сакталсынбы?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> кызматында сакталсынбы?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g> менен <xliff:g id="TYPE_1">%2$s</xliff:g> <xliff:g id="LABEL">%3$s</xliff:g> кызматында сакталсынбы?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g> <xliff:g id="LABEL">%4$s</xliff:g> кызматында сакталсынбы?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сактоо"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Жок, рахмат"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"сырсөз"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 2040bdf..e57c851 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ບໍ່ສາມາດຕື່ມຂໍ້ມູນເນື້ອຫາອັດຕະໂນມັດໄດ້"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"ບັນທຶກໄປໃສ່ <xliff:g id="LABEL">%1$s</xliff:g> ບໍ?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"ບັນທຶກ <xliff:g id="TYPE">%1$s</xliff:g> ໄປໃສ່ <xliff:g id="LABEL">%2$s</xliff:g> ບໍ?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ໄປໃສ່ <xliff:g id="LABEL">%3$s</xliff:g> ບໍ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ໄປໃສ່ <xliff:g id="LABEL">%4$s</xliff:g> ບໍ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ບັນທຶກ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ບໍ່, ຂອບໃຈ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"​ລະ​ຫັດ​ຜ່ານ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index c84ab90..e98c66c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Turinio negalima pildyti automatiškai"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Išsaugoti skiltyje „<xliff:g id="LABEL">%1$s</xliff:g>“?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Išsaugoti <xliff:g id="TYPE">%1$s</xliff:g> skiltyje „<xliff:g id="LABEL">%2$s</xliff:g>“?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> sistemoje „<xliff:g id="LABEL">%3$s</xliff:g>“?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> sistemoje „<xliff:g id="LABEL">%4$s</xliff:g>“?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Išsaugoti"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, ačiū"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"slaptažodį"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index f16b129..4251a52 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1766,10 +1766,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Saturu nevar automātiski aizpildīt."</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Vai saglabāt pakalpojumā <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vai saglabāt <xliff:g id="TYPE">%1$s</xliff:g> pakalpojumā <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vai saglabāt informāciju (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) iezīmē <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vai saglabāt informāciju (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) iezīmē <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Saglabāt"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nē, paldies"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"paroli"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index a6e3795..2fb9553 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1738,10 +1738,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Содржините не може автоматски да се пополнат"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Да се зачува во <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Да се зачува <xliff:g id="TYPE">%1$s</xliff:g> во <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> во <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> во <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Зачувај"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, благодарам"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index c9c63d3..8f80f1ad 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1733,14 +1733,11 @@
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"സമയം നൽകുന്നതിന് ടെക്സ്റ്റ് ഇൻപുട്ട് ‌മോ‌ഡിലേക്ക് ‌മാറുക."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"‌സമയം നൽകുന്നതിന് ക്ലോക്ക് മോഡിലേക്ക് ‌മാറുക."</string>
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"സ്വയമേവ പൂരിപ്പിക്കൽ ഓപ്ഷനുകൾ"</string>
-    <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
-    <skip />
+    <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ഉള്ളടക്കങ്ങൾ സ്വയമേവ പൂരിപ്പിക്കാൻ കഴിയില്ല"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> എന്നിവ <xliff:g id="LABEL">%3$s</xliff:g> എന്നതിൽ സംരക്ഷിക്കട്ടെ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> എന്നിവ <xliff:g id="LABEL">%4$s</xliff:g> എന്നതിൽ സംരക്ഷിക്കട്ടെ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"സംരക്ഷിക്കുക"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"വേണ്ട, നന്ദി"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"പാസ്‌വേഡ്"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index fb842b2..88aacdae 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1733,10 +1733,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Агуулгыг автоматаар бөглөх боломжгүй"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>-д хадгалах уу?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>-г <xliff:g id="LABEL">%2$s</xliff:g>-д хадгалах уу?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>-г <xliff:g id="LABEL">%3$s</xliff:g>-д хадгалах уу?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>-г <xliff:g id="LABEL">%4$s</xliff:g>-д хадгалах уу?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Хадгалах"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Үгүй, баярлалаа"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"нууц үг"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 538d626..4769676 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1733,8 +1733,7 @@
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"वेळ इनपुटसाठी मजकूर इनपुट मोडवर स्विच करा."</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"वेळ इनपुटसाठी घड्याळ मोडवर स्विच करा."</string>
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"स्वयं-भरण पर्याय"</string>
-    <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
-    <skip />
+    <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"सामग्रींची स्‍वयं-भरणा करता येणार नाही"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> वर जतन करायचे?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="LABEL">%2$s</xliff:g> वर <xliff:g id="TYPE">%1$s</xliff:g> जतन करायचे?"</string>
     <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index ef5883a..e414985 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Kandungan tidak boleh dilengkapkan secara automatik"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Simpan ke <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ke <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ke <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Tidak, terima kasih"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"kata laluan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index ad0602e..5252422 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1186,7 +1186,7 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> သည် အခြားအက်ပ်များအပေါ်တွင် ပြပါသည်"</string>
-    <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ကအခြားအက်ပ်ပေါ်တွင် ပြသနေသည်။"</string>
+    <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ကို အခြားအက်ပ်များပေါ်တွင် မြင်နေရပါသည်။"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ကို ဤဝန်ဆောင်မှုအား အသုံးမပြုစေလိုလျှင် ဆက်တင်ကို တို့၍ ဖွင့်ပြီး ၎င်းကို ပိတ်လိုက်ပါ။"</string>
     <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ပိတ်ပါ"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> ပြင်ဆင်နေသည်"</string>
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"အကြောင်းအရာများကို အော်တိုဖြည့်၍မရပါ"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> သို့ သိမ်းဆည်းလိုပါသလား။"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ကို <xliff:g id="LABEL">%2$s</xliff:g> သို့ သိမ်းဆည်းလိုပါသလား။"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g> ကို <xliff:g id="LABEL">%3$s</xliff:g> သို့ သိမ်းဆည်းလိုပါသလား။"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g>၊ <xliff:g id="TYPE_2">%3$s</xliff:g> ကို <xliff:g id="LABEL">%4$s</xliff:g>သို့ သိမ်းဆည်းလိုပါသလား။"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"သိမ်းရန်"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"မလိုပါ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"စကားဝှက်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 974d55f..9c638ec 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Innhold kan ikke fylles ut automatisk"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Vil du lagre i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vil du lagre <xliff:g id="TYPE">%1$s</xliff:g> i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> til <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> til <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Lagre"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nei takk"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"passord"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 9c3ae4c..86c18d6 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1738,14 +1738,11 @@
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"समय इनपुट गर्न पाठ इनपुट मोडमा स्विच गर्नुहोस्।"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"समय इनपुट गर्न घडी मोडमा स्विच गर्नुहोस्।"</string>
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"स्वतः भरणका विकल्पहरू"</string>
-    <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
-    <skip />
+    <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"सामग्रीहरूलाई स्वत: भरण गर्न मिल्दैन"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> लाई <xliff:g id="LABEL">%2$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> लाई <xliff:g id="LABEL">%3$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> लाई <xliff:g id="LABEL">%4$s</xliff:g> मा सुरक्षित गर्ने हो?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"सुरक्षित गर्नुहोस्"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"पर्दैन, धन्यवाद"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"पासवर्ड"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 15c8ff3..af8c0a2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Content kan niet automatisch worden aangevuld"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Opslaan in <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> opslaan in <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> opslaan in <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> opslaan in <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Opslaan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nee, bedankt"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"Wachtwoord"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index ea1194a..71fd285 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1733,14 +1733,11 @@
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"ਸਮਾਂ ਇਨਪੁੱਟ ਕਰਨ ਲਈ ਲਿਖਤ ਇਨਪੁੱਟ ਮੋਡ \'ਤੇ ਬਦਲੀ ਕਰੋ।"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"ਸਮਾਂ ਇਨਪੁੱਟ ਕਰਨ ਲਈ ਘੜੀ ਮੋਡ \'ਤੇ ਬਦਲੀ ਕਰੋ।"</string>
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"ਆਟੋਫਿਲ ਵਿਕਲਪ"</string>
-    <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
-    <skip />
+    <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ਸਮੱਗਰੀਆਂ ਆਟੋਫਿਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ <xliff:g id="LABEL">%2$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ <xliff:g id="LABEL">%3$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ <xliff:g id="LABEL">%4$s</xliff:g> ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"ਪਾਸਵਰਡ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index d7572a0..dee76d5 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Nie można automatycznie uzupełnić treści"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Zapisać w: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Zapisać element <xliff:g id="TYPE">%1$s</xliff:g> w: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Zapisać: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> w: <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Zapisać: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> w: <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Zapisz"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nie, dziękuję"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"hasło"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 1231a8b..2212c06 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher os conteúdos automaticamente"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Salvar em <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"senha"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index c533a03..241b2fe 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher automaticamente o conteúdo"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Pretende guardar no <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Pretende guardar o(a) <xliff:g id="TYPE">%1$s</xliff:g> no <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> no <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> no <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"palavra-passe"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 1231a8b..2212c06 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher os conteúdos automaticamente"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Salvar em <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"senha"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 8a6b349..f347a8e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1766,10 +1766,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Conținutul nu poate fi completat automat"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Salvați în <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Salvați <xliff:g id="TYPE">%1$s</xliff:g> în <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> în <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g> în <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvați"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nu, mulțumesc"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"parolă"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 40fe776..3ac621a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Ошибка автозаполнения"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Сохранить в <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>: сохранить в <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Сохранить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) в \"<xliff:g id="LABEL">%3$s</xliff:g>\"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Сохранить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) в \"<xliff:g id="LABEL">%4$s</xliff:g>\"?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сохранить"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Нет, спасибо"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"Пароль"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index cd4cebdd..6c595fb 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1737,10 +1737,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"අන්තර්ගතය ස්වයං පිරවුම් කළ නොහැකිය"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> වෙත සුරකින්නද?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> වෙත සුරකින්නද?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="LABEL">%3$s</xliff:g> වෙත <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> සුරකින්නද?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="LABEL">%4$s</xliff:g> වෙත <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> සුරකින්නද?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"සුරකින්න"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"එපා ස්තූතියි"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"මුරපදය"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 71411f7..af5268e 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Obsah nie je možné automaticky vyplniť"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Uložiť do zariadenia <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Uložiť <xliff:g id="TYPE">%1$s</xliff:g> do zariadenia <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Uložiť <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Uložiť <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Uložiť"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nie, vďaka"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"heslo"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5b76e79..877add7 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Vsebine ni mogoče samodejno izpolniti"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Shrani v <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Shrani <xliff:g id="TYPE">%1$s</xliff:g> v <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Želite shraniti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> v <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Želite shraniti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> v <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Shrani"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"geslo"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index d26b652..b645553 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Përmbajtjet nuk mund të plotësohen automatikisht"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Të ruhet te <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Të ruhet <xliff:g id="TYPE">%1$s</xliff:g> te <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Të ruhen <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> te <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Të ruhen <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> te <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Ruaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Jo, faleminderit"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"fjalëkalimi"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 15456f8..6e13582 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1766,10 +1766,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Садржај не може аутоматски да се попуни"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Желите ли да сачувате у: <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Желите ли да сачувате ставку <xliff:g id="TYPE">%1$s</xliff:g> у: <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> у <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> у <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сачувај"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, хвала"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"лозинка"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index cf411a0..90dfd681a 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Det gick inte att fylla i innehållet automatiskt"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Vill du spara detta i <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Vill du spara <xliff:g id="TYPE">%1$s</xliff:g> i <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Spara <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Spara <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g> i <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Spara"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nej tack"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"lösenordet"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index e7b12f0..664a038 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1733,10 +1733,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Maudhui hayawezi kujazwa kiotomatiki"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Ungependa kuhifadhi kwenye <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Ungependa kuhifadhi <xliff:g id="TYPE">%1$s</xliff:g> kwenye <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> kwenye <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> kwenye <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Hifadhi"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hapana, asante"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"nenosiri"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index c2b850d..1f81757 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"உள்ளடக்கத்தைத் தானாக நிரப்ப முடியவில்லை"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> இல் சேமிக்கவா?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>ஐ <xliff:g id="LABEL">%2$s</xliff:g> இல் சேமிக்கவா?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ஆகியவற்றை <xliff:g id="LABEL">%3$s</xliff:g> இல் சேமிக்கவா?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ஆகியவற்றை <xliff:g id="LABEL">%4$s</xliff:g> இல் சேமிக்கவா?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"சேமி"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"வேண்டாம்"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"கடவுச்சொல்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 6c489fd..0fb49d5 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"కంటెంట్‌లను స్వీయ పూరింపు చేయడం సాధ్యపడదు"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g>కు సేవ్ చేయాలా?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>ని <xliff:g id="LABEL">%2$s</xliff:g>కు సేవ్ చేయాలా?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>లను <xliff:g id="LABEL">%3$s</xliff:g>కు సేవ్ చేయాలా?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>లను <xliff:g id="LABEL">%4$s</xliff:g>కు సేవ్ చేయాలా?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"సేవ్ చేయి"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"వద్దు, ధన్యవాదాలు"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"పాస్‌వర్డ్"</string>
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index 78eeee9..d62b93e 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -36,4 +36,7 @@
     <!-- The default gravity for the picture-in-picture window.
          Currently, this maps to Gravity.BOTTOM | Gravity.RIGHT -->
     <integer name="config_defaultPictureInPictureGravity">0x55</integer>
+
+    <!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
+    <bool name="config_useDefaultFocusHighlight">false</bool>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 994906b..ed22eef 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"ไม่สามารถป้อนเนื้อหาอัตโนมัติ"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"บันทึกไปยัง <xliff:g id="LABEL">%1$s</xliff:g> ใช่ไหม"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"บันทึก <xliff:g id="TYPE">%1$s</xliff:g> ไปยัง <xliff:g id="LABEL">%2$s</xliff:g> ใช่ไหม"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"บันทึก <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ไปยัง <xliff:g id="LABEL">%3$s</xliff:g> ไหม"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"บันทึก <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ไปยัง <xliff:g id="LABEL">%4$s</xliff:g> ไหม"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"บันทึก"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ไม่เป็นไร"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"รหัสผ่าน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 3e14b14..8b5962f 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Hindi maaaring ma-autofill ang mga content"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"I-save sa <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"I-save ang <xliff:g id="TYPE">%1$s</xliff:g> sa <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> sa <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> sa <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"I-save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hindi, salamat na lang"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"password"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index da4ed4f..7be1384 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"İçerikler otomatik doldurulamıyor"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> hizmetine kaydedilsin mi?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g>, <xliff:g id="LABEL">%2$s</xliff:g> etkinliğine kaydedilsin mi?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g> ve <xliff:g id="TYPE_1">%2$s</xliff:g> bilgileri <xliff:g id="LABEL">%3$s</xliff:g> hizmetine kaydedilsin mi?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g> bilgileri <xliff:g id="LABEL">%4$s</xliff:g> hizmetine kaydedilsin mi?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Kaydet"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hayır, teşekkürler"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"şifre"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index c4f3d44..6c5846d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1797,10 +1797,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Вміст не можна заповнити автоматично"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Зберегти в службі <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Зберегти дані (<xliff:g id="TYPE">%1$s</xliff:g>) у службі <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у службі <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>) у службі <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Зберегти"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ні, дякую"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"пароль"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index c7f533c..ccaa412 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1733,14 +1733,11 @@
     <string name="time_picker_text_input_mode_description" msgid="4148166758173708199">"وقت ان پٹ کے لیے ٹیکسٹ ان پٹ وضع پر سوئچ کریں۔"</string>
     <string name="time_picker_radial_mode_description" msgid="4953403779779557198">"وقت ان پٹ کے لیے گھڑی و‏ضع پر سوئچ کریں۔"</string>
     <string name="autofill_picker_accessibility_title" msgid="8469043291648711535">"آٹو فل کے اختیارات"</string>
-    <!-- no translation found for autofill_error_cannot_autofill (7402758580060110371) -->
-    <skip />
+    <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"موادوں کو آٹو فل نہیں کیا جا سکتا"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> میں محفوظ کریں؟"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> کو <xliff:g id="LABEL">%2$s</xliff:g> میں محفوظ کریں؟"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> کو <xliff:g id="LABEL">%3$s</xliff:g> میں محفوظ کریں؟"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g>، <xliff:g id="TYPE_2">%3$s</xliff:g> کو <xliff:g id="LABEL">%4$s</xliff:g> میں محفوظ کریں؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"محفوظ کریں"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"نہیں، شکریہ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"پاس ورڈ"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 513ef88..ee2438f 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -796,7 +796,7 @@
     <string name="factorytest_failed" msgid="5410270329114212041">"Ishlab chiqarish sinovi amalga oshmadi"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"The FACTORY_TEST amali faqatgina /system/app ichiga o‘rnatilgan paketlar bilan ishlay oladi."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST amalini bajarish uchun birorta ham paket topilmadi."</string>
-    <string name="factorytest_reboot" msgid="6320168203050791643">"O‘chirib-yoqish"</string>
+    <string name="factorytest_reboot" msgid="6320168203050791643">"O‘chirib yoqish"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"\"<xliff:g id="TITLE">%s</xliff:g>\"dagi sahifa buni xabar qilmoqda:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Tasdiqlash"</string>
@@ -1146,7 +1146,7 @@
     <string name="sim_done_button" msgid="827949989369963775">"Tayyor"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"SIM karta qo‘shildi"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Uyali tarmoqqa ulanish uchun qurilmangizni o‘chirib-yoqing."</string>
-    <string name="sim_restart_button" msgid="4722407842815232347">"O‘chirib-yoqish"</string>
+    <string name="sim_restart_button" msgid="4722407842815232347">"O‘chirib yoqish"</string>
     <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Yangi SIM karta to‘g‘ri ishlashi uchun operator ilovasini o‘rnatib, ochish kerak bo‘ladi."</string>
     <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ILOVANI YUKLAB OLING"</string>
     <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"HOZIR EMAS"</string>
@@ -1736,10 +1736,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Kontentlarni avtomatik to‘ldirib bo‘lmaydi"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"<xliff:g id="LABEL">%1$s</xliff:g> xizmatiga saqlansinmi?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"<xliff:g id="TYPE">%1$s</xliff:g> <xliff:g id="LABEL">%2$s</xliff:g> xizmatiga saqlansinmi?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ma’lumotlari <xliff:g id="LABEL">%3$s</xliff:g> yorlig‘iga saqlansinmi?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ma’lumotlari <xliff:g id="LABEL">%4$s</xliff:g> yorlig‘iga saqlansinmi?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Saqlash"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Yo‘q, kerak emas"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"parol"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 6b61b56..c85f413 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Không thể tự động điền nội dung"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Lưu vào <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Lưu <xliff:g id="TYPE">%1$s</xliff:g> vào <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> vào <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> vào <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Lưu"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Không, cảm ơn"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"mật khẩu"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 0202a99..1daecdd 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"无法自动填充内容"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"要保存到<xliff:g id="LABEL">%1$s</xliff:g>吗?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"要将<xliff:g id="TYPE">%1$s</xliff:g>保存到<xliff:g id="LABEL">%2$s</xliff:g>吗?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>保存到<xliff:g id="LABEL">%3$s</xliff:g>吗?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>保存到<xliff:g id="LABEL">%4$s</xliff:g>吗?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"保存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"密码"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index da5c464..902cfea 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"無法自動填入內容"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"要儲存至 <xliff:g id="LABEL">%1$s</xliff:g> 嗎?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存至 <xliff:g id="LABEL">%2$s</xliff:g> 嗎?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>儲存至「<xliff:g id="LABEL">%3$s</xliff:g>」嗎?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>儲存至「<xliff:g id="LABEL">%4$s</xliff:g>」嗎?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"密碼"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index c7146a7..91c5df3 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"無法自動填入內容"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"要儲存到「<xliff:g id="LABEL">%1$s</xliff:g>」嗎?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存到「<xliff:g id="LABEL">%2$s</xliff:g>」嗎?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>儲存到「<xliff:g id="LABEL">%3$s</xliff:g>」嗎?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>儲存到「<xliff:g id="LABEL">%4$s</xliff:g>」嗎?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"密碼"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 540370f..5289834 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1735,10 +1735,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Okuqukethwe akukwazi ukugcwalisa ngokuzenzakalela"</string>
     <string name="autofill_save_title" msgid="7081244500504163245">"Londoloza ku-<xliff:g id="LABEL">%1$s</xliff:g>?"</string>
     <string name="autofill_save_title_with_type" msgid="4977385733042555659">"Londoloza i-<xliff:g id="TYPE">%1$s</xliff:g> ku-<xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <!-- no translation found for autofill_save_title_with_2types (8875796560521962098) -->
-    <skip />
-    <!-- no translation found for autofill_save_title_with_3types (6889899028382843493) -->
-    <skip />
+    <string name="autofill_save_title_with_2types" msgid="8875796560521962098">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ku-<xliff:g id="LABEL">%3$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6889899028382843493">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ku-<xliff:g id="LABEL">%4$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Londoloza"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Cha ngiyabonga"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"iphasiwedi"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 221e736..4fb21fa 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -430,10 +430,9 @@
             <flag name="adjustNothing" value="0x30" />
         </attr>
 
-        <!-- Flag allowing you to disable the preview animation for a window.
-             The default value is false; if set to true, the system can never
-             use the window's theme to show a preview of it before your
-             actual instance is shown to the user. -->
+        <!-- Flag allowing you to disable the splash screen for a window. The default value is
+             false; if set to true, the system can never use the window's theme to show a splash
+             screen before your actual instance is shown to the user. -->
         <attr name="windowDisablePreview" format="boolean" />
 
         <!-- Flag indicating that this window should not be displayed at all.
@@ -1372,6 +1371,22 @@
              Corresponds to
              {@link android.view.inputmethod.EditorInfo#IME_ACTION_PREVIOUS}. -->
         <flag name="actionPrevious" value="0x00000007" />
+        <!-- Used to request that the IME should not update any personalized data such as typing
+             history and personalized language model based on what the user typed on this text
+             editing object. Typical use cases are:
+             <ul>
+                 <li>When the application is in a special mode, where user's activities are expected
+                 to be not recorded in the application's history. Some web browsers and chat
+                 applications may have this kind of modes.</li>
+                 <li>When storing typing history does not make much sense.  Specifying this flag in
+                 typing games may help to avoid typing history from being filled up with words that
+                 the user is less likely to type in their daily life.  Another example is that when
+                 the application already knows that the expected input is not a valid word (e.g. a
+                 promotion code that is not a valid word in any natural language).</li>
+             </ul>
+             <p>Applications need to be aware that the flag is not a guarantee, and some IMEs may
+             not respect it.</p> -->
+        <flag name="flagNoPersonalizedLearning" value="0x1000000" />
         <!-- Used to request that the IME never go
              into fullscreen mode.  Applications need to be aware that the flag is not
              a guarantee, and not all IMEs will respect it.
@@ -2049,6 +2064,17 @@
              Corresponds to setting {@link android.view.View#SYSTEM_UI_FLAG_LIGHT_STATUS_BAR} on
              the decor view. -->
         <attr name="windowLightStatusBar" format="boolean" />
+
+        <!-- Reference to a drawable to be used as the splash screen content of the window. This
+             drawable will be placed on top of the {@link android.R.attr#windowBackground} with its
+             bounds inset by the system bars. If the drawable should not be inset by the system
+             bars, use a fullscreen theme.
+             <p>
+             Note that even if no splashscreen content is set on the theme, the system may still
+             show a splash screen using the other attributes on the theme, like the
+             {@link android.R.attr#windowBackground}.
+             -->
+        <attr name="windowSplashscreenContent" format="reference" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -2294,18 +2320,7 @@
             <enum name="auto" value="0x00000010" />
         </attr>
 
-        <!-- Controls the autofill behavior for this view. -->
-        <attr name="autofillMode">
-            <!-- Inherit the behavior from the parent. If there is no parent it is auto. This is the
-                 default value for this attribute.-->
-            <enum name="inherit" value="0" />
-            <!-- Allows this view to automatically trigger an autofill request when it get focus.
-                 -->
-            <enum name="auto" value="1" />
-            <!-- Do not trigger an autofill request when this view is focused. The user can still
-                 manually force an autofill request for this view. -->
-            <enum name="manual" value="2" />
-        </attr>
+        <attr name="__removed3" />
 
         <!-- Describes the content of a view so that a autofill service can fill in the appropriate
              data. Multiple hints can be combined in a comma separated list or an array of strings
@@ -3217,18 +3232,7 @@
              and subtype in order to provide the consistent user experience in switching
              between IMEs and subtypes. -->
         <attr name="supportsSwitchingToNextInputMethod" format="boolean" />
-        <!-- Set to true if this input method supports ways to dismiss the windows assigned to
-             the input method (for example, a dismiss button rendered by the input method itself).  The
-             System UI may optimize the UI by not showing system-level dismiss button if this
-             value is true.
-             <p> Must be a boolean value, either "true" or "false". The default value is "false".
-             <p> This may also be a reference to a resource (in the form "@[package:]type:name")
-             or theme attribute (in the form "?[package:]type:name") containing a value of this
-             type.
-             <p> A UI element that dismisses the input method window should report
-             {@link android.view.accessibility.AccessibilityNodeInfo#ACTION_DISMISS} action, so
-             that accessibility services can handle it accordingly. -->
-        <attr name="supportsDismissingWindow" format="boolean" />
+        <attr name="__removed2" format="boolean" />
     </declare-styleable>
 
     <!-- This is the subtype of InputMethod. Subtype can describe locales (for example, en_US and
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 3e4b66d7..95ba942 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -322,6 +322,10 @@
          your application running at all times. -->
     <attr name="persistent" format="boolean" />
 
+    <!-- If set, the "persistent" attribute will only be honored if the feature
+         specified here is present on the device. -->
+    <attr name="persistentFeature" format="string" />
+
     <!-- Flag to specify if this application needs to be present for all users. Only pre-installed
          applications can request this feature. Default value is false. -->
     <attr name="requiredForAllUsers" format="boolean" />
@@ -1358,6 +1362,7 @@
              for normal behavior. -->
         <attr name="hasCode" format="boolean" />
         <attr name="persistent" />
+        <attr name="persistentFeature" />
         <attr name="requiredForAllUsers" />
         <!-- Specify whether the components in this application are enabled or not (that is, can be
              instantiated by the system).
@@ -2434,6 +2439,14 @@
         <!-- Whether the given RRO is static or not. -->
         <attr name="isStatic" format="boolean" />
 
+        <!-- Required property name/value pair used to enable this overlay.
+             e.g. name=ro.oem.sku value=MKT210.
+             Overlay will be ignored unless system property exists and is
+             set to specified value -->
+        <!-- @hide @SystemApi This shouldn't be public. -->
+        <attr name="requiredSystemPropertyName" format="string" />
+        <!-- @hide @SystemApi This shouldn't be public. -->
+        <attr name="requiredSystemPropertyValue" format="string" />
     </declare-styleable>
 
     <!-- Declaration of an {@link android.content.Intent} object in XML.  May
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 937fc6f..536906c 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -171,6 +171,9 @@
     <color name="profile_badge_2">#ff000000</color><!-- Black -->
     <color name="profile_badge_3">#ff22f033</color><!-- Green -->
 
+    <!-- Default instant app badge color -->
+    <color name="instant_app_badge">#FFFFFFFF</color><!-- White -->
+
     <!-- Multi-sim sim colors -->
     <color name="Teal_700">#ff00796b</color>
     <color name="Teal_800">#ff00695c</color>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index e0cc5b5..8c37d4b 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -74,10 +74,10 @@
 
     <item name="disabled_alpha_material_light" format="float" type="dimen">0.26</item>
     <item name="disabled_alpha_material_dark" format="float" type="dimen">0.30</item>
-    <item name="primary_content_alpha_material_light" format="float" type="dimen">1</item>
-    <item name="primary_content_alpha_material_dark" format="float" type="dimen">0.87</item>
-    <item name="secondary_content_alpha_material_light" format="float" type="dimen">.7</item>
-    <item name="secondary_content_alpha_material_dark" format="float" type="dimen">0.54</item>
+    <item name="primary_content_alpha_material_dark" format="float" type="dimen">1</item>
+    <item name="primary_content_alpha_material_light" format="float" type="dimen">0.87</item>
+    <item name="secondary_content_alpha_material_dark" format="float" type="dimen">.7</item>
+    <item name="secondary_content_alpha_material_light" format="float" type="dimen">0.54</item>
 
     <item name="highlight_alpha_material_light" format="float" type="dimen">0.12</item>
     <item name="highlight_alpha_material_dark" format="float" type="dimen">0.20</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index aef4c28..6228b4e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -852,6 +852,8 @@
             1 - Go to sleep (doze)
             2 - Really go to sleep (don't doze)
             3 - Really go to sleep and go home (don't doze)
+            4 - Go to home
+            5 - Dismiss IME if shown. Otherwise go to home
     -->
     <integer name="config_shortPressOnPowerBehavior">1</integer>
 
@@ -2833,4 +2835,7 @@
           specified name exists on the device, autofill will be disabled by default.
     -->
     <string name="config_defaultAutofillService" translatable="false"></string>
+
+    <!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
+    <bool name="config_useDefaultFocusHighlight">true</bool>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ed940b3..89c912fd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2785,7 +2785,7 @@
         <public name="focusedByDefault" />
         <public name="appCategory" />
         <public name="autoSizeMaxTextSize" />
-        <public name="supportsDismissingWindow" />
+        <public name="__removed2" />
         <public name="restartOnConfigChanges" />
         <public name="certDigest" />
         <public name="splitName" />
@@ -2797,7 +2797,7 @@
         <public name="numericModifiers" />
         <public name="fontProviderAuthority" />
         <public name="fontProviderQuery" />
-        <public name="autofillMode" />
+        <public name="__removed3" />
         <public name="primaryContentAlpha" />
         <public name="secondaryContentAlpha" />
         <public name="requiredFeature" />
@@ -2815,6 +2815,12 @@
         <public name="maxAspectRatio"/>
         <public name="iconSpaceReserved"/>
         <public name="defaultFocusHighlightEnabled" />
+        <public name="persistentFeature"/>
+        <public name="windowSplashscreenContent" />
+        <!-- @hide @SystemApi -->
+        <public name="requiredSystemPropertyName" />
+        <!-- @hide @SystemApi -->
+        <public name="requiredSystemPropertyValue" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
@@ -2828,13 +2834,13 @@
 
     <public-group type="drawable" first-id="0x010800b4">
         <public name="autofilled_highlight" />
+        <public name="ic_picture_in_picture" />
     </public-group>
 
     <public-group type="string" first-id="0x01040019">
         <public name="paste_as_plain_text" />
     </public-group>
 
-
   <!-- ===============================================================
        DO NOT ADD UN-GROUPED ITEMS HERE
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0821674..bd35073 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3000,6 +3000,8 @@
 
     <!-- Do not translate. Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
+    <!-- Do not translate. Default access point SSID used for local only hotspot -->
+    <string name="wifi_localhotspot_configure_ssid_default" translatable="false">AndroidShare</string>
 
     <!-- A notification is shown the first time a connection is attempted on an app owned AP -->
     <!-- title for this message -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9354679..d0ac79e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -19,6 +19,9 @@
   <!-- Private symbols that we need to reference from framework code.  See
        frameworks/base/core/res/MakeJavaSymbols.sed for how to easily generate
        this.
+
+       Can be referenced in java code as: com.android.internal.R.<type>.<name>
+       and in layout xml as: "@*android:<type>/<name>"
   -->
   <java-symbol type="id" name="account_name" />
   <java-symbol type="id" name="account_row_icon" />
@@ -424,6 +427,7 @@
   <java-symbol type="integer" name="config_mdc_initial_max_retry" />
   <java-symbol type="integer" name="config_keepPreloadsMinDays" />
   <java-symbol type="bool" name="config_hasPermanentDpad" />
+  <java-symbol type="bool" name="config_useDefaultFocusHighlight" />
 
   <java-symbol type="color" name="tab_indicator_text_v4" />
 
@@ -1003,6 +1007,7 @@
   <java-symbol type="string" name="wifi_p2p_turnon_message" />
   <java-symbol type="string" name="wifi_p2p_frequency_conflict_message" />
   <java-symbol type="string" name="wifi_tether_configure_ssid_default" />
+  <java-symbol type="string" name="wifi_localhotspot_configure_ssid_default" />
   <java-symbol type="string" name="wifi_watchdog_network_disabled" />
   <java-symbol type="string" name="wifi_watchdog_network_disabled_detailed" />
   <java-symbol type="string" name="imei" />
@@ -1318,6 +1323,7 @@
   <java-symbol type="drawable" name="ic_corp_user_badge" />
   <java-symbol type="drawable" name="ic_corp_badge_no_background" />
   <java-symbol type="drawable" name="ic_corp_statusbar_icon" />
+  <java-symbol type="drawable" name="ic_instant_icon_badge_bolt" />
   <java-symbol type="drawable" name="emulator_circular_window_overlay" />
 
   <java-symbol type="drawable" name="sim_light_blue" />
@@ -1349,6 +1355,7 @@
   <java-symbol type="color" name="profile_badge_1" />
   <java-symbol type="color" name="profile_badge_2" />
   <java-symbol type="color" name="profile_badge_3" />
+  <java-symbol type="color" name="instant_app_badge" />
 
   <java-symbol type="layout" name="action_bar_home" />
   <java-symbol type="layout" name="action_bar_title_item" />
@@ -2857,6 +2864,7 @@
   <java-symbol type="id" name="accessibility_button_target_icon" />
   <java-symbol type="id" name="accessibility_button_target_label" />
   <java-symbol type="string" name="accessibility_magnification_chooser_text" />
+  <java-symbol type="drawable" name="ic_accessibility_magnification" />
 
   <!-- com.android.internal.widget.RecyclerView -->
   <java-symbol type="id" name="item_touch_helper_previous_elevation"/>
@@ -2867,6 +2875,7 @@
   <!-- com.android.server.autofill -->
   <java-symbol type="layout" name="autofill_save"/>
   <java-symbol type="layout" name="autofill_dataset_picker"/>
+  <java-symbol type="id" name="autofill_dataset_picker"/>
   <java-symbol type="id" name="autofill_dataset_list"/>
   <java-symbol type="id" name="autofill" />
   <java-symbol type="id" name="autofill_save_title" />
diff --git a/core/tests/coretests/res/xml/ime_meta_dismiss.xml b/core/tests/coretests/res/xml/ime_meta_dismiss.xml
deleted file mode 100644
index 59f8ecc..0000000
--- a/core/tests/coretests/res/xml/ime_meta_dismiss.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-    Copyright (C) 2017 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-
-<input-method
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:settingsActivity="com.android.inputmethod.latin.settings.SettingsActivity"
-    android:supportsDismissingWindow="true"
->
-  <subtype
-      android:label="subtype1"
-      android:imeSubtypeLocale="en_US"
-      android:imeSubtypeMode="keyboard" />
-</input-method>
diff --git a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
index 6bcf8fc..0e1e6ac 100644
--- a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
+++ b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
@@ -27,6 +27,6 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.animator_basic);
-        mAnimatingButton = (Button) findViewById(R.id.animatingButton);
+        mAnimatingButton = findViewById(R.id.animatingButton);
     }
 }
diff --git a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
index 5ade66e..7550cb5 100644
--- a/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/AdaptiveIconDrawableTest.java
@@ -2,18 +2,22 @@
 
 import static org.junit.Assert.assertTrue;
 
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.Path.Direction;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Region;
 import android.test.AndroidTestCase;
 import android.util.Log;
+import android.util.PathParser;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.util.Arrays;
@@ -35,7 +39,7 @@
      * Nothing is drawn.
      */
     @Test
-    public void testDrawWithoutSetBounds() throws Exception {
+    public void testDraw_withoutBounds() throws Exception {
         mBackgroundDrawable = new ColorDrawable(Color.BLUE);
         mForegroundDrawable = new ColorDrawable(Color.RED);
         mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
@@ -59,7 +63,7 @@
      * When setBound is called, translate accordingly.
      */
     @Test
-    public void testDrawSetBounds() throws Exception {
+    public void testDraw_withBounds() throws Exception {
         int dpi = 4 ;
         int top = 18 * dpi;
         int left = 18 * dpi;
@@ -102,6 +106,71 @@
         }
     }
 
+    /**
+     * When setBound isn't called before getIconMask method is called.
+     * default device config mask is returned.
+     */
+    @Test
+    public void testGetIconMask_withoutBounds() throws Exception {
+        mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
+        Path pathFromDrawable = mIconDrawable.getIconMask();
+        Path pathFromDeviceConfig = PathParser.createPathFromPathData(
+            Resources.getSystem().getString(com.android.internal.R.string.config_icon_mask));
+
+        RectF boundFromDrawable = new RectF();
+        pathFromDrawable.computeBounds(boundFromDrawable, true);
+
+        RectF boundFromDeviceConfig = new RectF();
+        pathFromDeviceConfig.computeBounds(boundFromDeviceConfig, true);
+
+        double delta = 0.01;
+        assertEquals("left", boundFromDrawable.left, boundFromDeviceConfig.left, delta);
+        assertEquals("top", boundFromDrawable.top, boundFromDeviceConfig.top, delta);
+        assertEquals("right", boundFromDrawable.right, boundFromDeviceConfig.right, delta);
+        assertEquals("bottom", boundFromDrawable.bottom, boundFromDeviceConfig.bottom, delta);
+
+        assertTrue("path from device config is convex.", pathFromDeviceConfig.isConvex());
+        assertTrue("path from drawable is convex.", pathFromDrawable.isConvex());
+    }
+
+    @Test
+    public void testGetIconMaskAfterSetBounds() throws Exception {
+        int dpi = 4;
+        int top = 18 * dpi;
+        int left = 18 * dpi;
+        int right = 90 * dpi;
+        int bottom = 90 * dpi;
+
+        mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
+        mIconDrawable.setBounds(left, top, right, bottom);
+        RectF maskBounds = new RectF();
+
+        mIconDrawable.getIconMask().computeBounds(maskBounds, true);
+
+        double delta = 0.01;
+        assertEquals("left", left, maskBounds.left, delta);
+        assertEquals("top", top, maskBounds.top, delta);
+        assertEquals("right", right, maskBounds.right, delta);
+        assertEquals("bottom", bottom, maskBounds.bottom, delta);
+
+        assertTrue(mIconDrawable.getIconMask().isConvex());
+    }
+
+    @Test
+    public void testGetOutline_withBounds() throws Exception {
+        int dpi = 4;
+        int top = 18 * dpi;
+        int left = 18 * dpi;
+        int right = 90 * dpi;
+        int bottom = 90 * dpi;
+
+        mIconDrawable = new AdaptiveIconDrawable(mBackgroundDrawable, mForegroundDrawable);
+        mIconDrawable.setBounds(left, top, right, bottom);
+        Outline outline = new Outline();
+        mIconDrawable.getOutline(outline);
+        assertTrue("outline path should be convex", outline.mPath.isConvex());
+    }
+
     //
     // Utils
     //
diff --git a/core/tests/coretests/src/android/graphics/drawable/IconTest.java b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
index b50955b..b7a48c7 100644
--- a/core/tests/coretests/src/android/graphics/drawable/IconTest.java
+++ b/core/tests/coretests/src/android/graphics/drawable/IconTest.java
@@ -119,13 +119,13 @@
         final AdaptiveIconDrawable draw1 = (AdaptiveIconDrawable) im1.loadDrawable(mContext);
 
         final Bitmap test1 = Bitmap.createBitmap(
-            (int)(draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
-            (int)(draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
+            (int)(draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction())),
+            (int)(draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction())),
             Bitmap.Config.ARGB_8888);
 
         draw1.setBounds(0, 0,
-            (int) (draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())),
-            (int) (draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage())));
+            (int) (draw1.getIntrinsicWidth() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction())),
+            (int) (draw1.getIntrinsicHeight() * (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction())));
         draw1.draw(new Canvas(test1));
 
         final File dir = getContext().getExternalFilesDir(null);
diff --git a/core/tests/coretests/src/android/metrics/LogMakerTest.java b/core/tests/coretests/src/android/metrics/LogMakerTest.java
index bab9f63..63c1f87 100644
--- a/core/tests/coretests/src/android/metrics/LogMakerTest.java
+++ b/core/tests/coretests/src/android/metrics/LogMakerTest.java
@@ -263,4 +263,32 @@
         assertFalse(a.isSubsetOf(b));
         assertFalse(b.isSubsetOf(a));
     }
+
+    public void testConstructFromNull() {
+        new LogMaker(null);
+        // no promises, just don't throw
+    }
+
+    public void testConstructFromNullKey() {
+        Object[] items = new Object[2];
+        items[0] = null;
+        items[1] = "foo";
+        new LogMaker(items);
+        // no promises, just don't throw
+    }
+
+    public void testConstructFromNullField() {
+        Object[] items = new Object[2];
+        items[0] = 10;
+        items[1] = null;
+        new LogMaker(items);
+        // no promises, just don't throw
+    }
+
+    public void testConstructFromTruncatedArray() {
+        Object[] items = new Object[1];
+        items[0] = 10;
+        new LogMaker(items);
+        // no promises, just don't throw
+    }
 }
diff --git a/core/tests/coretests/src/android/os/BrightnessLimit.java b/core/tests/coretests/src/android/os/BrightnessLimit.java
index f4a5e09..43cd373 100644
--- a/core/tests/coretests/src/android/os/BrightnessLimit.java
+++ b/core/tests/coretests/src/android/os/BrightnessLimit.java
@@ -40,7 +40,7 @@
         
         setContentView(R.layout.brightness_limit);
         
-        Button b = (Button) findViewById(R.id.go);
+        Button b = findViewById(R.id.go);
         b.setOnClickListener(this);
     }
 
diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java
new file mode 100644
index 0000000..aaaf55c
--- /dev/null
+++ b/core/tests/coretests/src/android/os/VintfObjectTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class VintfObjectTest extends TestCase {
+    public void testReport() {
+        String[] xmls = VintfObject.report();
+        assertTrue(xmls.length > 0);
+        // From /system/manifest.xml
+        assertTrue(String.join("", xmls).contains(
+                "<manifest version=\"1.0\" type=\"framework\">"));
+    }
+}
diff --git a/core/tests/coretests/src/android/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
index 1dd3ef6..ccc8c18 100644
--- a/core/tests/coretests/src/android/provider/FontsContractTest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -17,29 +17,29 @@
 
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import static android.provider.FontsContract.Columns.RESULT_CODE_OK;
+import static android.provider.FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND;
+import static android.provider.FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE;
+import static android.provider.FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY;
+
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.content.pm.Signature;
 import android.database.MatrixCursor;
-import android.graphics.Typeface;
 import android.graphics.fonts.FontRequest;
-import android.graphics.fonts.FontResult;
-import android.os.Bundle;
-import android.os.ResultReceiver;
+import android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+import android.graphics.fonts.FontVariationAxis;
+import android.provider.FontsContract.FontInfo;
 import android.support.test.filters.SmallTest;
 import android.test.ProviderTestCase2;
 import android.util.Base64;
 
-import org.mockito.ArgumentCaptor;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -61,8 +61,6 @@
     private final FontRequest request = new FontRequest(
             TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query");
     private TestFontsProvider mProvider;
-    private FontsContract mContract;
-    private ResultReceiver mResultReceiver;
     private PackageManager mPackageManager;
 
     public FontsContractTest() {
@@ -74,126 +72,178 @@
 
         mProvider = getProvider();
         mPackageManager = mock(PackageManager.class);
-        mContract = new FontsContract(getMockContext(), mPackageManager);
-        mResultReceiver = mock(ResultReceiver.class);
     }
 
-    public void testGetFontFromProvider_resultOK() {
-        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
-
-        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
-        verify(mResultReceiver).send(
-                eq(FontsContract.Columns.RESULT_CODE_OK), bundleCaptor.capture());
-
-        Bundle bundle = bundleCaptor.getValue();
-        assertNotNull(bundle);
-        List<FontResult> resultList =
-                bundle.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS);
-        assertNotNull(resultList);
-        assertEquals(1, resultList.size());
-        FontResult fontResult = resultList.get(0);
-        assertEquals(TestFontsProvider.TTC_INDEX, fontResult.getTtcIndex());
-        assertEquals(TestFontsProvider.VARIATION_SETTINGS, fontResult.getFontVariationSettings());
-        assertEquals(TestFontsProvider.NORMAL_WEIGHT, fontResult.getWeight());
-        assertEquals(TestFontsProvider.ITALIC, fontResult.getItalic());
-        assertNotNull(fontResult.getFileDescriptor());
+    public void testGetFontFromProvider_resultOK() throws InvalidFormatException {
+        FontInfo[] fonts = FontsContract.getFontFromProvider(
+                getMockContext(), request, TestFontsProvider.AUTHORITY, null);
+        assertNotNull(fonts);
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(TestFontsProvider.TTC_INDEX, font.getTtcIndex());
+        FontVariationAxis[] actual = font.getAxes();
+        assertEquals(1, actual.length);
+        assertEquals("wdth", actual[0].getTag());
+        assertEquals(1.0f, actual[0].getStyleValue(), 0);
+        assertEquals(TestFontsProvider.NORMAL_WEIGHT, font.getWeight());
+        assertEquals(TestFontsProvider.ITALIC, font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_OK, font.getResultCode());
     }
 
-    public void testGetFontFromProvider_providerDoesntReturnAllFields() {
+    public void testGetFontFromProvider_providerDoesntReturnAllFields()
+            throws InvalidFormatException {
         mProvider.setReturnAllFields(false);
 
-        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
-        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
-        verify(mResultReceiver).send(
-                eq(FontsContract.Columns.RESULT_CODE_OK), bundleCaptor.capture());
-
-        Bundle bundle = bundleCaptor.getValue();
-        assertNotNull(bundle);
-        List<FontResult> resultList =
-                bundle.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS);
-        assertNotNull(resultList);
-        assertEquals(1, resultList.size());
-        FontResult fontResult = resultList.get(0);
-        assertEquals(0, fontResult.getTtcIndex());
-        assertNull(fontResult.getFontVariationSettings());
-        assertEquals(400, fontResult.getWeight());
-        assertFalse(fontResult.getItalic());
-        assertNotNull(fontResult.getFileDescriptor());
+        FontInfo[] fonts = FontsContract.getFontFromProvider(
+                getMockContext(), request, TestFontsProvider.AUTHORITY, null);
+        assertNotNull(fonts);
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(0, font.getTtcIndex());
+        assertNull(font.getAxes());
+        assertEquals(400, font.getWeight());
+        assertFalse(font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_OK, font.getResultCode());
     }
 
-    public void testGetFontFromProvider_resultFontNotFound() {
+    public void testGetFontFromProvider_resultFontNotFound() throws InvalidFormatException {
         // Make the provider return unknown
-        mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND);
-        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
-
-        verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND,null);
+        mProvider.setResultCode(RESULT_CODE_FONT_NOT_FOUND);
+        FontInfo[] fonts = FontsContract.getFontFromProvider(
+                getMockContext(), request, TestFontsProvider.AUTHORITY, null);
+        assertNotNull(fonts);
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(TestFontsProvider.TTC_INDEX, font.getTtcIndex());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_FONT_NOT_FOUND, font.getResultCode());
     }
 
-    public void testGetFontFromProvider_resultFontUnavailable() {
+    public void testGetFontFromProvider_resultFontUnavailable() throws InvalidFormatException {
         // Make the provider return font unavailable
-        mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE);
-        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+        mProvider.setResultCode(RESULT_CODE_FONT_UNAVAILABLE);
+        FontInfo[] fonts = FontsContract.getFontFromProvider(
+                getMockContext(), request, TestFontsProvider.AUTHORITY, null);
 
-        verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE,null);
+        assertNotNull(fonts);
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(TestFontsProvider.TTC_INDEX, font.getTtcIndex());
+        FontVariationAxis[] actual = font.getAxes();
+        assertEquals(1, actual.length);
+        assertEquals("wdth", actual[0].getTag());
+        assertEquals(1.0f, actual[0].getStyleValue(), 0);
+        assertEquals(TestFontsProvider.NORMAL_WEIGHT, font.getWeight());
+        assertEquals(TestFontsProvider.ITALIC, font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_FONT_UNAVAILABLE, font.getResultCode());
     }
 
-    public void testGetFontFromProvider_resultMalformedQuery() {
+    public void testGetFontFromProvider_resultMalformedQuery() throws InvalidFormatException {
         // Make the provider return font unavailable
-        mProvider.setResultCode(FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY);
-        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+        mProvider.setResultCode(RESULT_CODE_MALFORMED_QUERY);
+        FontInfo[] fonts = FontsContract.getFontFromProvider(
+                getMockContext(), request, TestFontsProvider.AUTHORITY, null);
 
-        verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY,null);
+        assertNotNull(fonts);
+        assertEquals(1, fonts.length);
+        FontInfo font = fonts[0];
+        assertEquals(TestFontsProvider.TTC_INDEX, font.getTtcIndex());
+        FontVariationAxis[] actual = font.getAxes();
+        assertEquals(1, actual.length);
+        assertEquals("wdth", actual[0].getTag());
+        assertEquals(1.0f, actual[0].getStyleValue(), 0);
+        assertEquals(TestFontsProvider.NORMAL_WEIGHT, font.getWeight());
+        assertEquals(TestFontsProvider.ITALIC, font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_MALFORMED_QUERY, font.getResultCode());
     }
 
-    public void testGetFontFromProvider_resultFontNotFoundSecondRow() {
+    public void testGetFontFromProvider_resultFontNotFoundSecondRow()
+            throws InvalidFormatException {
         MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
                 FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
                 FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
                 FontsContract.Columns.RESULT_CODE });
-        cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0, RESULT_CODE_OK});
         cursor.addRow(new Object[] { 1, 0, null, 400, 0,
-                FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
+                RESULT_CODE_FONT_NOT_FOUND});
         mProvider.setCustomCursor(cursor);
-        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+        FontInfo[] fonts = FontsContract.getFontFromProvider(
+                getMockContext(), request, TestFontsProvider.AUTHORITY, null);
 
-        verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+        assertNotNull(fonts);
+        assertEquals(2, fonts.length);
+
+        FontInfo font = fonts[0];
+        assertEquals(0, font.getTtcIndex());
+        assertNull(font.getAxes());
+        assertEquals(400, font.getWeight());
+        assertFalse(font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_OK, font.getResultCode());
+
+        font = fonts[1];
+        assertEquals(0, font.getTtcIndex());
+        assertNull(font.getAxes());
+        assertEquals(400, font.getWeight());
+        assertFalse(font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_FONT_NOT_FOUND, font.getResultCode());
     }
 
-    public void testGetFontFromProvider_resultFontNotFoundOtherRow() {
+    public void testGetFontFromProvider_resultFontNotFoundOtherRow() throws InvalidFormatException {
         MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
                 FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
                 FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
                 FontsContract.Columns.RESULT_CODE });
-        cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0, RESULT_CODE_OK});
         cursor.addRow(new Object[] { 1, 0, null, 400, 0,
-                FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND});
-        cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
+                RESULT_CODE_FONT_NOT_FOUND});
+        cursor.addRow(new Object[] { 1, 0, null, 400, 0, RESULT_CODE_OK});
         mProvider.setCustomCursor(cursor);
-        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+        FontInfo[] fonts = FontsContract.getFontFromProvider(
+                getMockContext(), request, TestFontsProvider.AUTHORITY, null);
 
-        verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
-    }
+        assertNotNull(fonts);
+        assertEquals(3, fonts.length);
 
-    public void testGetFontFromProvider_resultCodeIsNegativeNumber() {
-        MatrixCursor cursor = new MatrixCursor(new String[] { FontsContract.Columns._ID,
-                FontsContract.Columns.TTC_INDEX, FontsContract.Columns.VARIATION_SETTINGS,
-                FontsContract.Columns.WEIGHT, FontsContract.Columns.ITALIC,
-                FontsContract.Columns.RESULT_CODE });
-        cursor.addRow(new Object[] { 1, 0, null, 400, 0, FontsContract.Columns.RESULT_CODE_OK});
-        cursor.addRow(new Object[] { 1, 0, null, 400, 0, -5});
-        mProvider.setCustomCursor(cursor);
-        mContract.getFontFromProvider(request, mResultReceiver, TestFontsProvider.AUTHORITY);
+        FontInfo font = fonts[0];
+        assertEquals(0, font.getTtcIndex());
+        assertNull(font.getAxes());
+        assertEquals(400, font.getWeight());
+        assertFalse(font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_OK, font.getResultCode());
 
-        verify(mResultReceiver).send(FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND, null);
+        font = fonts[1];
+        assertEquals(0, font.getTtcIndex());
+        assertNull(font.getAxes());
+        assertEquals(400, font.getWeight());
+        assertFalse(font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_FONT_NOT_FOUND, font.getResultCode());
+
+        font = fonts[2];
+        assertEquals(0, font.getTtcIndex());
+        assertNull(font.getAxes());
+        assertEquals(400, font.getWeight());
+        assertFalse(font.isItalic());
+        assertNotNull(font.getUri());
+        assertEquals(RESULT_CODE_OK, font.getResultCode());
     }
 
     public void testGetProvider_providerNotFound() {
         when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(null);
 
-        ProviderInfo result = mContract.getProvider(request, mResultReceiver);
-
-        verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
-        assertNull(result);
+        try {
+            FontsContract.getProvider(mPackageManager, request);
+            fail();
+        } catch (NameNotFoundException e) {
+            // pass
+        }
     }
 
     public void testGetProvider_providerIsSystemApp() throws PackageManager.NameNotFoundException {
@@ -201,9 +251,7 @@
         info.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
         when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
 
-        ProviderInfo result = mContract.getProvider(request, mResultReceiver);
-
-        verifyZeroInteractions(mResultReceiver);
+        ProviderInfo result = FontsContract.getProvider(mPackageManager, request);
         assertEquals(info, result);
     }
 
@@ -213,23 +261,22 @@
         info.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
         when(mPackageManager.resolveContentProvider(anyString(), anyInt())).thenReturn(info);
 
-        ProviderInfo result = mContract.getProvider(
-                new FontRequest(TestFontsProvider.AUTHORITY, "com.wrong.package", "query"),
-                mResultReceiver);
+        try {
+            FontsContract.getProvider(
+                mPackageManager,
+                new FontRequest(TestFontsProvider.AUTHORITY, "com.wrong.package", "query"));
+            fail();
+        } catch (NameNotFoundException e) {
+            // pass
+        }
 
-        verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
-        assertNull(result);
     }
 
     public void testGetProvider_providerIsNonSystemAppNoCerts()
             throws PackageManager.NameNotFoundException {
         setupPackageManager();
 
-        // The default request is missing the certificates info.
-        ProviderInfo result = mContract.getProvider(request, mResultReceiver);
-
-        verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
-        assertNull(result);
+        assertNull(FontsContract.getProvider(mPackageManager, request));
     }
 
     public void testGetProvider_providerIsNonSystemAppWrongCerts()
@@ -240,10 +287,8 @@
         List<byte[]> certList = Arrays.asList(wrongCert);
         FontRequest requestWrongCerts = new FontRequest(
                 TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
-        ProviderInfo result = mContract.getProvider(requestWrongCerts, mResultReceiver);
 
-        verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
-        assertNull(result);
+        assertNull(FontsContract.getProvider(mPackageManager, requestWrongCerts));
     }
 
     public void testGetProvider_providerIsNonSystemAppCorrectCerts()
@@ -253,9 +298,9 @@
         List<byte[]> certList = Arrays.asList(BYTE_ARRAY);
         FontRequest requestRightCerts = new FontRequest(
                 TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
-        ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
+        ProviderInfo result = FontsContract.getProvider(
+                mPackageManager, requestRightCerts);
 
-        verifyZeroInteractions(mResultReceiver);
         assertEquals(info, result);
     }
 
@@ -267,11 +312,7 @@
         List<byte[]> certList = Arrays.asList(wrongCert, BYTE_ARRAY);
         FontRequest requestRightCerts = new FontRequest(
                 TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
-        ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
-
-        // There is one too many certs, should fail as the set doesn't match.
-        verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
-        assertNull(result);
+        assertNull(FontsContract.getProvider(mPackageManager, requestRightCerts));
     }
 
     public void testGetProvider_providerIsNonSystemAppDuplicateCerts()
@@ -294,12 +335,7 @@
         List<byte[]> certList = Arrays.asList(BYTE_ARRAY_2, BYTE_ARRAY_COPY);
         FontRequest requestRightCerts = new FontRequest(
                 TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
-        ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
-
-        // The given list includes an extra cert and doesn't have a second copy of the cert like
-        // the provider does, so it should have failed.
-        verify(mResultReceiver).send(FontsContract.RESULT_CODE_WRONG_CERTIFICATES, null);
-        assertNull(result);
+        assertNull(FontsContract.getProvider(mPackageManager, requestRightCerts));
     }
 
     public void testGetProvider_providerIsNonSystemAppCorrectCertsSeveralSets()
@@ -312,9 +348,8 @@
         certList.add(Arrays.asList(BYTE_ARRAY));
         FontRequest requestRightCerts = new FontRequest(
                 TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", certList);
-        ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
+        ProviderInfo result = FontsContract.getProvider(mPackageManager, requestRightCerts);
 
-        verifyZeroInteractions(mResultReceiver);
         assertEquals(info, result);
     }
 
@@ -326,10 +361,12 @@
         certList.add(Arrays.asList(BYTE_ARRAY));
         FontRequest requestRightCerts = new FontRequest(
                 TestFontsProvider.AUTHORITY, "com.wrong.package.name", "query", certList);
-        ProviderInfo result = mContract.getProvider(requestRightCerts, mResultReceiver);
-
-        verify(mResultReceiver).send(FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND, null);
-        assertNull(result);
+        try {
+            FontsContract.getProvider(mPackageManager, requestRightCerts);
+            fail();
+        } catch (NameNotFoundException e) {
+            // pass
+        }
     }
 
     private ProviderInfo setupPackageManager()
diff --git a/core/tests/coretests/src/android/view/Disabled.java b/core/tests/coretests/src/android/view/Disabled.java
index fa92107..d3c7470 100644
--- a/core/tests/coretests/src/android/view/Disabled.java
+++ b/core/tests/coretests/src/android/view/Disabled.java
@@ -34,16 +34,16 @@
         setContentView(R.layout.disabled);
 
         // Find our buttons
-        Button disabledButton = (Button) findViewById(R.id.disabledButton);
+        Button disabledButton = findViewById(R.id.disabledButton);
         disabledButton.setEnabled(false);
         
         // Find our buttons
-        Button disabledButtonA = (Button) findViewById(R.id.disabledButtonA);
+        Button disabledButtonA = findViewById(R.id.disabledButtonA);
         disabledButtonA.setOnClickListener(this);
     }
 
     public void onClick(View v) {
-        Button disabledButtonB = (Button) findViewById(R.id.disabledButtonB);
+        Button disabledButtonB = findViewById(R.id.disabledButtonB);
         disabledButtonB.setEnabled(!disabledButtonB.isEnabled());
     }
 }
diff --git a/core/tests/coretests/src/android/view/DrawableBgMinSize.java b/core/tests/coretests/src/android/view/DrawableBgMinSize.java
index a75b23a..58bfb8a 100644
--- a/core/tests/coretests/src/android/view/DrawableBgMinSize.java
+++ b/core/tests/coretests/src/android/view/DrawableBgMinSize.java
@@ -58,14 +58,14 @@
         mBackgroundDrawable = getResources().getDrawable(R.drawable.drawable_background);
         mBigBackgroundDrawable = getResources().getDrawable(R.drawable.big_drawable_background);
  
-        mChangeBackgroundsButton = (Button) findViewById(R.id.change_backgrounds);
+        mChangeBackgroundsButton = findViewById(R.id.change_backgrounds);
         mChangeBackgroundsButton.setOnClickListener(this);
         
-        mTextView = (TextView) findViewById(R.id.text_view);
-        mLinearLayout = (LinearLayout) findViewById(R.id.linear_layout);
-        mRelativeLayout = (RelativeLayout) findViewById(R.id.relative_layout);
-        mFrameLayout = (FrameLayout) findViewById(R.id.frame_layout);
-        mAbsoluteLayout = (AbsoluteLayout) findViewById(R.id.absolute_layout);
+        mTextView = findViewById(R.id.text_view);
+        mLinearLayout = findViewById(R.id.linear_layout);
+        mRelativeLayout = findViewById(R.id.relative_layout);
+        mFrameLayout = findViewById(R.id.frame_layout);
+        mAbsoluteLayout = findViewById(R.id.absolute_layout);
 
         changeBackgrounds(mBackgroundDrawable);
     }
diff --git a/core/tests/coretests/src/android/view/PopupWindowVisibility.java b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
index 6e11ede..85ce04f 100644
--- a/core/tests/coretests/src/android/view/PopupWindowVisibility.java
+++ b/core/tests/coretests/src/android/view/PopupWindowVisibility.java
@@ -45,13 +45,13 @@
 
         mFrame = findViewById(R.id.frame);
         
-        mHide = (Button) findViewById(R.id.hide);
+        mHide = findViewById(R.id.hide);
         mHide.setOnClickListener(this);
         
-        mShow = (Button) findViewById(R.id.show);
+        mShow = findViewById(R.id.show);
         mShow.setOnClickListener(this);
         
-        Spinner spinner = (Spinner) findViewById(R.id.spinner);
+        Spinner spinner = findViewById(R.id.spinner);
         ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(this,
                 android.R.layout.simple_spinner_item, mStrings);
         spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -59,7 +59,7 @@
         
         ArrayAdapter<String> autoAdapter = new ArrayAdapter<String>(this,
                 android.R.layout.simple_dropdown_item_1line, COUNTRIES);
-        AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.auto);
+        AutoCompleteTextView textView = findViewById(R.id.auto);
         textView.setAdapter(autoAdapter);
     }
 
diff --git a/core/tests/coretests/src/android/view/PreDrawListener.java b/core/tests/coretests/src/android/view/PreDrawListener.java
index 981c6c0..60bbee4 100644
--- a/core/tests/coretests/src/android/view/PreDrawListener.java
+++ b/core/tests/coretests/src/android/view/PreDrawListener.java
@@ -75,9 +75,9 @@
         super.onCreate(icicle);
         setContentView(R.layout.pre_draw_listener);
 
-        mFrame = (MyLinearLayout) findViewById(R.id.frame);
+        mFrame = findViewById(R.id.frame);
 
-        Button mGoButton = (Button) findViewById(R.id.go);
+        Button mGoButton = findViewById(R.id.go);
         mGoButton.setOnClickListener(this);
     }
 
diff --git a/core/tests/coretests/src/android/view/Visibility.java b/core/tests/coretests/src/android/view/Visibility.java
index 97ff252..031568c 100644
--- a/core/tests/coretests/src/android/view/Visibility.java
+++ b/core/tests/coretests/src/android/view/Visibility.java
@@ -37,9 +37,9 @@
         mVictim = findViewById(R.id.victim);
 
         // Find our buttons
-        Button visibleButton = (Button) findViewById(R.id.vis);
-        Button invisibleButton = (Button) findViewById(R.id.invis);
-        Button goneButton = (Button) findViewById(R.id.gone);
+        Button visibleButton = findViewById(R.id.vis);
+        Button invisibleButton = findViewById(R.id.invis);
+        Button goneButton = findViewById(R.id.gone);
 
         // Wire each button to a click listener
         visibleButton.setOnClickListener(mVisibleListener);
diff --git a/core/tests/coretests/src/android/view/VisibilityCallback.java b/core/tests/coretests/src/android/view/VisibilityCallback.java
index 7290a62..f98a0a8 100644
--- a/core/tests/coretests/src/android/view/VisibilityCallback.java
+++ b/core/tests/coretests/src/android/view/VisibilityCallback.java
@@ -45,9 +45,9 @@
         mVictim = (MonitoredTextView)findViewById(R.id.victim);
 
         // Find our buttons
-        Button visibleButton = (Button) findViewById(R.id.vis);
-        Button invisibleButton = (Button) findViewById(R.id.invis);
-        Button goneButton = (Button) findViewById(R.id.gone);
+        Button visibleButton = findViewById(R.id.vis);
+        Button invisibleButton = findViewById(R.id.invis);
+        Button goneButton = findViewById(R.id.gone);
 
         // Wire each button to a click listener
         visibleButton.setOnClickListener(mVisibleListener);
diff --git a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
index 23dc80f..13cef52 100644
--- a/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
+++ b/core/tests/coretests/src/android/view/inputmethod/InputMethodInfoTest.java
@@ -51,12 +51,10 @@
         final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta);
 
         assertThat(imi.supportsSwitchingToNextInputMethod(), is(false));
-        assertThat(imi.supportsDismissingWindow(), is(false));
 
         final InputMethodInfo clone = cloneViaParcel(imi);
 
         assertThat(clone.supportsSwitchingToNextInputMethod(), is(false));
-        assertThat(clone.supportsDismissingWindow(), is(false));
     }
 
     @Test
@@ -70,17 +68,6 @@
         assertThat(clone.supportsSwitchingToNextInputMethod(), is(true));
     }
 
-    @Test
-    public void testSupportsDismissingWindow() throws Exception {
-        final InputMethodInfo imi = buildInputMethodForTest(R.xml.ime_meta_dismiss);
-
-        assertThat(imi.supportsDismissingWindow(), is(true));
-
-        final InputMethodInfo clone = cloneViaParcel(imi);
-
-        assertThat(clone.supportsDismissingWindow(), is(true));
-    }
-
     private InputMethodInfo buildInputMethodForTest(final @XmlRes int metaDataRes)
             throws Exception {
         final Context context = InstrumentationRegistry.getContext();
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
new file mode 100644
index 0000000..39b999d
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.textclassifier;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import android.os.LocaleList;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.Locale;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TextClassificationManagerTest {
+
+    private static final LocaleList LOCALES = LocaleList.forLanguageTags("en");
+
+    private TextClassificationManager mTcm;
+    private TextClassifier mClassifier;
+
+    @Before
+    public void setup() {
+        mTcm = InstrumentationRegistry.getTargetContext()
+                .getSystemService(TextClassificationManager.class);
+        mTcm.setTextClassifier(null);
+        mClassifier = mTcm.getTextClassifier();
+    }
+
+    @Test
+    public void testSmartSelection() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Contact me at droid@android.com";
+        String selected = "droid";
+        String suggested = "droid@android.com";
+        int startIndex = text.indexOf(selected);
+        int endIndex = startIndex + selected.length();
+        int smartStartIndex = text.indexOf(suggested);
+        int smartEndIndex = smartStartIndex + suggested.length();
+
+        assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES),
+                isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_EMAIL));
+    }
+
+    @Test
+    public void testSmartSelection_nullLocaleList() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Contact me at droid@android.com";
+        String selected = "droid";
+        String suggested = "droid@android.com";
+        int startIndex = text.indexOf(selected);
+        int endIndex = startIndex + selected.length();
+        int smartStartIndex = text.indexOf(suggested);
+        int smartEndIndex = smartStartIndex + suggested.length();
+        LocaleList nullLocales = null;
+
+        assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, nullLocales),
+                isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_EMAIL));
+    }
+
+    @Test
+    public void testSmartSelection_url() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Visit http://www.android.com for more information";
+        String selected = "http";
+        String suggested = "http://www.android.com";
+        int startIndex = text.indexOf(selected);
+        int endIndex = startIndex + selected.length();
+        int smartStartIndex = text.indexOf(suggested);
+        int smartEndIndex = smartStartIndex + suggested.length();
+
+        assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES),
+                isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_URL));
+    }
+
+    @Test
+    public void testTextClassificationResult() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Contact me at droid@android.com";
+        String classifiedText = "droid@android.com";
+        int startIndex = text.indexOf(classifiedText);
+        int endIndex = startIndex + classifiedText.length();
+        assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, LOCALES),
+                isTextClassificationResult(classifiedText, TextClassifier.TYPE_EMAIL));
+    }
+
+    @Test
+    public void testTextClassificationResult_url() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Visit http://www.android.com for more information";
+        String classifiedText = "http://www.android.com";
+        int startIndex = text.indexOf(classifiedText);
+        int endIndex = startIndex + classifiedText.length();
+        assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, LOCALES),
+                isTextClassificationResult(classifiedText, TextClassifier.TYPE_URL));
+    }
+
+    @Test
+    public void testTextClassificationResult_nullLocaleList() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Contact me at droid@android.com";
+        String classifiedText = "droid@android.com";
+        int startIndex = text.indexOf(classifiedText);
+        int endIndex = startIndex + classifiedText.length();
+        LocaleList nullLocales = null;
+        assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, nullLocales),
+                isTextClassificationResult(classifiedText, TextClassifier.TYPE_EMAIL));
+    }
+
+    @Test
+    public void testLanguageDetection() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "This is a piece of English text";
+        assertThat(mTcm.detectLanguages(text), isDetectedLanguage("en"));
+
+        text = "Das ist ein deutscher Text";
+        assertThat(mTcm.detectLanguages(text), isDetectedLanguage("de"));
+
+        text = "これは日本語のテキストです";
+        assertThat(mTcm.detectLanguages(text), isDetectedLanguage("ja"));
+    }
+
+    @Test
+    public void testSetTextClassifier() {
+        TextClassifier classifier = mock(TextClassifier.class);
+        mTcm.setTextClassifier(classifier);
+        assertEquals(classifier, mTcm.getTextClassifier());
+    }
+
+    private boolean isTextClassifierDisabled() {
+        return mClassifier == TextClassifier.NO_OP;
+    }
+
+    private static Matcher<TextSelection> isTextSelection(
+            final int startIndex, final int endIndex, final String type) {
+        return new BaseMatcher<TextSelection>() {
+            @Override
+            public boolean matches(Object o) {
+                if (o instanceof TextSelection) {
+                    TextSelection selection = (TextSelection) o;
+                    return startIndex == selection.getSelectionStartIndex()
+                            && endIndex == selection.getSelectionEndIndex()
+                            && selection.getEntityCount() > 0
+                            && type.equals(selection.getEntity(0));
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendValue(
+                        String.format("%d, %d, %s", startIndex, endIndex, type));
+            }
+        };
+    }
+
+    private static Matcher<TextClassificationResult> isTextClassificationResult(
+            final String text, final String type) {
+        return new BaseMatcher<TextClassificationResult>() {
+            @Override
+            public boolean matches(Object o) {
+                if (o instanceof TextClassificationResult) {
+                    TextClassificationResult result = (TextClassificationResult) o;
+                    return text.equals(result.getText())
+                            && result.getEntityCount() > 0
+                            && type.equals(result.getEntity(0));
+                    // TODO: Include other properties.
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("text=").appendValue(text)
+                        .appendText(", type=").appendValue(type);
+            }
+        };
+    }
+
+    private static Matcher<List<TextLanguage>> isDetectedLanguage(final String language) {
+        return new BaseMatcher<List<TextLanguage>>() {
+            @Override
+            public boolean matches(Object o) {
+                if (o instanceof List) {
+                    List languages = (List) o;
+                    if (!languages.isEmpty()) {
+                        Object o1 = languages.get(0);
+                        if (o1 instanceof TextLanguage) {
+                            TextLanguage lang = (TextLanguage) o1;
+                            return lang.getLanguageCount() > 0
+                                    && new Locale(language).getLanguage()
+                                            .equals(lang.getLanguage(0).getLanguage());
+                        }
+                    }
+                }
+                return false;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendValue(String.format("%s", language));
+            }
+        };
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java b/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
index f6cec26..b4e05aa 100644
--- a/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
+++ b/core/tests/coretests/src/android/widget/AutoCompleteTextViewSimple.java
@@ -47,7 +47,7 @@
 
         // setup layout & views
         setContentView(R.layout.autocompletetextview_simple);
-        mTextView = (AutoCompleteTextView) findViewById(R.id.autocompletetextview1);
+        mTextView = findViewById(R.id.autocompletetextview1);
         
         // configure callbacks used for monitoring
         mTextView.setOnItemClickListener(this);
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 3029134..2203b6a 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -28,6 +28,7 @@
 import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
 import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
 import static android.widget.espresso.TextViewAssertions.hasSelection;
+import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarItemIndex;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed;
 import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
@@ -46,6 +47,11 @@
 import static org.hamcrest.Matchers.anyOf;
 import static org.hamcrest.Matchers.is;
 
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.textclassifier.TextClassificationManager;
+import android.view.textclassifier.TextClassifier;
 import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider;
 
 import android.support.test.espresso.action.EspressoKey;
@@ -71,7 +77,8 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        getActivity();
+        getActivity().getSystemService(TextClassificationManager.class)
+                .setTextClassifier(TextClassifier.NO_OP);
     }
 
     public void testTypedTextIsOnScreen() throws Exception {
@@ -676,4 +683,38 @@
         // hasTransientState should return false when selection is created by API.
         assertFalse(textView.hasTransientState());
     }
+
+    public void testAssistItemIsAtIndexZero() throws Exception {
+        getActivity().getSystemService(TextClassificationManager.class).setTextClassifier(null);
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        textView.post(() -> textView.setCustomSelectionActionModeCallback(
+                new ActionMode.Callback() {
+                    @Override
+                    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
+                        // Create another item at order position 0 to confirm that it will never be
+                        // placed before the textAssist item.
+                        menu.add(Menu.NONE, 0 /* id */, 0 /* order */, "Test");
+                        return true;
+                    }
+
+                    @Override
+                    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
+                        return true;
+                    }
+
+                    @Override
+                    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
+                        return false;
+                    }
+
+                    @Override
+                    public void onDestroyActionMode(ActionMode actionMode) {}
+                }));
+        final String text = "droid@android.com";
+
+        onView(withId(R.id.textview)).perform(replaceText(text));
+        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('@')));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarItemIndex(android.R.id.textAssist, 0);
+    }
 }
diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
index 838f4db..5206c9b 100644
--- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
+++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java
@@ -29,7 +29,13 @@
 import static org.hamcrest.Matchers.allOf;
 import static org.hamcrest.Matchers.is;
 
+import android.view.MenuItem;
+import android.view.ViewGroup;
+import java.util.ArrayList;
+import java.util.List;
+import org.hamcrest.Description;
 import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
 
 import android.support.test.espresso.NoMatchingRootException;
 import android.support.test.espresso.NoMatchingViewException;
@@ -123,6 +129,39 @@
     }
 
     /**
+     * Asserts that the floating toolbar contains a specified item at a specified index.
+     *
+     * @param menuItemId id of the menu item
+     * @param index expected index of the menu item in the floating toolbar
+     * @throws AssertionError if the assertion fails
+     */
+    public static void assertFloatingToolbarItemIndex(final int menuItemId, final int index) {
+        onFloatingToolBar().check(matches(new TypeSafeMatcher<View>() {
+            private List<Integer> menuItemIds = new ArrayList<>();
+
+            @Override
+            public boolean matchesSafely(View view) {
+                collectMenuItemIds(view);
+                return menuItemIds.size() > index && menuItemIds.get(index) == menuItemId;
+            }
+
+            @Override
+            public void describeTo(Description description) {}
+
+            private void collectMenuItemIds(View view) {
+                if (view.getTag() instanceof MenuItem) {
+                    menuItemIds.add(((MenuItem) view.getTag()).getItemId());
+                } else if (view instanceof ViewGroup) {
+                    ViewGroup viewGroup = (ViewGroup) view;
+                    for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                        collectMenuItemIds(viewGroup.getChildAt(i));
+                    }
+                }
+            }
+        }));
+    }
+
+    /**
      * Asserts that the floating toolbar doesn't contain the specified item.
      *
      * @param itemLabel label of the item.
diff --git a/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java b/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
index f7d91aa..f6b0520 100644
--- a/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
+++ b/core/tests/coretests/src/android/widget/focus/DescendantFocusability.java
@@ -40,13 +40,13 @@
 
         setContentView(R.layout.descendant_focusability);
 
-        beforeDescendants = (ViewGroup) findViewById(R.id.beforeDescendants);
+        beforeDescendants = findViewById(R.id.beforeDescendants);
         beforeDescendantsChild = (Button) beforeDescendants.getChildAt(0);
 
-        afterDescendants = (ViewGroup) findViewById(R.id.afterDescendants);
+        afterDescendants = findViewById(R.id.afterDescendants);
         afterDescendantsChild = (Button) afterDescendants.getChildAt(0);
 
-        blocksDescendants = (ViewGroup) findViewById(R.id.blocksDescendants);
+        blocksDescendants = findViewById(R.id.blocksDescendants);
         blocksDescendantsChild = (Button) blocksDescendants.getChildAt(0);
     }
 
diff --git a/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java b/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
index 93245e7..b3d5ec5 100644
--- a/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
+++ b/core/tests/coretests/src/android/widget/focus/FocusAfterRemoval.java
@@ -35,10 +35,10 @@
         super.onCreate(icicle);
         setContentView(R.layout.focus_after_removal);
 
-        final LinearLayout left = (LinearLayout) findViewById(R.id.leftLayout);
+        final LinearLayout left = findViewById(R.id.leftLayout);
 
         // top left makes parent layout GONE
-        Button topLeftButton = (Button) findViewById(R.id.topLeftButton);
+        Button topLeftButton = findViewById(R.id.topLeftButton);
         topLeftButton.setOnClickListener(new View.OnClickListener() {
 
             public void onClick(View v) {
@@ -48,7 +48,7 @@
 
         // bottom left makes parent layout INVISIBLE
         // top left makes parent layout GONE
-        Button bottomLeftButton = (Button) findViewById(R.id.bottomLeftButton);
+        Button bottomLeftButton = findViewById(R.id.bottomLeftButton);
         bottomLeftButton.setOnClickListener(new View.OnClickListener() {
 
             public void onClick(View v) {
@@ -57,7 +57,7 @@
         });
 
         // top right button makes top right button GONE
-        final Button topRightButton = (Button) findViewById(R.id.topRightButton);
+        final Button topRightButton = findViewById(R.id.topRightButton);
         topRightButton.setOnClickListener(new View.OnClickListener() {
 
             public void onClick(View v) {
@@ -66,7 +66,7 @@
         });
 
         // bottom right button makes bottom right button INVISIBLE
-        final Button bottomRightButton = (Button) findViewById(R.id.bottomRightButton);
+        final Button bottomRightButton = findViewById(R.id.bottomRightButton);
         bottomRightButton.setOnClickListener(new View.OnClickListener() {
 
             public void onClick(View v) {
diff --git a/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java b/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
index db082ec..acd632f 100644
--- a/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
+++ b/core/tests/coretests/src/android/widget/focus/LinearLayoutGrid.java
@@ -33,7 +33,7 @@
     }
 
     public ViewGroup getRootView() {
-        return (ViewGroup) findViewById(R.id.layout);
+        return findViewById(R.id.layout);
     }
 
     public Button getButtonAt(int column, int row) {
@@ -51,11 +51,11 @@
     private LinearLayout getColumn(int column) {
         switch (column) {
             case 0:
-                return (LinearLayout) findViewById(R.id.column1);
+                return findViewById(R.id.column1);
             case 1:
-                return (LinearLayout) findViewById(R.id.column2);
+                return findViewById(R.id.column2);
             case 2:
-                return (LinearLayout) findViewById(R.id.column3);
+                return findViewById(R.id.column3);
             default:
                 throw new IllegalArgumentException("column out of range");
         }
diff --git a/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java b/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
index ceb0e95..b908201 100644
--- a/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
+++ b/core/tests/coretests/src/android/widget/focus/ListWithFooterViewAndNewLabels.java
@@ -54,7 +54,7 @@
         setListAdapter(mMyAdapter);
 
         // not in list
-        Button topButton = (Button) findViewById(R.id.button);
+        Button topButton = findViewById(R.id.button);
         topButton.setText("click to add new item");
         topButton.setOnClickListener(new View.OnClickListener() {
 
diff --git a/core/tests/coretests/src/android/widget/focus/RequestFocus.java b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
index 21d762a..4daf0b4 100644
--- a/core/tests/coretests/src/android/widget/focus/RequestFocus.java
+++ b/core/tests/coretests/src/android/widget/focus/RequestFocus.java
@@ -34,7 +34,7 @@
         setContentView(R.layout.focus_after_removal);
 
         // bottom right button starts with the focus.
-        final Button bottomRightButton = (Button) findViewById(R.id.bottomRightButton);
+        final Button bottomRightButton = findViewById(R.id.bottomRightButton);
         bottomRightButton.requestFocus();
         bottomRightButton.setText("I should have focus");
     }
diff --git a/core/tests/coretests/src/android/widget/gridview/GridPadding.java b/core/tests/coretests/src/android/widget/gridview/GridPadding.java
index 0b9e4c5..c3156dc 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridPadding.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridPadding.java
@@ -40,7 +40,7 @@
             values[i] = String.valueOf(i);
         }
 
-        mGridView = (GridView) findViewById(R.id.grid);
+        mGridView = findViewById(R.id.grid);
         mGridView.setAdapter(new ArrayAdapter<String>(this,
                 android.R.layout.simple_list_item_1, values));
     }
diff --git a/core/tests/coretests/src/android/widget/gridview/GridScrollListener.java b/core/tests/coretests/src/android/widget/gridview/GridScrollListener.java
index 4290941..0ce5a31 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridScrollListener.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridScrollListener.java
@@ -46,8 +46,8 @@
             values[i] = ((Integer)i).toString();
         }
         
-        mText = (TextView) findViewById(R.id.text);
-        mGridView = (GridView) findViewById(R.id.grid);
+        mText = findViewById(R.id.text);
+        mGridView = findViewById(R.id.grid);
         mGridView.setAdapter(new ArrayAdapter<String>(this,
                 android.R.layout.simple_list_item_1, values));
 
diff --git a/core/tests/coretests/src/android/widget/gridview/GridThrasher.java b/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
index 0ef5db9..ad89bb6 100644
--- a/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
+++ b/core/tests/coretests/src/android/widget/gridview/GridThrasher.java
@@ -115,9 +115,9 @@
         
         setContentView(R.layout.grid_thrasher);
         
-        mText = (TextView) findViewById(R.id.text);
+        mText = findViewById(R.id.text);
         mAdapter = new ThrashListAdapter(this);
-        GridView g = (GridView) findViewById(R.id.grid);
+        GridView g = findViewById(R.id.grid);
         g.setAdapter(mAdapter);
         
         mHandler.postDelayed(mThrash, 5000);
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java b/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
index fe2525f..83331ca 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LLEditTextThenButton.java
@@ -36,9 +36,9 @@
 
         setContentView(R.layout.linear_layout_edittext_then_button);
 
-        mLayout = (LinearLayout) findViewById(R.id.layout);
-        mEditText = (EditText) findViewById(R.id.editText);
-        mButton = (Button) findViewById(R.id.button);
+        mLayout = findViewById(R.id.layout);
+        mEditText = findViewById(R.id.editText);
+        mButton = findViewById(R.id.button);
     }
 
     public LinearLayout getLayout() {
diff --git a/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java b/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
index 3d0144f..ab2f060 100644
--- a/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
+++ b/core/tests/coretests/src/android/widget/layout/linear/LLOfButtons1.java
@@ -37,7 +37,7 @@
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         setContentView(R.layout.linear_layout_buttons);
-        mFirstButton = (Button) findViewById(R.id.button1);
+        mFirstButton = findViewById(R.id.button1);
 
         mFirstButton.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
@@ -48,7 +48,7 @@
     }
 
     public LinearLayout getLayout() {
-        return (LinearLayout) findViewById(R.id.layout);
+        return findViewById(R.id.layout);
     }
 
     public Button getFirstButton() {
diff --git a/core/tests/coretests/src/android/widget/listview/ListDividers.java b/core/tests/coretests/src/android/widget/listview/ListDividers.java
index 3928c03..9b5a087 100644
--- a/core/tests/coretests/src/android/widget/listview/ListDividers.java
+++ b/core/tests/coretests/src/android/widget/listview/ListDividers.java
@@ -40,7 +40,7 @@
             values[i] = ((Integer) i).toString();
         }
 
-        mListView = (ListView) findViewById(android.R.id.list);
+        mListView = findViewById(android.R.id.list);
         mListView.setAdapter(new ArrayAdapter<String>(this,
                 android.R.layout.simple_list_item_1, values));
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListFilter.java b/core/tests/coretests/src/android/widget/listview/ListFilter.java
index 9e9d1b0..c2ac90e 100644
--- a/core/tests/coretests/src/android/widget/listview/ListFilter.java
+++ b/core/tests/coretests/src/android/widget/listview/ListFilter.java
@@ -46,10 +46,10 @@
         getListView().setTextFilterEnabled(true);
         mFrame = findViewById(R.id.frame);
         
-        mHide = (Button) findViewById(R.id.hide);
+        mHide = findViewById(R.id.hide);
         mHide.setOnClickListener(this);
         
-        mShow = (Button) findViewById(R.id.show);
+        mShow = findViewById(R.id.show);
         mShow.setOnClickListener(this);
     }
     
diff --git a/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java b/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
index 5f09ff6..a373a5b 100644
--- a/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
+++ b/core/tests/coretests/src/android/widget/listview/ListInHorizontal.java
@@ -43,7 +43,7 @@
             values[i] = ((Integer) i).toString();
         }
 
-        mListView = (ListView) findViewById(R.id.list);
+        mListView = findViewById(R.id.list);
         mListView.setAdapter(new ArrayAdapter<String>(this,
                 android.R.layout.simple_list_item_1, values));
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java b/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
index d5d7261..76814fb 100644
--- a/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
+++ b/core/tests/coretests/src/android/widget/listview/ListRecyclerProfiling.java
@@ -38,14 +38,14 @@
             values[i] = ((Integer) i).toString();
         }
 
-        ListView listView = (ListView) findViewById(R.id.list);
+        ListView listView = findViewById(R.id.list);
 
         ViewDebug.startRecyclerTracing("SimpleList", listView);
 
         listView.setAdapter(new ArrayAdapter<String>(this,
                 android.R.layout.simple_list_item_1, values));
 
-        ImageButton stopProfiling = (ImageButton) findViewById(R.id.pause);
+        ImageButton stopProfiling = findViewById(R.id.pause);
         stopProfiling.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 ViewDebug.stopRecyclerTracing();
diff --git a/core/tests/coretests/src/android/widget/listview/ListScrollListener.java b/core/tests/coretests/src/android/widget/listview/ListScrollListener.java
index 58a31dc..f349dc6 100644
--- a/core/tests/coretests/src/android/widget/listview/ListScrollListener.java
+++ b/core/tests/coretests/src/android/widget/listview/ListScrollListener.java
@@ -46,7 +46,7 @@
             values[i] = ((Integer)i).toString();
         }
         
-        mText = (TextView) findViewById(R.id.text);
+        mText = findViewById(R.id.text);
         setListAdapter(new ArrayAdapter<String>(this,
                 android.R.layout.simple_list_item_1, values));
 
diff --git a/core/tests/coretests/src/android/widget/listview/ListThrasher.java b/core/tests/coretests/src/android/widget/listview/ListThrasher.java
index ba3d590..0237a95 100644
--- a/core/tests/coretests/src/android/widget/listview/ListThrasher.java
+++ b/core/tests/coretests/src/android/widget/listview/ListThrasher.java
@@ -112,7 +112,7 @@
 
         setContentView(R.layout.list_thrasher);
 
-        mText = (TextView) findViewById(R.id.text);
+        mText = findViewById(R.id.text);
         mAdapter = new ThrashListAdapter(this);
         setListAdapter(mAdapter);
 
diff --git a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
index 9cc8544..afc275f 100644
--- a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
+++ b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisible.java
@@ -43,8 +43,8 @@
         final Rect rect = new Rect();
         final View childToMakeVisible = findViewById(R.id.childToMakeVisible);
 
-        final TextView topBlob = (TextView) findViewById(R.id.topBlob);
-        final TextView bottomBlob = (TextView) findViewById(R.id.bottomBlob);
+        final TextView topBlob = findViewById(R.id.topBlob);
+        final TextView bottomBlob = findViewById(R.id.bottomBlob);
 
         // estimate to get blobs larger than screen
         int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
diff --git a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
index 0e2586d..731b25a 100644
--- a/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
+++ b/core/tests/coretests/src/android/widget/scroll/RequestRectangleVisibleWithInternalScroll.java
@@ -53,11 +53,11 @@
 
         setContentView(R.layout.scroll_to_rect_with_internal_scroll);
 
-        mTextBlob = (TextView) findViewById(R.id.blob);
+        mTextBlob = findViewById(R.id.blob);
         mTextBlob.scrollBy(0, scrollYofBlob);
 
 
-        mScrollToBlob = (Button) findViewById(R.id.scrollToBlob);
+        mScrollToBlob = findViewById(R.id.scrollToBlob);
         mScrollToBlob.setOnClickListener(new View.OnClickListener() {
 
             public void onClick(View v) {
diff --git a/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java b/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
index 4d0892c..027ea0f 100644
--- a/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
+++ b/core/tests/coretests/src/android/widget/scroll/ScrollViewButtonsAndLabels.java
@@ -66,8 +66,8 @@
         int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
         mNumGroups = screenHeight / 30;
 
-        mScrollView = (ScrollView) findViewById(R.id.scrollView);
-        mLinearLayout = (LinearLayout) findViewById(R.id.layout);
+        mScrollView = findViewById(R.id.scrollView);
+        mLinearLayout = findViewById(R.id.layout);
 
         LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
                 LinearLayout.LayoutParams.MATCH_PARENT,
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
index 686f75b..515e558 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodSubtypeSwitchingControllerTest.java
@@ -75,8 +75,7 @@
         }
         final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
                 DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
-                DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod,
-                false /* supportsDismissingWindow */);
+                DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod);
         if (subtypes == null) {
             items.add(new ImeSubtypeListItem(imeName, null /* variableName */, imi,
                     NOT_A_SUBTYPE_ID, null, SYSTEM_LOCALE));
@@ -112,8 +111,7 @@
                 .build());
         final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
                 DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
-                DUMMY_FORCE_DEFAULT, true /* supportsSwitchingToNextInputMethod */,
-                false /* supportsDismissingWindow */);
+                DUMMY_FORCE_DEFAULT, true /* supportsSwitchingToNextInputMethod */);
         return new ImeSubtypeListItem(imeName, subtypeName, imi, subtypeIndex, subtypeLocale,
                 systemLocale);
     }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
index 2b0ae21..d8de70c 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
@@ -249,4 +249,65 @@
         assertEquals(2, bi.getUidStats().get(UID).getJobStats().size());
         bi.noteJobFinishLocked(jobName2, UID);
     }
+
+    @SmallTest
+    public void testSyncs() throws Exception {
+        final MockClocks clocks = new MockClocks();
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+        final String syncName = "sync_name";
+        long curr = 0; // realtime in us
+
+        // On battery
+        curr = 1000 * (clocks.realtime = clocks.uptime = 100);
+        bi.updateTimeBasesLocked(true, false, curr, curr); // on battery
+        // App in foreground
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+
+        // Start timer
+        curr = 1000 * (clocks.realtime = clocks.uptime = 151);
+        bi.noteSyncStartLocked(syncName, UID);
+
+        // Stop timer
+        curr = 1000 * (clocks.realtime = clocks.uptime = 161);
+        bi.noteSyncFinishLocked(syncName, UID);
+
+        // Move to background
+        curr = 1000 * (clocks.realtime = clocks.uptime = 202);
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+
+        // Start timer
+        curr = 1000 * (clocks.realtime = clocks.uptime = 254);
+        bi.noteSyncStartLocked(syncName, UID);
+
+        // Off battery
+        curr = 1000 * (clocks.realtime = clocks.uptime = 305);
+        bi.updateTimeBasesLocked(false, false, curr, curr); // off battery
+
+        // Stop timer
+        curr = 1000 * (clocks.realtime = clocks.uptime = 409);
+        bi.noteSyncFinishLocked(syncName, UID);
+
+        // Test
+        curr = 1000 * (clocks.realtime = clocks.uptime = 657);
+        final ArrayMap<String, ? extends BatteryStats.Timer> syncs =
+                bi.getUidStats().get(UID).getSyncStats();
+        assertEquals(1, syncs.size());
+        BatteryStats.Timer timer = syncs.valueAt(0);
+        BatteryStats.Timer bgTimer = timer.getSubTimer();
+        long time = timer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
+        int count = timer.getCountLocked(STATS_SINCE_CHARGED);
+        int bgCount = bgTimer.getCountLocked(STATS_SINCE_CHARGED);
+        long bgTime = bgTimer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
+        assertEquals((161 - 151 + 305 - 254) * 1000, time);
+        assertEquals(2, count);
+        assertEquals(1, bgCount);
+        assertEquals((305 - 254) * 1000, bgTime);
+
+        // Test that a second sync is separate.
+        curr = 1000 * (clocks.realtime = clocks.uptime = 3000);
+        final String syncName2 = "second_sync";
+        bi.noteSyncStartLocked(syncName2, UID);
+        assertEquals(2, bi.getUidStats().get(UID).getSyncStats().size());
+        bi.noteSyncFinishLocked(syncName2, UID);
+    }
 }
diff --git a/core/tests/overlaytests/OverlayAppFiltered/Android.mk b/core/tests/overlaytests/OverlayAppFiltered/Android.mk
new file mode 100644
index 0000000..8ba21df
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFiltered/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JAVA_LIBRARIES += legacy-test
+
+LOCAL_SDK_VERSION := system_current
+
+LOCAL_PACKAGE_NAME := com.android.overlaytest.filtered_app_overlay
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/OverlayAppFiltered/AndroidManifest.xml b/core/tests/overlaytests/OverlayAppFiltered/AndroidManifest.xml
new file mode 100644
index 0000000..5b7950a
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFiltered/AndroidManifest.xml
@@ -0,0 +1,9 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.overlaytest.filtered_app_overlay"
+        android:versionCode="1"
+        android:versionName="1.0">
+        <overlay android:targetPackage="com.android.overlaytest"
+                android:requiredSystemPropertyName="persist.oem.overlay.test"
+                android:requiredSystemPropertyValue="foo"
+                android:priority="3"/>
+</manifest>
diff --git a/core/tests/overlaytests/OverlayAppFiltered/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/OverlayAppFiltered/res/raw/lorem_ipsum.txt
new file mode 100644
index 0000000..0954ced
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFiltered/res/raw/lorem_ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum: filtered overlays.
diff --git a/core/tests/overlaytests/OverlayAppFiltered/res/values/config.xml b/core/tests/overlaytests/OverlayAppFiltered/res/values/config.xml
new file mode 100644
index 0000000..60b94ee
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFiltered/res/values/config.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="str">filtered</string>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppFiltered/res/xml/integer.xml b/core/tests/overlaytests/OverlayAppFiltered/res/xml/integer.xml
new file mode 100644
index 0000000..e2652b7
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFiltered/res/xml/integer.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<integer value="3"/>
diff --git a/core/tests/overlaytests/OverlayAppFirst/Android.mk b/core/tests/overlaytests/OverlayAppFirst/Android.mk
index ee991fc..51f4487 100644
--- a/core/tests/overlaytests/OverlayAppFirst/Android.mk
+++ b/core/tests/overlaytests/OverlayAppFirst/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_LIBRARIES += legacy-test
 
 LOCAL_SDK_VERSION := current
 
diff --git a/core/tests/overlaytests/OverlayAppSecond/Android.mk b/core/tests/overlaytests/OverlayAppSecond/Android.mk
index 87402c43..b3cfd18 100644
--- a/core/tests/overlaytests/OverlayAppSecond/Android.mk
+++ b/core/tests/overlaytests/OverlayAppSecond/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_LIBRARIES += legacy-test
 
 LOCAL_SDK_VERSION := current
 
diff --git a/core/tests/overlaytests/OverlayTest/Android.mk b/core/tests/overlaytests/OverlayTest/Android.mk
index 4767e52..964348f 100644
--- a/core/tests/overlaytests/OverlayTest/Android.mk
+++ b/core/tests/overlaytests/OverlayTest/Android.mk
@@ -7,6 +7,8 @@
 
 LOCAL_DEX_PREOPT := false
 
+LOCAL_JAVA_LIBRARIES += legacy-test
+
 LOCAL_MODULE_PATH := $(TARGET_OUT)/app
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/core/tests/overlaytests/OverlayTestOverlay/Android.mk b/core/tests/overlaytests/OverlayTestOverlay/Android.mk
index b1327f71..5265d91 100644
--- a/core/tests/overlaytests/OverlayTestOverlay/Android.mk
+++ b/core/tests/overlaytests/OverlayTestOverlay/Android.mk
@@ -3,7 +3,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_LIBRARIES += legacy-test
 
 LOCAL_SDK_VERSION := current
 
diff --git a/core/tests/overlaytests/testrunner.py b/core/tests/overlaytests/testrunner.py
index 2aa25ad..e88805e8 100755
--- a/core/tests/overlaytests/testrunner.py
+++ b/core/tests/overlaytests/testrunner.py
@@ -13,6 +13,7 @@
 TASK_DISABLE_OVERLAYS = 'disable overlays'
 TASK_ENABLE_MULTIPLE_OVERLAYS = 'enable multiple overlays'
 TASK_ENABLE_SINGLE_OVERLAY = 'enable single overlay'
+TASK_ENABLE_FILTERED_OVERLAYS = 'enable filtered overlays'
 TASK_FILE_EXISTS_TEST = 'test (file exists)'
 TASK_GREP_IDMAP_TEST = 'test (grep idmap)'
 TASK_MD5_TEST = 'test (md5)'
@@ -25,6 +26,7 @@
 TASK_ROOT = 'root'
 TASK_REMOUNT = 'remount'
 TASK_RM = 'rm'
+TASK_SETPROP = 'setprop'
 TASK_SETUP_IDMAP_PATH = 'setup idmap --path'
 TASK_SETUP_IDMAP_SCAN = 'setup idmap --scan'
 TASK_START = 'start'
@@ -188,7 +190,10 @@
         return "%s -> %s" % (self.src, self.dest)
 
     def execute(self):
-        src = os.getenv('OUT') + "/" + self.src
+        src = os.getenv('OUT')
+        if (src is None):
+          return 1, "", "Unable to proceed - $OUT environment var not set\n"
+        src += "/" + self.src
         argv = shlex.split(adb + ' push %s %s' % (src, self.dest))
         proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         (stdout, stderr) = proc.communicate()
@@ -219,10 +224,24 @@
 
     def execute(self):
         returncode, stdout, stderr = _adb_shell('ls %s' % self.path)
-        if returncode != 0 and stdout.endswith(': No such file or directory\n'):
+        if returncode != 0 and stderr.endswith(': No such file or directory\n'):
             return 0, "", ""
         return _adb_shell('rm -r %s' % self.path)
 
+class SetPropTask:
+    def __init__(self, prop, value):
+        self.prop = prop
+        self.value = value
+
+    def get_type(self):
+        return TASK_SETPROP
+
+    def get_name(self):
+        return self.prop
+
+    def execute(self):
+      return _adb_shell('setprop %s %s' % (self.prop, self.value))
+
 class IdmapPathTask:
     def __init__(self, path_target_apk, path_overlay_apk, path_idmap):
         self.path_target_apk = path_target_apk
@@ -236,7 +255,7 @@
         return self.path_idmap
 
     def execute(self):
-        return _adb_shell('su system idmap --path "%s" "%s" "%s"' % (self.path_target_apk, self.path_overlay_apk, self.path_idmap))
+        return _adb_shell('su system idmap --scan "%s" "%s" "%s" "%s"' % (self.target_pkg_name, self.target_pkg, self.idmap_dir, self.overlay_dir))
 
 class IdmapScanTask:
     def __init__(self, overlay_dir, target_pkg_name, target_pkg, idmap_dir, symlink_dir):
@@ -411,8 +430,12 @@
         RmTask("/data/resource-cache/vendor@overlay@framework_b.apk@idmap"),
         RmTask("/vendor/overlay/app_a.apk"),
         RmTask("/vendor/overlay/app_b.apk"),
+        RmTask("/vendor/overlay/app_c.apk"),
         RmTask("/data/resource-cache/vendor@overlay@app_a.apk@idmap"),
         RmTask("/data/resource-cache/vendor@overlay@app_b.apk@idmap"),
+        RmTask("/data/resource-cache/vendor@overlay@app_c.apk@idmap"),
+        SetPropTask('persist.oem.overlay.test', '""'),
+        RmTask("/data/property/persist.oem.overlay.test"),
     ]
     return CompoundTask(TASK_DISABLE_OVERLAYS, tasks)
 
@@ -435,9 +458,23 @@
         PushTask('/data/app/com.android.overlaytest.overlay/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_b.apk'),
         PushTask('/data/app/com.android.overlaytest.first_app_overlay/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
         PushTask('/data/app/com.android.overlaytest.second_app_overlay/com.android.overlaytest.second_app_overlay.apk', '/vendor/overlay/app_b.apk'),
+        PushTask('/data/app/com.android.overlaytest.filtered_app_overlay/com.android.overlaytest.filtered_app_overlay.apk', '/vendor/overlay/app_c.apk'),
     ]
     return CompoundTask(TASK_ENABLE_MULTIPLE_OVERLAYS, tasks)
 
+def _create_enable_filtered_overlays_task():
+      tasks = [
+        _create_disable_overlays_task(),
+        SetPropTask('persist.oem.overlay.test', 'foo'),
+        MkdirTask('/system/vendor'),
+        MkdirTask('/vendor/overlay'),
+        PushTask('/data/app/com.android.overlaytest.overlay/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_b.apk'),
+        PushTask('/data/app/com.android.overlaytest.first_app_overlay/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
+        PushTask('/data/app/com.android.overlaytest.second_app_overlay/com.android.overlaytest.second_app_overlay.apk', '/vendor/overlay/app_b.apk'),
+        PushTask('/data/app/com.android.overlaytest.filtered_app_overlay/com.android.overlaytest.filtered_app_overlay.apk', '/vendor/overlay/app_c.apk'),
+      ]
+      return CompoundTask(TASK_ENABLE_FILTERED_OVERLAYS, tasks)
+
 def _create_setup_idmap_path_task(idmaps, symlinks):
     tasks = [
         _create_enable_single_overlay_task(),
@@ -450,12 +487,11 @@
 
 def _create_setup_idmap_scan_task(idmaps, symlinks):
     tasks = [
-        _create_enable_single_overlay_task(),
+        _create_enable_filtered_overlays_task(),
         RmTask(symlinks),
         RmTask(idmaps),
         MkdirTask(idmaps),
         MkdirTask(symlinks),
-        _create_enable_multiple_overlays_task(),
     ]
     return CompoundTask(TASK_SETUP_IDMAP_SCAN, tasks)
 
@@ -538,7 +574,7 @@
             help='do not rebuild test projects')
     parser.add_option('-i', '--test-idmap', action='store_true',
             dest='test_idmap', default=False,
-            help='run tests for single overlay')
+            help='run tests for idmap')
     parser.add_option('-0', '--test-no-overlay', action='store_true',
             dest='test_no_overlay', default=False,
             help='run tests without any overlay')
@@ -548,16 +584,21 @@
     parser.add_option('-2', '--test-multiple-overlays', action='store_true',
             dest='test_multiple_overlays', default=False,
             help='run tests for multiple overlays')
+    parser.add_option('-3', '--test-filtered-overlays', action='store_true',
+            dest='test_filtered_overlays', default=False,
+            help='run tests for filtered (sys prop) overlays')
     return parser
 
 if __name__ == '__main__':
     opt_parser = _create_opt_parser()
     opts, args = opt_parser.parse_args(sys.argv[1:])
-    if not opts.test_idmap and not opts.test_no_overlay and not opts.test_single_overlay and not opts.test_multiple_overlays:
+    if not opts.test_idmap and not opts.test_no_overlay and not opts.test_single_overlay and not opts.test_multiple_overlays and not opts.test_filtered_overlays:
         opts.test_idmap = True
         opts.test_no_overlay = True
         opts.test_single_overlay = True
         opts.test_multiple_overlays = True
+        opts.test_filtered_overlays = True
+
     if len(args) > 0:
         opt_parser.error("unexpected arguments: %s" % " ".join(args))
         # will never reach this: opt_parser.error will call sys.exit
@@ -580,6 +621,7 @@
         tasks.append(CompilationTask('OverlayTestOverlay/Android.mk'))
         tasks.append(CompilationTask('OverlayAppFirst/Android.mk'))
         tasks.append(CompilationTask('OverlayAppSecond/Android.mk'))
+        tasks.append(CompilationTask('OverlayAppFiltered/Android.mk'))
 
     # remount filesystem, install test project
     tasks.append(RootTask())
@@ -600,13 +642,13 @@
         tasks.append(GrepIdmapTest(idmaps + '/a.idmap', 'bool/config_annoy_dianne', 1))
 
         # idmap --scan
-        idmap = idmaps + '/vendor@overlay@framework_b.apk@idmap'
         tasks.append(StopTask())
         tasks.append(_create_setup_idmap_scan_task(idmaps, symlinks))
         tasks.append(StartTask())
         tasks.append(IdmapScanTask('/vendor/overlay', 'android', '/system/framework/framework-res.apk', idmaps, symlinks))
-        tasks.append(FileExistsTest(idmap))
-        tasks.append(GrepIdmapTest(idmap, 'bool/config_annoy_dianne', 1))
+        tasks.append(FileExistsTest(idmaps + '/vendor@overlay@framework_b.apk@idmap'))
+        tasks.append(GrepIdmapTest(idmaps + '/vendor@overlay@framework_b.apk@idmap', 'bool/config_annoy_dianne', 1))
+
 
         # overlays.list
         overlays_list_path = idmaps + '/overlays.list'
@@ -620,27 +662,38 @@
         tasks.append(RmTask(symlinks))
         tasks.append(RmTask(idmaps))
 
-    # test no overlay
+    # test no overlay: all overlays cleared
     if opts.test_no_overlay:
         tasks.append(StopTask())
         tasks.append(_create_disable_overlays_task())
         tasks.append(StartTask())
         tasks.append(InstrumentationTask('com.android.overlaytest.WithoutOverlayTest'))
 
-    # test single overlay
+    # test single overlay: one overlay (a)
     if opts.test_single_overlay:
         tasks.append(StopTask())
         tasks.append(_create_enable_single_overlay_task())
         tasks.append(StartTask())
         tasks.append(InstrumentationTask('com.android.overlaytest.WithOverlayTest'))
 
-    # test multiple overlays
+    # test multiple overlays: all overlays - including 'disabled' filtered
+    # overlay (system property unset) so expect 'b[p=2]' overrides 'a[p=1]' but
+    # 'c[p=3]' should be ignored
     if opts.test_multiple_overlays:
         tasks.append(StopTask())
         tasks.append(_create_enable_multiple_overlays_task())
         tasks.append(StartTask())
         tasks.append(InstrumentationTask('com.android.overlaytest.WithMultipleOverlaysTest'))
 
+    # test filtered overlays: all overlays - including 'enabled' filtered
+    # overlay (system property set/matched) so expect c[p=3] to override both a
+    # & b where applicable
+    if opts.test_filtered_overlays:
+        tasks.append(StopTask())
+        tasks.append(_create_enable_filtered_overlays_task())
+        tasks.append(StartTask())
+        tasks.append(InstrumentationTask('com.android.overlaytest.WithFilteredOverlaysTest'))
+
     ignored_errors = 0
     for t in tasks:
         type = t.get_type()
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index ec653d0..22d7541 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -40,6 +40,7 @@
 
     <privapp-permissions package="com.android.defcontainer">
         <permission name="android.permission.ACCESS_CACHE_FILESYSTEM"/>
+        <permission name="android.permission.ALLOCATE_AGGRESSIVE"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
     </privapp-permissions>
@@ -228,6 +229,7 @@
         <permission name="android.permission.MANAGE_FINGERPRINT"/>
         <permission name="android.permission.MANAGE_USB"/>
         <permission name="android.permission.MANAGE_USERS"/>
+        <permission name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE" />
         <permission name="android.permission.MASTER_CLEAR"/>
         <permission name="android.permission.MODIFY_PHONE_STATE"/>
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 3dab1f7..39b0bc7 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -277,6 +277,9 @@
         <font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
         <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
     </family>
+    <family lang="und-Adlm">
+        <font weight="400" style="normal">NotoSansAdlam-Regular.ttf</font>
+    </family>
     <family lang="und-Avst">
         <font weight="400" style="normal">NotoSansAvestan-Regular.ttf</font>
     </family>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 91906850..599406c 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -916,18 +916,20 @@
      * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
      *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
      *                 instead of transparent.
-     * @param colorSpace The color space of the bitmap. If null,
-     *                   {@link ColorSpace.Named#SRGB sRGB} is assumed. This argument is
-     *                   ignored if the config is not {@link Config#ARGB_8888}.
+     * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16},
+     *                   {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the
+     *                   config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB}
+     *                   is assumed.
      *
      * @throws IllegalArgumentException if the width or height are <= 0, if
      *         Config is Config.HARDWARE (because hardware bitmaps are always
      *         immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB},
-     *         or if the specified color space's transfer function is not an
-     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
+     *         if the specified color space's transfer function is not an
+     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if
+     *         the color space is null
      */
     public static Bitmap createBitmap(int width, int height, @NonNull Config config,
-            boolean hasAlpha, @Nullable ColorSpace colorSpace) {
+            boolean hasAlpha, @NonNull ColorSpace colorSpace) {
         return createBitmap(null, width, height, config, hasAlpha, colorSpace);
     }
 
@@ -951,7 +953,8 @@
      */
     public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
             @NonNull Config config, boolean hasAlpha) {
-        return createBitmap(display, width, height, config, hasAlpha, null);
+        return createBitmap(display, width, height, config, hasAlpha,
+                ColorSpace.get(ColorSpace.Named.SRGB));
     }
 
     /**
@@ -968,27 +971,32 @@
      * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
      *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
      *                 instead of transparent.
-     * @param colorSpace The color space of the bitmap. If null,
-     *                   {@link ColorSpace.Named#SRGB sRGB} is assumed. This argument is
-     *                   ignored if the config is not {@link Config#ARGB_8888}.
+     * @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16},
+     *                   {@link ColorSpace.Named#EXTENDED_SRGB scRGB} is assumed, and if the
+     *                   config is not {@link Config#ARGB_8888}, {@link ColorSpace.Named#SRGB sRGB}
+     *                   is assumed.
      *
      * @throws IllegalArgumentException if the width or height are <= 0, if
      *         Config is Config.HARDWARE (because hardware bitmaps are always
      *         immutable), if the specified color space is not {@link ColorSpace.Model#RGB RGB},
-     *         or if the specified color space's transfer function is not an
-     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
+     *         if the specified color space's transfer function is not an
+     *         {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}, or if
+     *         the color space is null
      */
     public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
-            @NonNull Config config, boolean hasAlpha, @Nullable ColorSpace colorSpace) {
+            @NonNull Config config, boolean hasAlpha, @NonNull ColorSpace colorSpace) {
         if (width <= 0 || height <= 0) {
             throw new IllegalArgumentException("width and height must be > 0");
         }
         if (config == Config.HARDWARE) {
             throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE");
         }
+        if (colorSpace == null) {
+            throw new IllegalArgumentException("can't create bitmap without a color space");
+        }
 
         Bitmap bm;
-        if (colorSpace == null || config != Config.ARGB_8888) {
+        if (config != Config.ARGB_8888) {
             bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, null, null);
         } else {
             if (!(colorSpace instanceof ColorSpace.Rgb)) {
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index ceedc1f..3b272c8 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -43,7 +43,6 @@
          * the same result from the decoder as if null were passed.
          */
         public Options() {
-            inDither = false;
             inScaled = true;
             inPremultiplied = true;
         }
@@ -114,8 +113,8 @@
 
         /**
          * If set to true, the decoder will return null (no bitmap), but
-         * the out... fields will still be set, allowing the caller to query
-         * the bitmap without having to allocate the memory for its pixels.
+         * the <code>out...</code> fields will still be set, allowing the caller to
+         * query the bitmap without having to allocate the memory for its pixels.
          */
         public boolean inJustDecodeBounds;
 
@@ -144,6 +143,35 @@
         public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
 
         /**
+         * <p>If this is non-null, the decoder will try to decode into this
+         * color space. If it is null, or the request cannot be met,
+         * the decoder will pick either the color space embedded in the image
+         * or the color space best suited for the requested image configuration
+         * (for instance {@link ColorSpace.Named#SRGB sRGB} for
+         * the {@link Bitmap.Config#ARGB_8888} configuration).</p>
+         *
+         * <p>{@link Bitmap.Config#RGBA_F16} always uses the
+         * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space).
+         * Bitmaps in other configurations without an embedded color space are
+         * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
+         *
+         * <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are
+         * currently supported. An <code>IllegalArgumentException</code> will
+         * be thrown by the decode methods when setting a non-RGB color space
+         * such as {@link ColorSpace.Named#CIE_LAB Lab}.</p>
+         *
+         * <p class="note">The specified color space's transfer function must be
+         * an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}. An
+         * <code>IllegalArgumentException</code> will be thrown by the decode methods
+         * if calling {@link ColorSpace.Rgb#getTransferParameters()} on the
+         * specified color space returns null.</p>
+         *
+         * <p>After decode, the bitmap's color space is stored in
+         * {@link #outColorSpace}.</p>
+         */
+        public ColorSpace inPreferredColorSpace = null;
+
+        /**
          * If true (which is the default), the resulting bitmap will have its
          * color channels pre-multipled by the alpha channel.
          *
@@ -403,9 +431,22 @@
         }
 
         static void validate(Options opts) {
-            if (opts != null && opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) {
+            if (opts == null) return;
+
+            if (opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) {
                 throw new IllegalArgumentException("Bitmaps with Config.HARWARE are always immutable");
             }
+
+            if (opts.inPreferredColorSpace != null) {
+                if (!(opts.inPreferredColorSpace instanceof ColorSpace.Rgb)) {
+                    throw new IllegalArgumentException("The destination color space must use the " +
+                            "RGB color model");
+                }
+                if (((ColorSpace.Rgb) opts.inPreferredColorSpace).getTransferParameters() == null) {
+                    throw new IllegalArgumentException("The destination color space must use an " +
+                            "ICC parametric transfer function");
+                }
+            }
         }
     }
 
@@ -421,7 +462,9 @@
      *         size be returned (in opts.outWidth and opts.outHeight)
      * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
      *         is {@link android.graphics.Bitmap.Config#HARDWARE}
-     *         and {@link BitmapFactory.Options#inMutable} is set.
+     *         and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+     *         is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+     *         function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
      */
     public static Bitmap decodeFile(String pathName, Options opts) {
         validate(opts);
@@ -463,7 +506,9 @@
      * resources, which we pass to be able to scale the bitmap accordingly.
      * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
      *         is {@link android.graphics.Bitmap.Config#HARDWARE}
-     *         and {@link BitmapFactory.Options#inMutable} is set.
+     *         and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+     *         is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+     *         function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
      */
     public static Bitmap decodeResourceStream(Resources res, TypedValue value,
             InputStream is, Rect pad, Options opts) {
@@ -501,7 +546,9 @@
      *         size be returned (in opts.outWidth and opts.outHeight)
      * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
      *         is {@link android.graphics.Bitmap.Config#HARDWARE}
-     *         and {@link BitmapFactory.Options#inMutable} is set.
+     *         and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+     *         is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+     *         function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
      */
     public static Bitmap decodeResource(Resources res, int id, Options opts) {
         validate(opts);
@@ -559,7 +606,9 @@
      *         size be returned (in opts.outWidth and opts.outHeight)
      * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
      *         is {@link android.graphics.Bitmap.Config#HARDWARE}
-     *         and {@link BitmapFactory.Options#inMutable} is set.
+     *         and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+     *         is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+     *         function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
      */
     public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
         if ((offset | length) < 0 || data.length < offset + length) {
@@ -641,7 +690,9 @@
      *         size be returned (in opts.outWidth and opts.outHeight)
      * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
      *         is {@link android.graphics.Bitmap.Config#HARDWARE}
-     *         and {@link BitmapFactory.Options#inMutable} is set.
+     *         and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+     *         is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+     *         function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
      *
      * <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT},
      * if {@link InputStream#markSupported is.markSupported()} returns true,
@@ -720,7 +771,9 @@
      * @return the decoded bitmap, or null
      * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
      *         is {@link android.graphics.Bitmap.Config#HARDWARE}
-     *         and {@link BitmapFactory.Options#inMutable} is set.
+     *         and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+     *         is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+     *         function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
      */
     public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
         validate(opts);
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index 04abca1..2da27c7 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -180,7 +180,9 @@
      *         decoded.
      * @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
      *         is {@link android.graphics.Bitmap.Config#HARDWARE}
-     *         and {@link BitmapFactory.Options#inMutable} is set.
+     *         and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+     *         is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+     *         function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
      */
     public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
         BitmapFactory.Options.validate(options);
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 7e6756e..5577f53 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -41,35 +41,16 @@
      * @param tileY The tiling mode for y to draw the bitmap in.
      */
     public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
-        set(bitmap, tileX, tileY);
+        this(bitmap, tileX.nativeInt, tileY.nativeInt);
     }
 
     private BitmapShader(Bitmap bitmap, int tileX, int tileY) {
-        setInternal(bitmap, tileX, tileY);
-    }
-
-    /**
-     * Reinitialize the BitmapShader's Bitmap and tile modes.
-     *
-     * @param bitmap The bitmap to use inside the shader
-     * @param tileX The tiling mode for x to draw the bitmap in.
-     * @param tileY The tiling mode for y to draw the bitmap in.
-     */
-    public void set(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY) {
-        if (tileX == null || tileY == null) {
-            throw new IllegalArgumentException();
-        }
-        setInternal(bitmap, tileX.nativeInt, tileY.nativeInt);
-    }
-
-    private void setInternal(Bitmap bitmap, int tileX, int tileY) {
         if (bitmap == null) {
             throw new IllegalArgumentException("Bitmap must be non-null");
         }
         if (bitmap == mBitmap && tileX == mTileX && tileY == mTileY) {
             return;
         }
-        discardNativeInstance();
         mBitmap = bitmap;
         mTileX = tileX;
         mTileY = tileY;
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index 218b857c..8cbf921 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -538,7 +538,7 @@
     /**
      * Returns the value of the alpha component in the range \([0..1]\).
      * Calling this method is equivalent to
-     * <code>getComponent(getComponentCount())</code>.
+     * <code>getComponent(getComponentCount() - 1)</code>.
      *
      * @see #red()
      * @see #green()
@@ -690,9 +690,8 @@
      * Returns the color space encoded in the specified color long.
      *
      * @param color The color long whose color space to extract
-     * @return A non-null color space instance. If the color long encodes
-     * an unknown or invalid color space, the {@link ColorSpace.Named#SRGB sRGB}
-     * color space is returned
+     * @return A non-null color space instance
+     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
      *
      * @see #red(long)
      * @see #green(long)
@@ -787,6 +786,7 @@
      *
      * @param color The color to test
      * @return True if the color is in the sRGB color space, false otherwise
+     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
      *
      * @see #isInColorSpace(long, ColorSpace)
      * @see #isWideGamut(long)
@@ -802,6 +802,7 @@
      *
      * @param color The color to test
      * @return True if the color is in a wide-gamut color space, false otherwise
+     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
      *
      * @see #isInColorSpace(long, ColorSpace)
      * @see #isSrgb(long)
@@ -831,6 +832,7 @@
      * a color space conversion is applied if needed.
      *
      * @return An ARGB color in the sRGB color space
+     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
      */
     @ColorInt
     public static int toArgb(@ColorLong long color) {
@@ -873,6 +875,7 @@
      *
      * @param color The color long to create a <code>Color</code> from
      * @return A non-null instance of {@link Color}
+     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
      */
     @NonNull
     public static Color valueOf(@ColorLong long color) {
@@ -1100,6 +1103,7 @@
      * @param color The color long to convert
      * @param colorSpace The destination color space
      * @return A color long in the destination color space
+     * @throws IllegalArgumentException If the encoded color space is invalid or unknown
      */
     @ColorLong
     public static long convert(@ColorLong long color, @NonNull ColorSpace colorSpace) {
@@ -1206,7 +1210,7 @@
      * @return A value between 0 (darkest black) and 1 (lightest white)
      *
      * @throws IllegalArgumentException If the specified color's color space
-     * does not use the {@link ColorSpace.Model#RGB RGB} color model
+     * is unknown or does not use the {@link ColorSpace.Model#RGB RGB} color model
      */
     public static float luminance(@ColorLong long color) {
         ColorSpace colorSpace = colorSpace(color);
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 61f6cc5..9201a2e 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -73,6 +73,8 @@
      * @see #getColorMatrix(ColorMatrix)
      * @see #setColorMatrixArray(float[])
      * @see ColorMatrix#reset()
+     *
+     * @hide
      */
     public void setColorMatrix(@Nullable ColorMatrix matrix) {
         discardNativeInstance();
@@ -99,6 +101,8 @@
      *
      * @throws ArrayIndexOutOfBoundsException if the specified array's
      *         length is < 20
+     *
+     * @hide
      */
     public void setColorMatrixArray(@Nullable float[] array) {
         // called '...Array' so that passing null isn't ambiguous
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index f1804e5..f2957a3 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -885,8 +885,32 @@
     }
 
     /**
-     * Returns the name of this color space. The name is never null
-     * and contains always at least 1 character.
+     * <p>Returns the name of this color space. The name is never null
+     * and contains always at least 1 character.</p>
+     *
+     * <p>Color space names are recommended to be unique but are not
+     * guaranteed to be. There is no defined format but the name usually
+     * falls in one of the following categories:</p>
+     * <ul>
+     *     <li>Generic names used to identify color spaces in non-RGB
+     *     color models. For instance: {@link Named#CIE_LAB Generic L*a*b*}.</li>
+     *     <li>Names tied to a particular specification. For instance:
+     *     {@link Named#SRGB sRGB IEC61966-2.1} or
+     *     {@link Named#ACES SMPTE ST 2065-1:2012 ACES}.</li>
+     *     <li>Ad-hoc names, often generated procedurally or by the user
+     *     during a calibration workflow. These names often contain the
+     *     make and model of the display.</li>
+     * </ul>
+     *
+     * <p>Because the format of color space names is not defined, it is
+     * not recommended to programmatically identify a color space by its
+     * name alone. Names can be used as a first approximation.</p>
+     *
+     * <p>It is however perfectly acceptable to display color space names to
+     * users in a UI, or in debuggers and logs. When displaying a color space
+     * name to the user, it is recommended to add extra information to avoid
+     * ambiguities: color model, a representation of the color space's gamut,
+     * white point, etc.</p>
      *
      * @return A non-null String of length >= 1
      */
@@ -1314,9 +1338,8 @@
     }
 
     /**
-     * <p>Returns an instance of {@link ColorSpace} whose ID matches the specified
-     * ID. If the ID is < 0 or &gt; {@link #MAX_ID}, calling this method is equivalent
-     * to calling <code>get(Named.SRGB)</code>.</p>
+     * <p>Returns an instance of {@link ColorSpace} whose ID matches the
+     * specified ID.</p>
      *
      * <p>This method always returns the same instance for a given ID.</p>
      *
@@ -1324,11 +1347,14 @@
      *
      * @param index An integer ID between {@link #MIN_ID} and {@link #MAX_ID}
      * @return A non-null {@link ColorSpace} instance
+     * @throws IllegalArgumentException If the ID does not match the ID of one of the
+     *         {@link Named named color spaces}
      */
     @NonNull
     static ColorSpace get(@IntRange(from = MIN_ID, to = MAX_ID) int index) {
         if (index < 0 || index > Named.values().length) {
-            return get(Named.SRGB);
+            throw new IllegalArgumentException("Invalid ID, must be in the range [0.." +
+                    Named.values().length + "]");
         }
         return sNamedColorSpaces[index];
     }
@@ -1566,7 +1592,7 @@
                 Math.abs(a.a - b.a) < 1e-3 &&
                 Math.abs(a.b - b.b) < 1e-3 &&
                 Math.abs(a.c - b.c) < 1e-3 &&
-                Math.abs(a.d - b.d) < 1e-3 &&
+                Math.abs(a.d - b.d) < 2e-3 && // Special case for variations in sRGB OETF/EOTF
                 Math.abs(a.e - b.e) < 1e-3 &&
                 Math.abs(a.f - b.f) < 1e-3 &&
                 Math.abs(a.g - b.g) < 1e-3;
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index 8438bf2..e107ea7 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -59,43 +59,10 @@
     }
 
     private ComposeShader(Shader shaderA, Shader shaderB, int nativeMode) {
-        setInternal(shaderA, shaderB, nativeMode);
-    }
-
-    /**
-     * Reinitialize the ComposeShader's component Shaders and blend mode.
-     *
-     * @param shaderA  The colors from this shader are seen as the "dst" by the mode
-     * @param shaderB  The colors from this shader are seen as the "src" by the mode
-     * @param mode     The PorterDuff mode that combines the colors from the two shaders.
-     */
-    public void set(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode) {
-        setInternal(shaderA, shaderB, mode.porterDuffMode);
-    }
-
-    /**
-     * Reinitialize the ComposeShader's component Shaders and blend mode.
-     *
-     * @param shaderA  The colors from this shader are seen as the "dst" by the mode
-     * @param shaderB  The colors from this shader are seen as the "src" by the mode
-     * @param mode     The PorterDuff mode that combines the colors from the two shaders.
-     */
-    public void set(@NonNull Shader shaderA, @NonNull Shader shaderB,
-            @NonNull PorterDuff.Mode mode) {
-        setInternal(shaderA, shaderB, mode.nativeInt);
-    }
-
-    private void setInternal(Shader shaderA, Shader shaderB, int nativeMode) {
         if (shaderA == null || shaderB == null) {
             throw new IllegalArgumentException("Shader parameters must not be null");
         }
 
-        if (shaderA == mShaderA && shaderB == mShaderB && mPorterDuffMode == nativeMode) {
-            // no work to do...
-            return;
-        }
-
-        discardNativeInstance();
         mShaderA = shaderA;
         mShaderB = shaderB;
         mPorterDuffMode = nativeMode;
@@ -109,16 +76,6 @@
                 mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
     }
 
-    @Override
-    void verifyNativeInstance() {
-        if (mShaderA.getNativeInstance() != mNativeInstanceShaderA
-                || mShaderB.getNativeInstance() != mNativeInstanceShaderB) {
-            // Child shader native instance has been updated,
-            // so our cached native instance is no longer valid - discard it
-            discardNativeInstance();
-        }
-    }
-
     /**
      * @hide
      */
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 4b1b0c6..d9a77e7 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -52,12 +52,19 @@
         mBuilderPtr = nInitBuilder(lang, variant);
     }
 
-    public void freeze() {
+    /**
+     * Finalize the FontFamily creation.
+     *
+     * @return boolean returns false if some error happens in native code, e.g. broken font file is
+     *                 passed, etc.
+     */
+    public boolean freeze() {
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("This FontFamily is already frozen");
         }
         mNativePtr = nCreateFamily(mBuilderPtr);
         mBuilderPtr = 0;
+        return mNativePtr != 0;
     }
 
     public void abortCreation() {
@@ -143,6 +150,25 @@
                 isItalic);
     }
 
+    /**
+     * Allow creating unsupported FontFamily.
+     *
+     * For compatibility reasons, we still need to create a FontFamily object even if Minikin failed
+     * to find any usable 'cmap' table for some reasons, e.g. broken 'cmap' table, no 'cmap' table
+     * encoded with Unicode code points, etc. Without calling this method, the freeze() method will
+     * return null if Minikin fails to find any usable 'cmap' table. By calling this method, the
+     * freeze() won't fail and will create an empty FontFamily. This empty FontFamily is placed at
+     * the top of the fallback chain but is never used. if we don't create this empty FontFamily
+     * and put it at top, bad things (performance regressions, unexpected glyph selection) will
+     * happen.
+     */
+    public void allowUnsupportedFont() {
+        if (mBuilderPtr == 0) {
+            throw new IllegalStateException("Unable to allow unsupported font.");
+        }
+        nAllowUnsupportedFont(mBuilderPtr);
+    }
+
     // TODO: Remove once internal user stop using private API.
     private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
         return nAddFont(builderPtr, font, ttcIndex, -1, -1);
@@ -154,6 +180,9 @@
     private static native long nCreateFamily(long mBuilderPtr);
 
     @CriticalNative
+    private static native void nAllowUnsupportedFont(long builderPtr);
+
+    @CriticalNative
     private static native void nAbort(long mBuilderPtr);
 
     @CriticalNative
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index b0c145b..1578ffb 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -57,8 +57,6 @@
     /**
      * Returns the RGB color used to multiply the source color when the
      * color filter is applied.
-     *
-     * @see #setColorMultiply(int)
      */
     @ColorInt
     public int getColorMultiply() {
@@ -71,6 +69,8 @@
      * The alpha channel of this color is ignored.
      *
      * @see #getColorMultiply()
+     *
+     * @hide
      */
     public void setColorMultiply(@ColorInt int mul) {
         if (mMul != mul) {
@@ -82,8 +82,6 @@
     /**
      * Returns the RGB color that will be added to the source color
      * when the color filter is applied.
-     *
-     * @see #setColorAdd(int)
      */
     @ColorInt
     public int getColorAdd() {
@@ -96,6 +94,8 @@
      * The alpha channel of this color is ignored.
      *
      * @see #getColorAdd()
+     *
+     * @hide
      */
     public void setColorAdd(@ColorInt int add) {
         if (mAdd != add) {
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 0e4cd0a..7139efe 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -57,7 +57,20 @@
     */
     public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
             @Nullable float positions[], @NonNull TileMode tile) {
-        set(x0, y0, x1, y1, colors, positions, tile);
+        if (colors.length < 2) {
+            throw new IllegalArgumentException("needs >= 2 number of colors");
+        }
+        if (positions != null && colors.length != positions.length) {
+            throw new IllegalArgumentException("color and position arrays must be of equal length");
+        }
+        mType = TYPE_COLORS_AND_POSITIONS;
+        mX0 = x0;
+        mY0 = y0;
+        mX1 = x1;
+        mY1 = y1;
+        mColors = colors.clone();
+        mPositions = positions != null ? positions.clone() : null;
+        mTileMode = tile;
     }
 
     /**
@@ -74,56 +87,6 @@
     public LinearGradient(float x0, float y0, float x1, float y1,
             @ColorInt int color0, @ColorInt int color1,
             @NonNull TileMode tile) {
-        set(x0, y0, x1, y1, color0, color1, tile);
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param x0           The x-coordinate for the start of the gradient line
-     * @param y0           The y-coordinate for the start of the gradient line
-     * @param x1           The x-coordinate for the end of the gradient line
-     * @param y1           The y-coordinate for the end of the gradient line
-     * @param colors       The colors to be distributed along the gradient line
-     * @param positions    May be null. The relative positions [0..1] of
-     *                     each corresponding color in the colors array. If this is null,
-     *                     the the colors are distributed evenly along the gradient line.
-     * @param  tile        The Shader tiling mode
-     */
-    public void set(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
-            @Nullable float positions[], @NonNull TileMode tile) {
-        if (colors.length < 2) {
-            throw new IllegalArgumentException("needs >= 2 number of colors");
-        }
-        if (positions != null && colors.length != positions.length) {
-            throw new IllegalArgumentException("color and position arrays must be of equal length");
-        }
-        discardNativeInstance();
-        mType = TYPE_COLORS_AND_POSITIONS;
-        mX0 = x0;
-        mY0 = y0;
-        mX1 = x1;
-        mY1 = y1;
-        mColors = colors.clone();
-        mPositions = positions != null ? positions.clone() : null;
-        mTileMode = tile;
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param x0       The x-coordinate for the start of the gradient line
-     * @param y0       The y-coordinate for the start of the gradient line
-     * @param x1       The x-coordinate for the end of the gradient line
-     * @param y1       The y-coordinate for the end of the gradient line
-     * @param color0   The color at the start of the gradient line.
-     * @param color1   The color at the end of the gradient line.
-     * @param tile     The Shader tiling mode
-    */
-    public void set(float x0, float y0, float x1, float y1,
-            @ColorInt int color0, @ColorInt int color1,
-            @NonNull TileMode tile) {
-        discardNativeInstance();
         mType = TYPE_COLOR_START_AND_COLOR_END;
         mX0 = x0;
         mY0 = y0;
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index ccc6ead..01d5825 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -49,6 +49,8 @@
      *
      * @see Color
      * @see #setColor(int)
+     *
+     * @hide
      */
     @ColorInt
     public int getColor() {
@@ -64,6 +66,8 @@
      * @see Color
      * @see #getColor()
      * @see #getMode()
+     *
+     * @hide
      */
     public void setColor(@ColorInt int color) {
         if (mColor != color) {
@@ -78,6 +82,8 @@
      *
      * @see PorterDuff
      * @see #setMode(android.graphics.PorterDuff.Mode)
+     *
+     * @hide
      */
     public PorterDuff.Mode getMode() {
         return mMode;
@@ -90,6 +96,8 @@
      * @see PorterDuff
      * @see #getMode()
      * @see #getColor()
+     *
+     * @hide
      */
     public void setMode(@NonNull PorterDuff.Mode mode) {
         if (mode == null) {
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index ae8f7da..f4b1191 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -57,7 +57,22 @@
     public RadialGradient(float centerX, float centerY, float radius,
             @NonNull @ColorInt int colors[], @Nullable float stops[],
             @NonNull TileMode tileMode) {
-        set(centerX, centerY, radius, colors, stops, tileMode);
+        if (radius <= 0) {
+            throw new IllegalArgumentException("radius must be > 0");
+        }
+        if (colors.length < 2) {
+            throw new IllegalArgumentException("needs >= 2 number of colors");
+        }
+        if (stops != null && colors.length != stops.length) {
+            throw new IllegalArgumentException("color and position arrays must be of equal length");
+        }
+        mType = TYPE_COLORS_AND_POSITIONS;
+        mX = centerX;
+        mY = centerY;
+        mRadius = radius;
+        mColors = colors.clone();
+        mPositions = stops != null ? stops.clone() : null;
+        mTileMode = tileMode;
     }
 
     /**
@@ -72,59 +87,9 @@
      */
     public RadialGradient(float centerX, float centerY, float radius,
             @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
-        set(centerX, centerY, radius, centerColor, edgeColor, tileMode);
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param centerX  The x-coordinate of the center of the radius
-     * @param centerY  The y-coordinate of the center of the radius
-     * @param radius   Must be positive. The radius of the circle for this gradient.
-     * @param colors   The colors to be distributed between the center and edge of the circle
-     * @param stops    May be <code>null</code>. Valid values are between <code>0.0f</code> and
-     *                 <code>1.0f</code>. The relative position of each corresponding color in
-     *                 the colors array. If <code>null</code>, colors are distributed evenly
-     *                 between the center and edge of the circle.
-     * @param tileMode The Shader tiling mode
-     */
-    public void set(float centerX, float centerY, float radius,
-            @NonNull @ColorInt int colors[], @Nullable float stops[], @NonNull TileMode tileMode) {
         if (radius <= 0) {
             throw new IllegalArgumentException("radius must be > 0");
         }
-        if (colors.length < 2) {
-            throw new IllegalArgumentException("needs >= 2 number of colors");
-        }
-        if (stops != null && colors.length != stops.length) {
-            throw new IllegalArgumentException("color and position arrays must be of equal length");
-        }
-        discardNativeInstance();
-        mType = TYPE_COLORS_AND_POSITIONS;
-        mX = centerX;
-        mY = centerY;
-        mRadius = radius;
-        mColors = colors.clone();
-        mPositions = stops != null ? stops.clone() : null;
-        mTileMode = tileMode;
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param centerX     The x-coordinate of the center of the radius
-     * @param centerY     The y-coordinate of the center of the radius
-     * @param radius      Must be positive. The radius of the circle for this gradient
-     * @param centerColor The color at the center of the circle.
-     * @param edgeColor   The color at the edge of the circle.
-     * @param tileMode    The Shader tiling mode
-     */
-    public void set(float centerX, float centerY, float radius,
-            @ColorInt int centerColor, @ColorInt int edgeColor, @NonNull TileMode tileMode) {
-        if (radius <= 0) {
-            throw new IllegalArgumentException("radius must be > 0");
-        }
-        discardNativeInstance();
         mType = TYPE_COLOR_CENTER_AND_COLOR_EDGE;
         mX = centerX;
         mY = centerY;
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 8410ab2..c744757 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -105,20 +105,13 @@
         return 0;
     }
 
-    void discardNativeInstance() {
+    private void discardNativeInstance() {
         if (mNativeInstance != 0) {
             nativeSafeUnref(mNativeInstance);
             mNativeInstance = 0;
         }
     }
 
-    /**
-     * Callback for subclasses to call {@link #discardNativeInstance()} if the most recently
-     * constructed native instance is no longer valid.
-     */
-    void verifyNativeInstance() {
-    }
-
     @Override
     protected void finalize() throws Throwable {
         try {
@@ -155,9 +148,6 @@
             throw new IllegalStateException("attempting to use a finalized Shader");
         }
 
-        // verify mNativeInstance is valid
-        verifyNativeInstance();
-
         if (mNativeInstance == 0) {
             mNativeInstance = createNativeInstance(mLocalMatrix == null
                     ? 0 : mLocalMatrix.native_instance);
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 0a1aef6..b6b80b4 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -54,7 +54,18 @@
      */
     public SweepGradient(float cx, float cy,
             @NonNull @ColorInt int colors[], @Nullable float positions[]) {
-        set(cx, cy, colors, positions);
+        if (colors.length < 2) {
+            throw new IllegalArgumentException("needs >= 2 number of colors");
+        }
+        if (positions != null && colors.length != positions.length) {
+            throw new IllegalArgumentException(
+                    "color and position arrays must be of equal length");
+        }
+        mType = TYPE_COLORS_AND_POSITIONS;
+        mCx = cx;
+        mCy = cy;
+        mColors = colors.clone();
+        mPositions = positions != null ? positions.clone() : null;
     }
 
     /**
@@ -66,50 +77,6 @@
      * @param color1   The color to use at the end of the sweep
      */
     public SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1) {
-        set(cx, cy, color0, color1);
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param cx       The x-coordinate of the center
-     * @param cy       The y-coordinate of the center
-     * @param colors   The colors to be distributed between around the center.
-     *                 There must be at least 2 colors in the array.
-     * @param positions May be NULL. The relative position of
-     *                 each corresponding color in the colors array, beginning
-     *                 with 0 and ending with 1.0. If the values are not
-     *                 monotonic, the drawing may produce unexpected results.
-     *                 If positions is NULL, then the colors are automatically
-     *                 spaced evenly.
-     */
-    public void set(float cx, float cy,
-            @NonNull @ColorInt int colors[], @Nullable float positions[]) {
-        if (colors.length < 2) {
-            throw new IllegalArgumentException("needs >= 2 number of colors");
-        }
-        if (positions != null && colors.length != positions.length) {
-            throw new IllegalArgumentException(
-                    "color and position arrays must be of equal length");
-        }
-        discardNativeInstance();
-        mType = TYPE_COLORS_AND_POSITIONS;
-        mCx = cx;
-        mCy = cy;
-        mColors = colors.clone();
-        mPositions = positions != null ? positions.clone() : null;
-    }
-
-    /**
-     * Reinitialize the shader.
-     *
-     * @param cx       The x-coordinate of the center
-     * @param cy       The y-coordinate of the center
-     * @param color0   The color to use at the start of the sweep
-     * @param color1   The color to use at the end of the sweep
-     */
-    public void set(float cx, float cy, @ColorInt int color0, @ColorInt int color1) {
-        discardNativeInstance();
         mType = TYPE_COLOR_START_AND_COLOR_END;
         mCx = cx;
         mCy = cy;
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 395dc07..97d3e5e 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -34,6 +34,7 @@
 import android.graphics.fonts.FontResult;
 import android.graphics.fonts.FontVariationAxis;
 import android.graphics.fonts.FontVariationAxis.InvalidFormatException;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
@@ -107,6 +108,7 @@
     /**
      * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
      */
+    @GuardedBy("sLock")
     private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
 
     static Typeface sDefaultTypeface;
@@ -128,6 +130,7 @@
     public static final int BOLD_ITALIC = 3;
 
     private int mStyle = 0;
+    private int mBaseWeight = 0;
 
     // Value for weight and italic. Indicates the value is resolved by font metadata.
     // Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
@@ -170,7 +173,8 @@
         if (sFallbackFonts != null) {
             synchronized (sDynamicTypefaceCache) {
                 final String key = Builder.createAssetUid(
-                        mgr, path, 0 /* ttcIndex */, null /* axes */);
+                        mgr, path, 0 /* ttcIndex */, null /* axes */,
+                        RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */);
                 Typeface typeface = sDynamicTypefaceCache.get(key);
                 if (typeface != null) return typeface;
 
@@ -179,9 +183,12 @@
                 if (fontFamily.addFontFromAssetManager(mgr, path, cookie, false /* isAsset */,
                         0 /* ttcIndex */, RESOLVE_BY_FONT_TABLE /* weight */,
                         RESOLVE_BY_FONT_TABLE /* italic */, null /* axes */)) {
-                    fontFamily.freeze();
+                    if (!fontFamily.freeze()) {
+                        return null;
+                    }
                     FontFamily[] families = {fontFamily};
-                    typeface = createFromFamiliesWithDefault(families);
+                    typeface = createFromFamiliesWithDefault(families,
+                            RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
                     sDynamicTypefaceCache.put(key, typeface);
                     return typeface;
                 }
@@ -240,12 +247,18 @@
                     return null;
                 }
             }
+            // Due to backward compatibility, even if the font is not supported by our font stack,
+            // we need to place the empty font at the first place. The typeface with empty font
+            // behaves different from default typeface especially in fallback font selection.
+            fontFamily.allowUnsupportedFont();
             fontFamily.freeze();
             FontFamily[] familyChain = { fontFamily };
-            typeface = createFromFamiliesWithDefault(familyChain);
+            typeface = createFromFamiliesWithDefault(familyChain,
+                    RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
             synchronized (sDynamicTypefaceCache) {
                 final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
-                        null /* axes */);
+                        null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */,
+                        RESOLVE_BY_FONT_TABLE /* italic */);
                 sDynamicTypefaceCache.put(key, typeface);
             }
             return typeface;
@@ -259,7 +272,8 @@
      */
     public static Typeface findFromCache(AssetManager mgr, String path) {
         synchronized (sDynamicTypefaceCache) {
-            final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */);
+            final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */,
+                    RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */);
             Typeface typeface = sDynamicTypefaceCache.get(key);
             if (typeface != null) {
                 return typeface;
@@ -291,6 +305,7 @@
      *                request. May not be null.
      * @param callback A callback that will be triggered when results are obtained. May not be null.
      */
+    @Deprecated
     public static void create(@NonNull FontRequest request, @NonNull FontRequestCallback callback) {
         // Check the cache first
         // TODO: would the developer want to avoid a cache hit and always ask for the freshest
@@ -391,8 +406,14 @@
                 IoUtils.closeQuietly(fd);
             }
         }
-        fontFamily.freeze();
-        Typeface typeface = Typeface.createFromFamiliesWithDefault(new FontFamily[] { fontFamily });
+        if (!fontFamily.freeze()) {
+            callback.onTypefaceRequestFailed(
+                    FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
+            return;
+        }
+        Typeface typeface = Typeface.createFromFamiliesWithDefault(
+                new FontFamily[] { fontFamily },
+                RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
         synchronized (sDynamicTypefaceCache) {
             String key = createProviderUid(request.getProviderAuthority(), request.getQuery());
             sDynamicTypefaceCache.put(key, typeface);
@@ -403,6 +424,7 @@
     /**
      * Interface used to receive asynchronously fetched typefaces.
      */
+    @Deprecated
     public interface FontRequestCallback {
         /**
          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
@@ -509,6 +531,10 @@
      * </p>
      */
     public static final class Builder {
+        /** @hide */
+        public static final int NORMAL_WEIGHT = 400;
+        /** @hide */
+        public static final int BOLD_WEIGHT = 700;
 
         private int mTtcIndex;
         private FontVariationAxis[] mAxes;
@@ -517,6 +543,11 @@
         private String mPath;
         private FileDescriptor mFd;
 
+        private FontsContract.FontInfo[] mFonts;
+        private Map<Uri, ByteBuffer> mFontBuffers;
+
+        private String mFallbackFamilyName;
+
         private int mWeight = RESOLVE_BY_FONT_TABLE;
         private int mItalic = RESOLVE_BY_FONT_TABLE;
 
@@ -559,6 +590,25 @@
         }
 
         /**
+         * Constracts a builder from an array of FontsContract.FontInfo.
+         *
+         * Since {@link FontsContract.FontInfo} holds information about TTC indices and
+         * variation settings, there is no need to call {@link #setTtcIndex} or
+         * {@link #setFontVariationSettings}. Similary, {@link FontsContract.FontInfo} holds
+         * weight and italic information, so {@link #setWeight} and {@link #setItalic} are used
+         * for style matching during font selection.
+         *
+         * @param results The array of {@link FontsContract.FontInfo}
+         * @param buffers The mapping from URI to buffers to be used during building.
+         * @hide
+         */
+        public Builder(@NonNull FontsContract.FontInfo[] fonts,
+                @NonNull Map<Uri, ByteBuffer> buffers) {
+            mFonts = fonts;
+            mFontBuffers = buffers;
+        }
+
+        /**
          * Sets weight of the font.
          *
          * Tells the system the weight of the given font. If not provided, the system will resolve
@@ -590,6 +640,10 @@
          *                 collection, do not call this method or specify 0.
          */
         public Builder setTtcIndex(@IntRange(from = 0) int ttcIndex) {
+            if (mFonts != null) {
+                throw new IllegalArgumentException(
+                        "TTC index can not be specified for FontResult source.");
+            }
             mTtcIndex = ttcIndex;
             return this;
         }
@@ -603,6 +657,13 @@
          */
         public Builder setFontVariationSettings(@Nullable String variationSettings)
                 throws InvalidFormatException {
+            if (mFonts != null) {
+                throw new IllegalArgumentException(
+                        "Font variation settings can not be specified for FontResult source.");
+            }
+            if (mAxes != null) {
+                throw new IllegalStateException("Font variation settings are already set.");
+            }
             mAxes = FontVariationAxis.fromFontVariationSettings(variationSettings);
             return this;
         }
@@ -613,11 +674,45 @@
          * @param axes An array of font variation axis tag-value pairs.
          */
         public Builder setFontVariationSettings(@Nullable FontVariationAxis[] axes) {
+            if (mFonts != null) {
+                throw new IllegalArgumentException(
+                        "Font variation settings can not be specified for FontResult source.");
+            }
+            if (mAxes != null) {
+                throw new IllegalStateException("Font variation settings are already set.");
+            }
             mAxes = axes;
             return this;
         }
 
         /**
+         * Sets a fallback family name.
+         *
+         * By specifying a fallback family name, a fallback Typeface will be returned if the
+         * {@link #build} method fails to create a Typeface from the provided font. The fallback
+         * family will be resolved with the provided weight and italic information specified by
+         * {@link #setWeight} and {@link #setItalic}.
+         *
+         * If {@link #setWeight} is not called, the fallback family keeps the default weight.
+         * Similary, if {@link #setItalic} is not called, the fallback family keeps the default
+         * italic information. For example, calling {@code builder.setFallback("sans-serif-light")}
+         * is equivalent to calling {@code builder.setFallback("sans-serif").setWeight(300)} in
+         * terms of fallback. The default weight and italic information are overridden by calling
+         * {@link #setWeight} and {@link #setItalic}. For example, if a Typeface is constructed
+         * using {@code builder.setFallback("sans-serif-light").setWeight(700)}, the fallback text
+         * will render as sans serif bold.
+         *
+         * @param familyName A family name to be used for fallback if the provided font can not be
+         *                   used. By passing {@code null}, build() returns {@code null}.
+         *                   If {@link #setFallback} is not called on the builder, {@code null}
+         *                   is assumed.
+         */
+        public Builder setFallback(@Nullable String familyName) {
+            mFallbackFamilyName = familyName;
+            return this;
+        }
+
+        /**
          * Creates a unique id for a given AssetManager and asset path.
          *
          * @param mgr  AssetManager instance
@@ -627,7 +722,7 @@
          * @return Unique id for a given AssetManager and asset path.
          */
         private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex,
-                @Nullable FontVariationAxis[] axes) {
+                @Nullable FontVariationAxis[] axes, int weight, int italic) {
             final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
             final StringBuilder builder = new StringBuilder();
             final int size = pkgs.size();
@@ -639,6 +734,10 @@
             builder.append("-");
             builder.append(Integer.toString(ttcIndex));
             builder.append("-");
+            builder.append(Integer.toString(weight));
+            builder.append("-");
+            builder.append(Integer.toString(italic));
+            builder.append("-");
             if (axes != null) {
                 for (FontVariationAxis axis : axes) {
                     builder.append(axis.getTag());
@@ -649,13 +748,61 @@
             return builder.toString();
         }
 
+        private static final Object sLock = new Object();
+        // TODO: Unify with Typeface.sTypefaceCache.
+        @GuardedBy("sLock")
+        private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache =
+                new LongSparseArray<>(3);
+
+        private Typeface resolveFallbackTypeface() {
+            if (mFallbackFamilyName == null) {
+                return null;
+            }
+
+            Typeface base =  sSystemFontMap.get(mFallbackFamilyName);
+            if (base == null) {
+                base = sDefaultTypeface;
+            }
+
+            if (mWeight == RESOLVE_BY_FONT_TABLE && mItalic == RESOLVE_BY_FONT_TABLE) {
+                return base;
+            }
+
+            final int weight = (mWeight == RESOLVE_BY_FONT_TABLE) ? base.mBaseWeight : mWeight;
+            final boolean italic =
+                    (mItalic == RESOLVE_BY_FONT_TABLE) ? (base.mStyle & ITALIC) != 0 : mItalic == 1;
+            final int key = weight << 1 | (italic ? 1 : 0);
+
+            Typeface typeface;
+            synchronized(sLock) {
+                SparseArray<Typeface> innerCache = sTypefaceCache.get(base.native_instance);
+                if (innerCache != null) {
+                    typeface = innerCache.get(key);
+                    if (typeface != null) {
+                        return typeface;
+                    }
+                }
+
+                typeface = new Typeface(
+                        nativeCreateFromTypefaceWithExactStyle(
+                                base.native_instance, weight, italic));
+
+                if (innerCache == null) {
+                    innerCache = new SparseArray<>(4); // [regular, bold] x [upright, italic]
+                    sTypefaceCache.put(base.native_instance, innerCache);
+                }
+                innerCache.put(key, typeface);
+            }
+            return typeface;
+        }
+
         /**
          * Generates new Typeface from specified configuration.
          *
          * @return Newly created Typeface. May return null if some parameters are invalid.
          */
         public Typeface build() {
-            if (mFd != null) {  // set source by setSourceFromFile(FileDescriptor)
+            if (mFd != null) {  // Builder is created with file descriptor.
                 try (FileInputStream fis = new FileInputStream(mFd)) {
                     FileChannel channel = fis.getChannel();
                     long size = channel.size();
@@ -664,40 +811,73 @@
                     final FontFamily fontFamily = new FontFamily();
                     if (!fontFamily.addFontFromBuffer(buffer, mTtcIndex, mAxes, mWeight, mItalic)) {
                         fontFamily.abortCreation();
-                        return null;
+                        return resolveFallbackTypeface();
                     }
-                    fontFamily.freeze();
+                    if (!fontFamily.freeze()) {
+                        return resolveFallbackTypeface();
+                    }
                     FontFamily[] families = { fontFamily };
-                    return createFromFamiliesWithDefault(families);
+                    return createFromFamiliesWithDefault(families, mWeight, mItalic);
                 } catch (IOException e) {
-                    return null;
+                    return resolveFallbackTypeface();
                 }
-            } else if (mAssetManager != null) {  // set source by setSourceFromAsset()
-                final String key = createAssetUid(mAssetManager, mPath, mTtcIndex, mAxes);
-                synchronized (sDynamicTypefaceCache) {
+            } else if (mAssetManager != null) {  // Builder is created with asset manager.
+                final String key = createAssetUid(
+                        mAssetManager, mPath, mTtcIndex, mAxes, mWeight, mItalic);
+                synchronized (sLock) {
                     Typeface typeface = sDynamicTypefaceCache.get(key);
                     if (typeface != null) return typeface;
                     final FontFamily fontFamily = new FontFamily();
                     if (!fontFamily.addFontFromAssetManager(mAssetManager, mPath, mTtcIndex,
                             true /* isAsset */, mTtcIndex, mWeight, mItalic, mAxes)) {
                         fontFamily.abortCreation();
-                        return null;
+                        return resolveFallbackTypeface();
                     }
-                    fontFamily.freeze();
+                    if (!fontFamily.freeze()) {
+                        return resolveFallbackTypeface();
+                    }
                     FontFamily[] families = { fontFamily };
-                    typeface = createFromFamiliesWithDefault(families);
+                    typeface = createFromFamiliesWithDefault(families, mWeight, mItalic);
                     sDynamicTypefaceCache.put(key, typeface);
                     return typeface;
                 }
-            } else if (mPath != null) {  // set source by setSourceFromFile(File)
+            } else if (mPath != null) {  // Builder is created with file path.
                 final FontFamily fontFamily = new FontFamily();
                 if (!fontFamily.addFont(mPath, mTtcIndex, mAxes, mWeight, mItalic)) {
                     fontFamily.abortCreation();
+                    return resolveFallbackTypeface();
+                }
+                if (!fontFamily.freeze()) {
+                    return resolveFallbackTypeface();
+                }
+                FontFamily[] families = { fontFamily };
+                return createFromFamiliesWithDefault(families, mWeight, mItalic);
+            } else if (mFonts != null) {
+                final FontFamily fontFamily = new FontFamily();
+                boolean atLeastOneFont = false;
+                for (FontsContract.FontInfo font : mFonts) {
+                    final ByteBuffer fontBuffer = mFontBuffers.get(font.getUri());
+                    if (fontBuffer == null) {
+                        continue;  // skip
+                    }
+                    final boolean success = fontFamily.addFontFromBuffer(fontBuffer,
+                            font.getTtcIndex(), font.getAxes(), font.getWeight(),
+                            font.isItalic() ? STYLE_ITALIC : STYLE_NORMAL);
+                    if (!success) {
+                        fontFamily.abortCreation();
+                        return null;
+                    }
+                    atLeastOneFont = true;
+                }
+                if (!atLeastOneFont) {
+                    // No fonts are avaialble. No need to create new Typeface and returns fallback
+                    // Typeface instead.
+                    fontFamily.abortCreation();
                     return null;
                 }
                 fontFamily.freeze();
                 FontFamily[] families = { fontFamily };
-                return createFromFamiliesWithDefault(families);
+                return createFromFamiliesWithDefault(families, mWeight, mItalic);
             }
 
             // Must not reach here.
@@ -796,12 +976,35 @@
             throw new NullPointerException();  // for backward compatibility
         }
         if (sFallbackFonts != null) {
-            Typeface typeface = new Builder(mgr, path).build();
-            if (typeface != null) {
-                return typeface;
+            synchronized (sLock) {
+                Typeface typeface = new Builder(mgr, path).build();
+                if (typeface != null) return typeface;
+
+                final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
+                        null /* axes */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
+                typeface = sDynamicTypefaceCache.get(key);
+                if (typeface != null) return typeface;
+
+                final FontFamily fontFamily = new FontFamily();
+                if (fontFamily.addFontFromAssetManager(mgr, path, 0, true /* isAsset */,
+                        0 /* ttc index */, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE,
+                        null /* axes */)) {
+                    // Due to backward compatibility, even if the font is not supported by our font
+                    // stack, we need to place the empty font at the first place. The typeface with
+                    // empty font behaves different from default typeface especially in fallback
+                    // font selection.
+                    fontFamily.allowUnsupportedFont();
+                    fontFamily.freeze();
+                    final FontFamily[] families = { fontFamily };
+                    typeface = createFromFamiliesWithDefault(families, RESOLVE_BY_FONT_TABLE,
+                            RESOLVE_BY_FONT_TABLE);
+                    sDynamicTypefaceCache.put(key, typeface);
+                    return typeface;
+                } else {
+                    fontFamily.abortCreation();
+                }
             }
         }
-        // For the compatibility reasons, throw runtime exception if failed to create Typeface.
         throw new RuntimeException("Font asset not found " + path);
     }
 
@@ -836,17 +1039,21 @@
      * @return The new typeface.
      */
     public static Typeface createFromFile(@Nullable String path) {
-        if (path == null) {
-            // For the compatibility reasons, need to throw NPE if the argument is null.
-            // See android.graphics.cts.TypefaceTest#testCreateFromFileByFileNameNull
-            throw new NullPointerException();
-        }
         if (sFallbackFonts != null) {
-            Typeface typeface = new Builder(path).build();
-            if (typeface != null) {
-                // For the compatibility reasons, throw runtime exception if failed to create
-                // Typeface.
-                return typeface;
+            final FontFamily fontFamily = new FontFamily();
+            if (fontFamily.addFont(path, 0 /* ttcIndex */, null /* axes */,
+                      RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE)) {
+                // Due to backward compatibility, even if the font is not supported by our font
+                // stack, we need to place the empty font at the first place. The typeface with
+                // empty font behaves different from default typeface especially in fallback font
+                // selection.
+                fontFamily.allowUnsupportedFont();
+                fontFamily.freeze();
+                FontFamily[] families = { fontFamily };
+                return createFromFamiliesWithDefault(families, RESOLVE_BY_FONT_TABLE,
+                        RESOLVE_BY_FONT_TABLE);
+            } else {
+                fontFamily.abortCreation();
             }
         }
         throw new RuntimeException("Font not found " + path);
@@ -862,16 +1069,25 @@
         for (int i = 0; i < families.length; i++) {
             ptrArray[i] = families[i].mNativePtr;
         }
-        return new Typeface(nativeCreateFromArray(ptrArray));
+        return new Typeface(nativeCreateFromArray(
+                ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
     }
 
     /**
      * Create a new typeface from an array of font families, including
      * also the font families in the fallback list.
-     *
+     * @param weight the weight for this family. {@link RESOLVE_BY_FONT_TABLE} can be used. In that
+     *               case, the table information in the first family's font is used. If the first
+     *               family has multiple fonts, the closest to the regular weight and upright font
+     *               is used.
+     * @param italic the italic information for this family. {@link RESOLVE_BY_FONT_TABLE} can be
+     *               used. In that case, the table information in the first family's font is used.
+     *               If the first family has multiple fonts, the closest to the regular weight and
+     *               upright font is used.
      * @param families array of font families
      */
-    private static Typeface createFromFamiliesWithDefault(FontFamily[] families) {
+    private static Typeface createFromFamiliesWithDefault(FontFamily[] families,
+                int weight, int italic) {
         long[] ptrArray = new long[families.length + sFallbackFonts.length];
         for (int i = 0; i < families.length; i++) {
             ptrArray[i] = families[i].mNativePtr;
@@ -879,7 +1095,7 @@
         for (int i = 0; i < sFallbackFonts.length; i++) {
             ptrArray[i + families.length] = sFallbackFonts[i].mNativePtr;
         }
-        return new Typeface(nativeCreateFromArray(ptrArray));
+        return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
     }
 
     // don't allow clients to call this directly
@@ -890,6 +1106,7 @@
 
         native_instance = ni;
         mStyle = nativeGetStyle(ni);
+        mBaseWeight = nativeGetBaseWeight(ni);
     }
 
     private static FontFamily makeFamilyFromParsed(FontConfig.Family family,
@@ -914,7 +1131,12 @@
                 Log.e(TAG, "Error creating font " + fullPathName + "#" + font.getTtcIndex());
             }
         }
-        fontFamily.freeze();
+        if (!fontFamily.freeze()) {
+            // Treat as system error since reaching here means that a system pre-installed font
+            // can't be used by our font stack.
+            Log.e(TAG, "Unable to load Family: " + family.getName() + ":" + family.getLanguage());
+            return null;
+        }
         return fontFamily;
     }
 
@@ -939,7 +1161,10 @@
             for (int i = 0; i < fontConfig.getFamilies().length; i++) {
                 FontConfig.Family f = fontConfig.getFamilies()[i];
                 if (i == 0 || f.getName() == null) {
-                    familyList.add(makeFamilyFromParsed(f, bufferForPath));
+                    FontFamily family = makeFamilyFromParsed(f, bufferForPath);
+                    if (family != null) {
+                        familyList.add(family);
+                    }
                 }
             }
             sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]);
@@ -956,8 +1181,12 @@
                         typeface = sDefaultTypeface;
                     } else {
                         FontFamily fontFamily = makeFamilyFromParsed(f, bufferForPath);
+                        if (fontFamily == null) {
+                            continue;
+                        }
                         FontFamily[] families = { fontFamily };
-                        typeface = Typeface.createFromFamiliesWithDefault(families);
+                        typeface = Typeface.createFromFamiliesWithDefault(families,
+                                RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
                     }
                     systemFonts.put(f.getName(), typeface);
                 }
@@ -1055,13 +1284,16 @@
     }
 
     private static native long nativeCreateFromTypeface(long native_instance, int style);
+    private static native long nativeCreateFromTypefaceWithExactStyle(
+            long native_instance, int weight, boolean italic);
     // TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
     private static native long nativeCreateFromTypefaceWithVariation(
             long native_instance, List<FontVariationAxis> axes);
     private static native long nativeCreateWeightAlias(long native_instance, int weight);
     private static native void nativeUnref(long native_instance);
     private static native int  nativeGetStyle(long native_instance);
-    private static native long nativeCreateFromArray(long[] familyArray);
+    private static native int  nativeGetBaseWeight(long native_instance);
+    private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
     private static native void nativeSetDefault(long native_instance);
     private static native int[] nativeGetSupportedAxes(long native_instance);
 }
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 6dfe03d..283a3e2 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -29,6 +29,7 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.ColorFilter;
 import android.graphics.Matrix;
 import android.graphics.Outline;
@@ -51,12 +52,27 @@
 import java.io.IOException;
 
 /**
- * This drawable supports two layers: foreground and background.
- *
- * <p>The layers are clipped when rendering using the mask path defined in the device configuration.
- *
  * <p>This class can also be created via XML inflation using <code>&lt;adaptive-icon></code> tag
  * in addition to dynamic creation.
+ *
+ * <p>This drawable supports two drawable layers: foreground and background. The layers are clipped
+ * when rendering using the mask defined in the device configuration.
+ *
+ * <ul>
+ * <li>Both foreground and background layers should be sized at 108 x 108 dp.</li>
+ * <li>The inner 72 x 72 dp  of the icon appears within the masked viewport.</li>
+ * <li>The outer 18 dp on each of the 4 sides of the layers is reserved for use by the system UI
+ * surfaces to create interesting visual effects, such as parallax or pulsing.</li>
+ * </ul>
+ *
+ * Such motion effect is achieved by internally setting the bounds of the foreground and
+ * background layer as following:
+ * <pre>
+ * Rect(getBounds().left - getBounds().getWidth() * #getExtraInsetFraction(),
+ *      getBounds().top - getBounds().getHeight() * #getExtraInsetFraction(),
+ *      getBounds().right + getBounds().getWidth() * #getExtraInsetFraction(),
+ *      getBounds().bottom + getBounds().getHeight() * #getExtraInsetFraction())
+ * </pre>
  */
 public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback {
 
@@ -65,7 +81,11 @@
      * @hide
      */
     public static final float MASK_SIZE = 100f;
-    private static final float SAFEZONE_SCALE = .9f;
+
+    /**
+     * Launcher icons design guideline
+     */
+    private static final float SAFEZONE_SCALE = 72f/66f;
 
     /**
      * All four sides of the layers are padded with extra inset so as to provide
@@ -80,7 +100,7 @@
     private static final float DEFAULT_VIEW_PORT_SCALE = 1f / (1 + 2 * EXTRA_INSET_PERCENTAGE);
 
     /**
-     * Clip path defined in {@link com.android.internal.R.string.config_icon_mask}.
+     * Clip path defined in R.string.config_icon_mask.
      */
     private static Path sMask;
 
@@ -134,9 +154,10 @@
 
         if (sMask == null) {
             sMask = PathParser.createPathFromPathData(
-                Resources.getSystem().getString(com.android.internal.R.string.config_icon_mask));
+                Resources.getSystem().getString(R.string.config_icon_mask));
         }
-        mMask = new Path();
+        mMask = PathParser.createPathFromPathData(
+            Resources.getSystem().getString(R.string.config_icon_mask));
         mMaskMatrix = new Matrix();
         mCanvas = new Canvas();
         mTransparentRegion = new Region();
@@ -212,13 +233,24 @@
      * All four sides of the layers are padded with extra inset so as to provide
      * extra content to reveal within the clip path when performing affine transformations on the
      * layers.
+     *
+     * @see #getForeground() and #getBackground() for more info on how this value is used
+     */
+    public static float getExtraInsetFraction() {
+        return EXTRA_INSET_PERCENTAGE;
+    }
+
+    /**
+     * @hide
      */
     public static float getExtraInsetPercentage() {
         return EXTRA_INSET_PERCENTAGE;
     }
 
     /**
-     * Only call this method after bound is set on this drawable.
+     * When called before the bound is set, the returned path is identical to
+     * R.string.config_icon_mask. After the bound is set, the
+     * returned path's computed bound is same as the #getBounds().
      *
      * @return the mask path object used to clip the drawable
      */
@@ -227,6 +259,10 @@
     }
 
     /**
+     * Returns the foreground drawable managed by this class. The bound of this drawable is
+     * extended by {@link #getExtraInsetFraction()} * getBounds().width on left/right sides and by
+     * {@link #getExtraInsetFraction()} * getBounds().height on top/bottom sides.
+     *
      * @return the foreground drawable managed by this drawable
      */
     public Drawable getForeground() {
@@ -234,6 +270,10 @@
     }
 
     /**
+     * Returns the foreground drawable managed by this class. The bound of this drawable is
+     * extended by {@link #getExtraInsetFraction()} * getBounds().width on left/right sides and by
+     * {@link #getExtraInsetFraction()} * getBounds().height on top/bottom sides.
+     *
      * @return the background drawable managed by this drawable
      */
     public Drawable getBackground() {
@@ -293,10 +333,15 @@
             mMaskBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ALPHA_8);
             mLayersBitmap = Bitmap.createBitmap(b.width(), b.height(), Bitmap.Config.ARGB_8888);
         }
+        // mMaskBitmap bound [0, w] x [0, h]
         mCanvas.setBitmap(mMaskBitmap);
         mPaint.setShader(null);
         mCanvas.drawPath(mMask, mPaint);
 
+        // mMask bound [left, top, right, bottom]
+        mMaskMatrix.postTranslate(b.left, b.top);
+        mMask.reset();
+        sMask.transform(mMaskMatrix, mMask);
         // reset everything that depends on the view bounds
         mTransparentRegion.setEmpty();
         mLayersShader = null;
@@ -309,6 +354,7 @@
         }
         if (mLayersShader == null) {
             mCanvas.setBitmap(mLayersBitmap);
+            mCanvas.drawColor(Color.BLACK);
             for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
                 if (mLayerState.mChildren[i] == null) {
                     continue;
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index c43899b..34da928 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -17,6 +17,8 @@
 package android.graphics.drawable;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -32,6 +34,7 @@
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.Shader;
+import android.graphics.Xfermode;
 import android.graphics.drawable.shapes.Shape;
 import android.util.AttributeSet;
 
@@ -306,6 +309,16 @@
         invalidateSelf();
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    @TestApi
+    public void setXfermode(@Nullable Xfermode mode) {
+        mShapeState.mPaint.setXfermode(mode);
+        invalidateSelf();
+    }
+
     @Override
     public int getOpacity() {
         if (mShapeState.mShape == null) {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 3e7a246..931a55a 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -600,12 +600,12 @@
 void GlopBuilder::build() {
     REQUIRE_STAGES(kAllStages);
     if (mOutGlop->mesh.vertices.attribFlags & VertexAttribFlags::TextureCoord) {
-        if (mOutGlop->fill.texture.texture->target() == GL_TEXTURE_2D) {
+        Texture* texture = mOutGlop->fill.texture.texture;
+        if (texture->target() == GL_TEXTURE_2D) {
             mDescription.hasTexture = true;
         } else {
             mDescription.hasExternalTexture = true;
         }
-        Texture* texture = mOutGlop->fill.texture.texture;
         mDescription.hasLinearTexture = texture->isLinear();
         mDescription.hasColorSpaceConversion = texture->hasColorSpaceConversion();
         mDescription.transferFunction = texture->getTransferFunctionType();
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index c460c0d..d64804e 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -144,8 +144,6 @@
         return CopyResult::UnknownError;
     }
 
-    SkAutoLockPixels alp(*bitmap);
-
     GLuint texture;
 
     GLenum format;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index ece0b47..623b496 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -60,7 +60,8 @@
 
 SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
     sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
-    mCanvasOwned = std::unique_ptr<SkCanvas>(new SkCanvas(bitmap));
+    mCanvasOwned =
+            std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
     mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(),
             cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
     mCanvas = mCanvasWrapper.get();
@@ -83,7 +84,8 @@
 
 void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
     sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
-    std::unique_ptr<SkCanvas> newCanvas = std::unique_ptr<SkCanvas>(new SkCanvas(bitmap));
+    std::unique_ptr<SkCanvas> newCanvas =
+            std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
     std::unique_ptr<SkCanvas> newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(),
             cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
 
@@ -388,14 +390,8 @@
 }
 
 bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) {
-    SkRRect roundRect;
-    if (path->isRRect(&roundRect)) {
-        this->recordClip(roundRect, op);
-        mCanvas->clipRRect(roundRect, op);
-    } else {
-        this->recordClip(*path, op);
-        mCanvas->clipPath(*path, op);
-    }
+    this->recordClip(*path, op);
+    mCanvas->clipPath(*path, op);
     return !mCanvas->isClipEmpty();
 }
 
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 246a8c57..929d1606 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -51,9 +51,9 @@
 }
 
 typedef sk_sp<Bitmap> (*AllocPixeRef)(size_t allocSize, const SkImageInfo& info, size_t rowBytes,
-        SkColorTable* ctable);
+        sk_sp<SkColorTable> ctable);
 
-static sk_sp<Bitmap> allocateBitmap(SkBitmap* bitmap, SkColorTable* ctable, AllocPixeRef alloc) {
+static sk_sp<Bitmap> allocateBitmap(SkBitmap* bitmap, sk_sp<SkColorTable> ctable, AllocPixeRef alloc) {
     const SkImageInfo& info = bitmap->info();
     if (info.colorType() == kUnknown_SkColorType) {
         LOG_ALWAYS_FATAL("unknown bitmap configuration");
@@ -69,27 +69,24 @@
         return nullptr;
     }
 
-    auto wrapper = alloc(size, info, rowBytes, ctable);
+    auto wrapper = alloc(size, info, rowBytes, std::move(ctable));
     if (wrapper) {
         wrapper->getSkBitmap(bitmap);
-        // since we're already allocated, we lockPixels right away
-        // HeapAllocator behaves this way too
-        bitmap->lockPixels();
     }
     return wrapper;
 }
 
-sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(SkBitmap* bitmap, SkColorTable* ctable) {
-   return allocateBitmap(bitmap, ctable, &Bitmap::allocateAshmemBitmap);
+sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(SkBitmap* bitmap, sk_sp<SkColorTable> ctable) {
+   return allocateBitmap(bitmap, std::move(ctable), &Bitmap::allocateAshmemBitmap);
 }
 
 static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& info, size_t rowBytes,
-        SkColorTable* ctable) {
+        sk_sp<SkColorTable> ctable) {
     void* addr = calloc(size, 1);
     if (!addr) {
         return nullptr;
     }
-    return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes, ctable));
+    return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes, std::move(ctable)));
 }
 
 #define FENCE_TIMEOUT 2000000000
@@ -170,7 +167,6 @@
 
 static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bitmap,
         GraphicBuffer& buffer, GLint format, GLint type) {
-    SkAutoLockPixels alp(bitmap);
     EGLDisplay display = eglGetCurrentDisplay();
     LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
                 "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
@@ -262,8 +258,8 @@
     return uirenderer::renderthread::RenderProxy::allocateHardwareBitmap(bitmap);
 }
 
-sk_sp<Bitmap> Bitmap::allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable) {
-   return allocateBitmap(bitmap, ctable, &android::allocateHeapBitmap);
+sk_sp<Bitmap> Bitmap::allocateHeapBitmap(SkBitmap* bitmap, sk_sp<SkColorTable> ctable) {
+   return allocateBitmap(bitmap, std::move(ctable), &android::allocateHeapBitmap);
 }
 
 sk_sp<Bitmap> Bitmap::allocateHeapBitmap(const SkImageInfo& info) {
@@ -276,7 +272,7 @@
 }
 
 sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info,
-        size_t rowBytes, SkColorTable* ctable) {
+        size_t rowBytes, sk_sp<SkColorTable> ctable) {
     // Create new ashmem region with read/write priv
     int fd = ashmem_create_region("bitmap", size);
     if (fd < 0) {
@@ -294,20 +290,18 @@
         close(fd);
         return nullptr;
     }
-    return sk_sp<Bitmap>(new Bitmap(addr, fd, size, info, rowBytes, ctable));
+    return sk_sp<Bitmap>(new Bitmap(addr, fd, size, info, rowBytes, std::move(ctable)));
 }
 
 void FreePixelRef(void* addr, void* context) {
     auto pixelRef = (SkPixelRef*) context;
-    pixelRef->unlockPixels();
     pixelRef->unref();
 }
 
 sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, SkPixelRef& pixelRef) {
     pixelRef.ref();
-    pixelRef.lockPixels();
     return sk_sp<Bitmap>(new Bitmap((void*) pixelRef.pixels(), (void*) &pixelRef, FreePixelRef,
-            info, pixelRef.rowBytes(), pixelRef.colorTable()));
+            info, pixelRef.rowBytes(), sk_ref_sp(pixelRef.colorTable())));
 }
 
 sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer) {
@@ -323,19 +317,13 @@
 }
 
 void Bitmap::setColorSpace(sk_sp<SkColorSpace> colorSpace) {
-    // TODO: See todo in reconfigure() below
-    SkImageInfo* myInfo = const_cast<SkImageInfo*>(&this->info());
-    *myInfo = info().makeColorSpace(std::move(colorSpace));
+    reconfigure(info().makeColorSpace(std::move(colorSpace)), rowBytes(), sk_ref_sp(colorTable()));
 }
 
-void Bitmap::reconfigure(const SkImageInfo& newInfo, size_t rowBytes, SkColorTable* ctable) {
+void Bitmap::reconfigure(const SkImageInfo& newInfo, size_t rowBytes, sk_sp<SkColorTable> ctable) {
     if (kIndex_8_SkColorType != newInfo.colorType()) {
         ctable = nullptr;
     }
-    mRowBytes = rowBytes;
-    if (mColorTable.get() != ctable) {
-        mColorTable.reset(SkSafeRef(ctable));
-    }
 
     // Need to validate the alpha type to filter against the color type
     // to prevent things like a non-opaque RGB565 bitmap
@@ -349,50 +337,48 @@
     // really hard to work with. Skia really, really wants immutable objects,
     // but with the nested-ref-count hackery going on that's just not
     // feasible without going insane trying to figure it out
-    SkImageInfo* myInfo = const_cast<SkImageInfo*>(&this->info());
-    *myInfo = newInfo;
-    changeAlphaType(alphaType);
-
-    // Docs say to only call this in the ctor, but we're going to call
-    // it anyway even if this isn't always the ctor.
-    // TODO: Fix this too as part of the above TODO
-    setPreLocked(getStorage(), mRowBytes, mColorTable.get());
+    this->android_only_reset(newInfo.makeAlphaType(alphaType), rowBytes, std::move(ctable));
 }
 
-Bitmap::Bitmap(void* address, size_t size, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
-            : SkPixelRef(info)
+static sk_sp<SkColorTable> sanitize(const SkImageInfo& info, sk_sp<SkColorTable> ctable) {
+    if (info.colorType() == kIndex_8_SkColorType) {
+        SkASSERT(ctable);
+        return ctable;
+    }
+    return nullptr; // drop the ctable if we're not indexed
+}
+Bitmap::Bitmap(void* address, size_t size, const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable)
+            : SkPixelRef(info, address, rowBytes, sanitize(info, std::move(ctable)))
             , mPixelStorageType(PixelStorageType::Heap) {
     mPixelStorage.heap.address = address;
     mPixelStorage.heap.size = size;
-    reconfigure(info, rowBytes, ctable);
 }
 
 Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc,
-                const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
-            : SkPixelRef(info)
+                const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable)
+            : SkPixelRef(info, address, rowBytes, sanitize(info, std::move(ctable)))
             , mPixelStorageType(PixelStorageType::External) {
     mPixelStorage.external.address = address;
     mPixelStorage.external.context = context;
     mPixelStorage.external.freeFunc = freeFunc;
-    reconfigure(info, rowBytes, ctable);
 }
 
 Bitmap::Bitmap(void* address, int fd, size_t mappedSize,
-                const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
-            : SkPixelRef(info)
+                const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable)
+            : SkPixelRef(info, address, rowBytes, sanitize(info, std::move(ctable)))
             , mPixelStorageType(PixelStorageType::Ashmem) {
     mPixelStorage.ashmem.address = address;
     mPixelStorage.ashmem.fd = fd;
     mPixelStorage.ashmem.size = mappedSize;
-    reconfigure(info, rowBytes, ctable);
 }
 
 Bitmap::Bitmap(GraphicBuffer* buffer, const SkImageInfo& info)
-        : SkPixelRef(info)
+        : SkPixelRef(info, nullptr,
+                     bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride(),
+                     nullptr)
         , mPixelStorageType(PixelStorageType::Hardware) {
     mPixelStorage.hardware.buffer = buffer;
     buffer->incStrong(buffer);
-    mRowBytes = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride();
 }
 
 Bitmap::~Bitmap() {
@@ -442,15 +428,8 @@
     }
 }
 
-bool Bitmap::onNewLockPixels(LockRec* rec) {
-    rec->fPixels = getStorage();
-    rec->fRowBytes = mRowBytes;
-    rec->fColorTable = mColorTable.get();
-    return true;
-}
-
 size_t Bitmap::getAllocatedSizeInBytes() const {
-    return info().getSafeSize(mRowBytes);
+    return info().getSafeSize(this->rowBytes());
 }
 
 int Bitmap::getAshmemFd() const {
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 3ade3fe..701b9db 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -44,14 +44,14 @@
 
 class ANDROID_API Bitmap : public SkPixelRef {
 public:
-    static sk_sp<Bitmap> allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable);
+    static sk_sp<Bitmap> allocateHeapBitmap(SkBitmap* bitmap, sk_sp<SkColorTable> ctable);
     static sk_sp<Bitmap> allocateHeapBitmap(const SkImageInfo& info);
 
     static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
 
-    static sk_sp<Bitmap> allocateAshmemBitmap(SkBitmap* bitmap, SkColorTable* ctable);
+    static sk_sp<Bitmap> allocateAshmemBitmap(SkBitmap* bitmap, sk_sp<SkColorTable> ctable);
     static sk_sp<Bitmap> allocateAshmemBitmap(size_t allocSize, const SkImageInfo& info,
-        size_t rowBytes, SkColorTable* ctable);
+        size_t rowBytes, sk_sp<SkColorTable> ctable);
 
     static sk_sp<Bitmap> createFrom(sp<GraphicBuffer> graphicBuffer);
 
@@ -61,27 +61,20 @@
             SkBitmap& bitmap);
 
     Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes,
-            SkColorTable* ctable);
+            sk_sp<SkColorTable> ctable);
     Bitmap(void* address, void* context, FreeFunc freeFunc,
-            const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
+            const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable);
     Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
-            size_t rowBytes, SkColorTable* ctable);
+            size_t rowBytes, sk_sp<SkColorTable> ctable);
 
     int width() const { return info().width(); }
     int height() const { return info().height(); }
 
-    // Can't mark as override since SkPixelRef::rowBytes isn't virtual
-    // but that's OK since we just want Bitmap to be able to rely
-    // on calling rowBytes() on an unlocked pixelref, which it will be
-    // doing on a Bitmap type, not a SkPixelRef, so static
-    // dispatching will do what we want.
-    size_t rowBytes() const { return mRowBytes; }
-
     int rowBytesAsPixels() const {
-        return mRowBytes >> info().shiftPerPixel();
+        return rowBytes() >> info().shiftPerPixel();
     }
 
-    void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
+    void reconfigure(const SkImageInfo& info, size_t rowBytes, sk_sp<SkColorTable> ctable);
     void reconfigure(const SkImageInfo& info);
     void setColorSpace(sk_sp<SkColorSpace> colorSpace);
     void setAlphaType(SkAlphaType alphaType);
@@ -103,7 +96,7 @@
     void getBounds(SkRect* bounds) const;
 
     bool readyToDraw() const {
-        return this->colorType() != kIndex_8_SkColorType || mColorTable;
+        return this->colorType() != kIndex_8_SkColorType || this->colorTable();
     }
 
     bool isHardware() const {
@@ -112,8 +105,6 @@
 
     GraphicBuffer* graphicBuffer();
 protected:
-    virtual bool onNewLockPixels(LockRec* rec) override;
-    virtual void onUnlockPixels() override { };
     virtual size_t getAllocatedSizeInBytes() const override;
 private:
     Bitmap(GraphicBuffer* buffer, const SkImageInfo& info);
@@ -122,8 +113,6 @@
 
     const PixelStorageType mPixelStorageType;
 
-    size_t mRowBytes = 0;
-    sk_sp<SkColorTable> mColorTable;
     bool mHasHardwareMipMap = false;
 
     union {
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 4b8575a..4fb4b533 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -39,14 +39,22 @@
 
 namespace android {
 
-// Resolve the 1..9 weight based on base weight and bold flag
+// This indicates that the passed information should be resolved by OS/2 table.
+// This value must be the same as the android.graphics.Typeface$Builder.RESOLVE_BY_FONT_TABLE.
+constexpr int RESOLVE_BY_FONT_TABLE = -1;
+
+// Resolve the 1..10 weight based on base weight and bold flag
 static void resolveStyle(Typeface* typeface) {
-    int weight = typeface->fBaseWeight / 100;
+    // TODO: Better to use raw base weight value for font selection instead of dividing by 100.
+    int weight = (typeface->fBaseWeight + 50) / 100;
     if (typeface->fSkiaStyle & SkTypeface::kBold) {
         weight += 3;
     }
-    if (weight > 9) {
-        weight = 9;
+    if (weight > 10) {
+        weight = 10;
+    }
+    if (weight < 1) {
+        weight = 1;
     }
     bool italic = (typeface->fSkiaStyle & SkTypeface::kItalic) != 0;
     typeface->fStyle = minikin::FontStyle(weight, italic);
@@ -71,6 +79,18 @@
     return result;
 }
 
+Typeface* Typeface::createFromTypefaceWithStyle(Typeface* base, int weight, bool italic) {
+    Typeface* resolvedFace = Typeface::resolveDefault(base);
+    Typeface* result = new Typeface();
+    if (result != nullptr) {
+        result->fFontCollection = resolvedFace->fFontCollection;
+        result->fBaseWeight = weight;
+        result->fStyle = minikin::FontStyle(weight / 100, italic);
+        result->fSkiaStyle = resolvedFace->fSkiaStyle;
+    }
+    return result;
+}
+
 Typeface* Typeface::createFromTypefaceWithVariation(Typeface* src,
         const std::vector<minikin::FontVariation>& variations) {
     Typeface* resolvedFace = Typeface::resolveDefault(src);
@@ -103,26 +123,50 @@
 }
 
 Typeface* Typeface::createFromFamilies(
-        std::vector<std::shared_ptr<minikin::FontFamily>>&& families) {
+        std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
+        int weight, int italic) {
     Typeface* result = new Typeface;
     result->fFontCollection.reset(new minikin::FontCollection(families));
-    if (families.empty()) {
-        ALOGW("createFromFamilies creating empty collection");
-        result->fSkiaStyle = SkTypeface::kNormal;
-    } else {
+
+    if (weight == RESOLVE_BY_FONT_TABLE || italic == RESOLVE_BY_FONT_TABLE) {
+        int weightFromFont;
+        bool italicFromFont;
+
         const minikin::FontStyle defaultStyle;
-        const std::shared_ptr<minikin::FontFamily>& firstFamily = families[0];
-        const minikin::MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
+        const minikin::MinikinFont* mf =
+                families.empty() ?  nullptr : families[0]->getClosestMatch(defaultStyle).font;
         if (mf != nullptr) {
             SkTypeface* skTypeface = reinterpret_cast<const MinikinFontSkia*>(mf)->GetSkTypeface();
-            // TODO: probably better to query more precise style from family, will be important
-            // when we open up API to access 100..900 weights
-            result->fSkiaStyle = skTypeface->style();
+            const SkFontStyle& style = skTypeface->fontStyle();
+            weightFromFont = style.weight();
+            italicFromFont = style.slant() != SkFontStyle::kUpright_Slant;
         } else {
-            result->fSkiaStyle = SkTypeface::kNormal;
+            // We can't obtain any information from fonts. Just use default values.
+            weightFromFont = SkFontStyle::kNormal_Weight;
+            italicFromFont = false;
+        }
+
+        if (weight == RESOLVE_BY_FONT_TABLE) {
+            weight = weightFromFont;
+        }
+        if (italic == RESOLVE_BY_FONT_TABLE) {
+            italic = italicFromFont? 1 : 0;
         }
     }
-    result->fBaseWeight = 400;
+
+    // Sanitize the invalid value passed from public API.
+    if (weight < 0) {
+        weight = SkFontStyle::kNormal_Weight;
+    }
+
+    result->fBaseWeight = weight;
+    // This bold detection comes from SkTypefae.h
+    const bool isBold = weight >= SkFontStyle::kSemiBold_Weight;
+    const bool isItalic = italic == 1;
+    // TODO: remove fSkiaStyle
+    result->fSkiaStyle = isBold ?
+            (isItalic ? SkTypeface::kBoldItalic : SkTypeface::kBold) :
+            (isItalic ? SkTypeface::kItalic : SkTypeface::kNormal);
     resolveStyle(result);
     return result;
 }
@@ -153,7 +197,7 @@
     Typeface* hwTypeface = new Typeface();
     hwTypeface->fFontCollection = collection;
     hwTypeface->fSkiaStyle = SkTypeface::kNormal;
-    hwTypeface->fBaseWeight = 400;
+    hwTypeface->fBaseWeight = SkFontStyle::kSemiBold_Weight;
     hwTypeface->fStyle = minikin::FontStyle(4 /* weight */, false /* italic */);
 
     Typeface::setDefault(hwTypeface);
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index 19a4f6c5..e35a7b4 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -42,13 +42,16 @@
 
     static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
 
+    static Typeface* createFromTypefaceWithStyle(Typeface* base, int weight, bool italic);
+
     static Typeface* createFromTypefaceWithVariation(Typeface* src,
             const std::vector<minikin::FontVariation>& variations);
 
     static Typeface* createWeightAlias(Typeface* src, int baseweight);
 
     static Typeface* createFromFamilies(
-            std::vector<std::shared_ptr<minikin::FontFamily>>&& families);
+            std::vector<std::shared_ptr<minikin::FontFamily>>&& families,
+            int weight, int italic);
 
     static void setDefault(Typeface* face);
 
diff --git a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
index d26eb59..68a0869 100644
--- a/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
+++ b/libs/hwui/pipeline/skia/ReorderBarrierDrawables.cpp
@@ -190,9 +190,32 @@
     }
     const Vector3 lightPos = SkiaPipeline::getLightCenter();
     SkPoint3 skiaLightPos = SkPoint3::Make(lightPos.x, lightPos.y, lightPos.z);
-    SkShadowUtils::DrawShadow(canvas, *casterPath, casterZValue, skiaLightPos,
+    if (shadowMatrix.hasPerspective() || revealClipPath || clippedToBounds) {
+        std::function<SkScalar(SkScalar, SkScalar)> casterHeightFunc;
+        if (shadowMatrix.hasPerspective()) {
+            // get the matrix with the full 3D transform
+            mat4 zMatrix;
+            caster->getRenderNode()->applyViewPropertyTransforms(zMatrix, true);
+            SkScalar A = zMatrix[2];
+            SkScalar B = zMatrix[6];
+            SkScalar C = zMatrix[mat4::kTranslateZ];
+            casterHeightFunc = [A, B, C](SkScalar x, SkScalar y) {
+                return A*x + B*y + C;  // casterZValue already baked into C
+            };
+        } else {
+            casterHeightFunc = [casterZValue] (SkScalar, SkScalar) {
+                return casterZValue;
+            };
+        }
+
+        SkShadowUtils::DrawUncachedShadow(canvas, *casterPath, casterHeightFunc, skiaLightPos,
             SkiaPipeline::getLightRadius(), ambientAlpha, spotAlpha, SK_ColorBLACK,
             casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
+    } else {
+        SkShadowUtils::DrawShadow(canvas, *casterPath, casterZValue, skiaLightPos,
+            SkiaPipeline::getLightRadius(), ambientAlpha, spotAlpha, SK_ColorBLACK,
+            casterAlpha < 1.0f ? SkShadowFlags::kTransparentOccluder_ShadowFlag : 0);
+    }
 }
 
 }; // namespace skiapipeline
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index a18d264..04aeb7c 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -63,8 +63,6 @@
     CopyResult copyResult = CopyResult::UnknownError;
     sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), textureDescription));
     if (image) {
-        SkAutoLockPixels alp(*bitmap);
-
         // convert to Skia data structures
         const SkRect bufferRect = SkRect::MakeIWH(imgWidth, imgHeight);
         SkRect skiaSrcRect = srcRect.toSkRect();
diff --git a/libs/hwui/tests/unit/BitmapTests.cpp b/libs/hwui/tests/unit/BitmapTests.cpp
index 225d2b2..ed689bd 100644
--- a/libs/hwui/tests/unit/BitmapTests.cpp
+++ b/libs/hwui/tests/unit/BitmapTests.cpp
@@ -34,7 +34,7 @@
     SkBitmap* bm = new SkBitmap();
     bm->allocPixels(SkImageInfo::Make(1, 1, kIndex_8_SkColorType, kPremul_SkAlphaType),
             ctable);
-    sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(bm, ctable.get());
+    sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(bm, ctable);
     EXPECT_FALSE(ctable->unique());
     delete bm;
     bitmap.reset();
diff --git a/libs/hwui/tests/unit/FontRendererTests.cpp b/libs/hwui/tests/unit/FontRendererTests.cpp
index ee20236..773a7ea 100644
--- a/libs/hwui/tests/unit/FontRendererTests.cpp
+++ b/libs/hwui/tests/unit/FontRendererTests.cpp
@@ -28,7 +28,7 @@
     return true;
 }
 
-RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, renderDropShadow) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, DISABLED_renderDropShadow) {
     SkPaint paint;
     paint.setTextSize(10);
     paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index 0d1eba4..c048dda 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -89,7 +89,6 @@
     sk_sp<Bitmap> adobeBitmap = Bitmap::allocateHeapBitmap(adobeInfo);
     SkBitmap adobeSkBitmap;
     adobeBitmap->getSkBitmap(&adobeSkBitmap);
-    adobeSkBitmap.lockPixels();
     *adobeSkBitmap.getAddr32(0, 0) = 0xFF0000F0; // Opaque, almost fully-red
 
     SkImageInfo info = adobeInfo.makeColorSpace(nullptr);
@@ -101,17 +100,21 @@
     SkiaCanvas canvas(skBitmap);
     canvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
     // The result should be fully red, since we convert to sRGB at draw time.
-    skBitmap.lockPixels();
     ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
 
+    // Create a software canvas with an Adobe color space.
+    SkiaCanvas adobeSkCanvas(adobeSkBitmap);
+    adobeSkCanvas.drawBitmap(*bitmap, 0, 0, nullptr);
+    // The result should be less than fully red, since we convert to Adobe RGB at draw time.
+    ASSERT_EQ(0xFF0000DC, *adobeSkBitmap.getAddr32(0, 0));
+
     // Now try in kDefer mode.  This is a little strange given that, in practice, all software
     // canvases are kImmediate.
     SkCanvas skCanvas(skBitmap);
     SkiaCanvas deferCanvas(&skCanvas, Canvas::XformToSRGB::kDefer);
     deferCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
-    // The result should be as initialized, since we deferred the conversion to sRGB.
-    skBitmap.lockPixels();
-    ASSERT_EQ(0xFF0000F0, *skBitmap.getAddr32(0, 0));
+    // The result should be as before, since we deferred the conversion to sRGB.
+    ASSERT_EQ(0xFF0000DC, *skBitmap.getAddr32(0, 0));
 
     // Test picture recording.  We will kDefer the xform at recording time, but handle it when
     // we playback to the software canvas.
@@ -121,9 +124,9 @@
     picCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
     sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
 
-    // Playback to a deferred canvas.  The result should be as initialized.
+    // Playback to a deferred canvas.  The result should be as before.
     deferCanvas.asSkCanvas()->drawPicture(picture);
-    ASSERT_EQ(0xFF0000F0, *skBitmap.getAddr32(0, 0));
+    ASSERT_EQ(0xFF0000DC, *skBitmap.getAddr32(0, 0));
 
     // Playback to an immediate canvas.  The result should be fully red.
     canvas.asSkCanvas()->drawPicture(picture);
diff --git a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
index 8312bda..5383e57 100644
--- a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
+++ b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
@@ -26,7 +26,7 @@
 using namespace android;
 using namespace android::uirenderer;
 
-RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, addRemove) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, DISABLED_addRemove) {
     SkPaint paint;
     paint.setTextSize(20);
 
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
new file mode 100644
index 0000000..4310706
--- /dev/null
+++ b/libs/input/Android.bp
@@ -0,0 +1,44 @@
+// 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.
+
+cc_library_shared {
+    name: "libinputservice",
+
+    srcs: [
+        "PointerController.cpp",
+        "SpriteController.cpp",
+    ],
+
+    shared_libs: [
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libskia",
+        "libgui",
+        "libui",
+        "libinput",
+        "libinputflinger",
+        "libnativewindow",
+    ],
+
+    include_dirs: ["frameworks/native/services"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+
+}
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
deleted file mode 100644
index e824275..0000000
--- a/libs/input/Android.mk
+++ /dev/null
@@ -1,54 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    PointerController.cpp \
-    SpriteController.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    liblog \
-    libutils \
-    libskia \
-    libgui \
-    libui \
-    libinput \
-    libinputflinger \
-    libnativewindow
-
-LOCAL_C_INCLUDES := \
-    frameworks/native/services
-
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-LOCAL_MODULE:= libinputservice
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index aac9727..de85c16 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -670,6 +670,8 @@
      * related to L5 will be filled.
      *
      * <p>The value is only available if {@link #hasCarrierFrequencyHz()} is {@code true}.
+     *
+     * @return the carrier frequency of the signal tracked in Hz.
      */
     public float getCarrierFrequencyHz() {
         return mCarrierFrequencyHz;
@@ -888,10 +890,10 @@
     }
 
     /**
-     * Returns {@code true} if {@link #getAutomaticGainControlLevelInDb()} is available,
+     * Returns {@code true} if {@link #getAutomaticGainControlLevelDb()} is available,
      * {@code false} otherwise.
      */
-    public boolean hasAutomaticGainControlLevelInDb() {
+    public boolean hasAutomaticGainControlLevelDb() {
         return isFlagSet(HAS_AUTOMATIC_GAIN_CONTROL);
     }
 
@@ -908,9 +910,9 @@
      * components) may also affect the typical output of of this value on any given hardware design
      * in an open sky test - the important aspect of this output is that changes in this value are
      * indicative of changes on input signal power in the frequency band for this measurement.
-     * <p>The value is only available if {@link #hasAutomaticGainControlLevelInDb()} is {@code true}
+     * <p>The value is only available if {@link #hasAutomaticGainControlLevelDb()} is {@code true}
      */
-    public double getAutomaticGainControlLevelInDb() {
+    public double getAutomaticGainControlLevelDb() {
         return mAutomaticGainControlLevelInDb;
     }
 
@@ -1064,7 +1066,7 @@
         builder.append(String.format(
             format,
             "AgcLevelDb",
-            hasAutomaticGainControlLevelInDb() ? mAutomaticGainControlLevelInDb : null));
+            hasAutomaticGainControlLevelDb() ? mAutomaticGainControlLevelInDb : null));
 
         return builder.toString();
     }
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index e90a174..a44bc5b 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -224,7 +224,7 @@
      *
      * @param satIndex the index of the satellite in the list.
      */
-    public boolean hasCarrierFrequency(int satIndex) {
+    public boolean hasCarrierFrequencyHz(int satIndex) {
         return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY) != 0;
     }
 
@@ -239,7 +239,11 @@
      * will be reported for this same satellite, in one all the values related to L1 will be filled,
      * and in the other all of the values related to L5 will be filled.
      *
-     * <p>The value is only available if {@link #hasCarrierFrequency(int satIndex)} is {@code true}.
+     * <p>The value is only available if {@link #hasCarrierFrequencyHz(int satIndex)} is {@code true}.
+     *
+     * @param satIndex the index of the satellite in the list.
+     *
+     * @return the carrier frequency of the signal tracked in Hz.
      */
     public float getCarrierFrequencyHz(int satIndex) {
         return mCarrierFrequencies[satIndex];
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index b222a6d..68f46ad 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -646,7 +646,10 @@
      *
      * <p>Following this call {@link #hasAltitude} will return false,
      * and {@link #getAltitude} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
      */
+    @Deprecated
     public void removeAltitude() {
         mAltitude = 0.0f;
         mFieldsMask &= ~HAS_ALTITUDE_MASK;
@@ -683,7 +686,10 @@
      *
      * <p>Following this call {@link #hasSpeed} will return false,
      * and {@link #getSpeed} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
      */
+    @Deprecated
     public void removeSpeed() {
         mSpeed = 0.0f;
         mFieldsMask &= ~HAS_SPEED_MASK;
@@ -733,7 +739,10 @@
      *
      * <p>Following this call {@link #hasBearing} will return false,
      * and {@link #getBearing} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
      */
+    @Deprecated
     public void removeBearing() {
         mBearing = 0.0f;
         mFieldsMask &= ~HAS_BEARING_MASK;
@@ -790,7 +799,10 @@
      *
      * <p>Following this call {@link #hasAccuracy} will return false, and
      * {@link #getAccuracy} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
      */
+    @Deprecated
     public void removeAccuracy() {
         mHorizontalAccuracyMeters = 0.0f;
         mFieldsMask &= ~HAS_HORIZONTAL_ACCURACY_MASK;
@@ -839,7 +851,11 @@
      *
      * <p>Following this call {@link #hasVerticalAccuracy} will return false, and
      * {@link #getVerticalAccuracyMeters} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
+     * @removed
      */
+    @Deprecated
     public void removeVerticalAccuracy() {
         mVerticalAccuracyMeters = 0.0f;
         mFieldsMask &= ~HAS_VERTICAL_ACCURACY_MASK;
@@ -883,7 +899,11 @@
      *
      * <p>Following this call {@link #hasSpeedAccuracy} will return false, and
      * {@link #getSpeedAccuracyMetersPerSecond} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
+     * @removed
      */
+    @Deprecated
     public void removeSpeedAccuracy() {
         mSpeedAccuracyMetersPerSecond = 0.0f;
         mFieldsMask &= ~HAS_SPEED_ACCURACY_MASK;
@@ -927,7 +947,11 @@
      *
      * <p>Following this call {@link #hasBearingAccuracy} will return false, and
      * {@link #getBearingAccuracyDegrees} will return 0.0.
+     *
+     * @deprecated use a new Location object for location updates.
+     * @removed
      */
+    @Deprecated
     public void removeBearingAccuracy() {
         mBearingAccuracyDegrees = 0.0f;
         mFieldsMask &= ~HAS_BEARING_ACCURACY_MASK;
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 611fdd1..ce50cc8 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -51,12 +51,13 @@
  * management messages) can be distributed out-of-band, or in-band with the stream.
  * <p>
  * To descramble elementary streams, the app first calls {@link #openSession} to
- * generate a sessionId that will uniquely identify a session. A session provides
- * a context for subsequent key updates and descrambling activities. The ECMs
- * (Entitlement control messages) are sent to the session via method {@link #processEcm}.
+ * generate a {@link Session} object that will uniquely identify a session. A session
+ * provides a context for subsequent key updates and descrambling activities. The ECMs
+ * (Entitlement control messages) are sent to the session via method
+ * {@link Session#processEcm}.
  * <p>
  * The app next constructs a MediaDescrambler object, and initializes it with the
- * sessionId using {@link MediaDescrambler#setMediaCasSession}. This ties the
+ * session using {@link MediaDescrambler#setMediaCasSession}. This ties the
  * descrambler to the session, and the descrambler can then be used to descramble
  * content secured with the session's key, either during extraction, or during decoding
  * with {@link android.media.MediaCodec}.
@@ -79,19 +80,20 @@
  * If the app uses {@link MediaExtractor}, it can delegate the CAS session
  * management to MediaExtractor by calling {@link MediaExtractor#setMediaCas}.
  * MediaExtractor will take over and call {@link #openSession}, {@link #processEmm}
- * and/or {@link #processEcm}, etc.. if necessary.
+ * and/or {@link Session#processEcm}, etc.. if necessary.
  * <p>
  * When using {@link MediaExtractor}, the app would still need a MediaDescrambler
  * to use with {@link MediaCodec} if the licensing requires a secure decoder. The
- * sessionId of the descrambler can be retrieved by {@link MediaExtractor#getDrmInitData}
- * and used to initialize a MediaDescrambler object for MediaCodec.
+ * session associated with the descrambler of a track can be retrieved by calling
+ * {@link MediaExtractor#getCasInfo}, and used to initialize a MediaDescrambler
+ * object for MediaCodec.
  * <p>
  * <h3>Listeners</h3>
  * <p>The app may register a listener to receive events from the CA system using
  * method {@link #setEventListener}. The exact format of the event is scheme-specific
  * and is not specified by this API.
  */
-public final class MediaCas {
+public final class MediaCas implements AutoCloseable {
     private static final String TAG = "MediaCas";
     private final ParcelableCasData mCasData = new ParcelableCasData();
     private ICas mICas;
@@ -229,6 +231,106 @@
     }
 
     /**
+     * Class for an open session with the CA system.
+     */
+    public final class Session implements AutoCloseable {
+        final byte[] mSessionId;
+
+        Session(@NonNull byte[] sessionId) {
+            mSessionId = sessionId;
+        }
+
+        /**
+         * Set the private data for a session.
+         *
+         * @param data byte array of the private data.
+         *
+         * @throws IllegalStateException if the MediaCas instance is not valid.
+         * @throws MediaCasException for CAS-specific errors.
+         * @throws MediaCasStateException for CAS-specific state exceptions.
+         */
+        public void setPrivateData(@NonNull byte[] data)
+                throws MediaCasException {
+            validateInternalStates();
+
+            try {
+                mICas.setSessionPrivateData(mSessionId, data);
+            } catch (ServiceSpecificException e) {
+                MediaCasException.throwExceptions(e);
+            } catch (RemoteException e) {
+                cleanupAndRethrowIllegalState();
+            }
+        }
+
+
+        /**
+         * Send a received ECM packet to the specified session of the CA system.
+         *
+         * @param data byte array of the ECM data.
+         * @param offset position within data where the ECM data begins.
+         * @param length length of the data (starting from offset).
+         *
+         * @throws IllegalStateException if the MediaCas instance is not valid.
+         * @throws MediaCasException for CAS-specific errors.
+         * @throws MediaCasStateException for CAS-specific state exceptions.
+         */
+        public void processEcm(@NonNull byte[] data, int offset, int length)
+                throws MediaCasException {
+            validateInternalStates();
+
+            try {
+                mCasData.set(data, offset, length);
+                mICas.processEcm(mSessionId, mCasData);
+            } catch (ServiceSpecificException e) {
+                MediaCasException.throwExceptions(e);
+            } catch (RemoteException e) {
+                cleanupAndRethrowIllegalState();
+            }
+        }
+
+        /**
+         * Send a received ECM packet to the specified session of the CA system.
+         * This is similar to {@link Session#processEcm(byte[], int, int)}
+         * except that the entire byte array is sent.
+         *
+         * @param data byte array of the ECM data.
+         *
+         * @throws IllegalStateException if the MediaCas instance is not valid.
+         * @throws MediaCasException for CAS-specific errors.
+         * @throws MediaCasStateException for CAS-specific state exceptions.
+         */
+        public void processEcm(@NonNull byte[] data) throws MediaCasException {
+            processEcm(data, 0, data.length);
+        }
+
+        /**
+         * Close the session.
+         *
+         * @throws IllegalStateException if the MediaCas instance is not valid.
+         * @throws MediaCasStateException for CAS-specific state exceptions.
+         */
+        @Override
+        public void close() {
+            validateInternalStates();
+
+            try {
+                mICas.closeSession(mSessionId);
+            } catch (ServiceSpecificException e) {
+                MediaCasStateException.throwExceptions(e);
+            } catch (RemoteException e) {
+                cleanupAndRethrowIllegalState();
+            }
+        }
+    }
+
+    Session createFromSessionId(byte[] sessionId) {
+        if (sessionId == null || sessionId.length == 0) {
+            return null;
+        }
+        return new Session(sessionId);
+    }
+
+    /**
      * Class for parceling CAS plugin descriptors over IMediaCasService binder.
      */
     static class ParcelableCasPluginDescriptor
@@ -404,21 +506,20 @@
     }
 
     /**
-     * Open a session for the specified program.
+     * Open a session to descramble one or more streams scrambled by the
+     * conditional access system.
      *
-     * @param programNumber program_number of the program (as in ISO/IEC13818-1).
-     *
-     * @return session id of the newly opened session.
+     * @return session the newly opened session.
      *
      * @throws IllegalStateException if the MediaCas instance is not valid.
      * @throws MediaCasException for CAS-specific errors.
      * @throws MediaCasStateException for CAS-specific state exceptions.
      */
-    public byte[] openSession(int programNumber) throws MediaCasException {
+    public Session openSession() throws MediaCasException {
         validateInternalStates();
 
         try {
-            return mICas.openSession(programNumber);
+            return createFromSessionId(mICas.openSession());
         } catch (ServiceSpecificException e) {
             MediaCasException.throwExceptions(e);
         } catch (RemoteException e) {
@@ -428,118 +529,6 @@
     }
 
     /**
-     * Open a session for the specified stream.
-     *
-     * @param programNumber program_number of the stream (as in ISO/IEC13818-1).
-     * @param elementaryPID elementary_PID of the stream (as in ISO/IEC13818-1).
-     *
-     * @return session id of the newly opened session.
-     *
-     * @throws IllegalStateException if the MediaCas instance is not valid.
-     * @throws MediaCasException for CAS-specific errors.
-     * @throws MediaCasStateException for CAS-specific state exceptions.
-     */
-    public byte[] openSession(int programNumber, int elementaryPID)
-            throws MediaCasException {
-        validateInternalStates();
-
-        try {
-            return mICas.openSessionForStream(programNumber, elementaryPID);
-        } catch (ServiceSpecificException e) {
-            MediaCasException.throwExceptions(e);
-        } catch (RemoteException e) {
-            cleanupAndRethrowIllegalState();
-        }
-        return null;
-    }
-
-    /**
-     * Close the specified session.
-     *
-     * @param sessionId the session to be closed.
-     *
-     * @throws IllegalStateException if the MediaCas instance is not valid.
-     * @throws MediaCasStateException for CAS-specific state exceptions.
-     */
-    public void closeSession(@NonNull byte[] sessionId) {
-        validateInternalStates();
-
-        try {
-            mICas.closeSession(sessionId);
-        } catch (ServiceSpecificException e) {
-            MediaCasStateException.throwExceptions(e);
-        } catch (RemoteException e) {
-            cleanupAndRethrowIllegalState();
-        }
-    }
-
-    /**
-     * Set the private data for a session.
-     *
-     * @param sessionId the session for which the private data is intended.
-     * @param data byte array of the private data.
-     *
-     * @throws IllegalStateException if the MediaCas instance is not valid.
-     * @throws MediaCasException for CAS-specific errors.
-     * @throws MediaCasStateException for CAS-specific state exceptions.
-     */
-    public void setSessionPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data)
-            throws MediaCasException {
-        validateInternalStates();
-
-        try {
-            mICas.setSessionPrivateData(sessionId, data);
-        } catch (ServiceSpecificException e) {
-            MediaCasException.throwExceptions(e);
-        } catch (RemoteException e) {
-            cleanupAndRethrowIllegalState();
-        }
-    }
-
-    /**
-     * Send a received ECM packet to the specified session of the CA system.
-     *
-     * @param sessionId the session for which the ECM is intended.
-     * @param data byte array of the ECM data.
-     * @param offset position within data where the ECM data begins.
-     * @param length length of the data (starting from offset).
-     *
-     * @throws IllegalStateException if the MediaCas instance is not valid.
-     * @throws MediaCasException for CAS-specific errors.
-     * @throws MediaCasStateException for CAS-specific state exceptions.
-     */
-    public void processEcm(@NonNull byte[] sessionId, @NonNull byte[] data,
-            int offset, int length) throws MediaCasException {
-        validateInternalStates();
-
-        try {
-            mCasData.set(data, offset, length);
-            mICas.processEcm(sessionId, mCasData);
-        } catch (ServiceSpecificException e) {
-            MediaCasException.throwExceptions(e);
-        } catch (RemoteException e) {
-            cleanupAndRethrowIllegalState();
-        }
-    }
-
-    /**
-     * Send a received ECM packet to the specified session of the CA system.
-     * This is similar to {@link #processEcm(byte[], byte[], int, int)}
-     * except that the entire byte array is sent.
-     *
-     * @param sessionId the session for which the ECM is intended.
-     * @param data byte array of the ECM data.
-     *
-     * @throws IllegalStateException if the MediaCas instance is not valid.
-     * @throws MediaCasException for CAS-specific errors.
-     * @throws MediaCasStateException for CAS-specific state exceptions.
-     */
-    public void processEcm(@NonNull byte[] sessionId, @NonNull byte[] data)
-            throws MediaCasException {
-        processEcm(sessionId, data, 0, data.length);
-    }
-
-    /**
      * Send a received EMM packet to the CA system.
      *
      * @param data byte array of the EMM data.
@@ -650,10 +639,8 @@
         }
     }
 
-    /**
-     * Release the MediaCas instance.
-     */
-    public void release() {
+    @Override
+    public void close() {
         if (mICas != null) {
             try {
                 mICas.release();
@@ -666,6 +653,6 @@
 
     @Override
     protected void finalize() {
-        release();
+        close();
     }
 }
\ No newline at end of file
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 7ee0a7d..a856e27 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -23,12 +23,12 @@
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaMetricsSet;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.view.Surface;
 
 import java.io.IOException;
@@ -3190,20 +3190,19 @@
     /**
      *  Return Metrics data about the current codec instance.
      *
-     * @return a MediaMetricsSet containing the set of attributes and values
+     * @return a {@link PersistableBundle} containing the set of attributes and values
      * available for the media being handled by this instance of MediaCodec
-     * The attributes are descibed in {@link MediaMetricsSet.MediaCodec}.
+     * The attributes are descibed in {@link MetricsConstants}.
      *
-     *  Additional vendor-specific fields may also be present in
-     *  the return value.
+     * Additional vendor-specific fields may also be present in
+     * the return value.
      */
-    public MediaMetricsSet getMetrics() {
-        Bundle bundle = native_getMetrics();
-	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
-	return mSet;
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
     }
 
-    private native Bundle native_getMetrics();
+    private native PersistableBundle native_getMetrics();
 
     /**
      * Change a video encoder's target bitrate on the fly. The value is an
@@ -3662,4 +3661,80 @@
             private final ByteBuffer mData;
         }
     }
+
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the codec being used
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String CODEC = "android.media.mediacodec.codec";
+
+        /**
+         * Key to extract the MIME type
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String MIME_TYPE = "android.media.mediacodec.mime";
+
+        /**
+         * Key to extract what the codec mode
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is a String. Values will be one of the constants
+         * {@link #MODE_AUDIO} or {@link #MODE_VIDEO}.
+         */
+        public static final String MODE = "android.media.mediacodec.mode";
+
+        /**
+         * The value returned for the key {@link #MODE} when the
+         * codec is a audio codec.
+         */
+        public static final String MODE_AUDIO = "audio";
+
+        /**
+         * The value returned for the key {@link #MODE} when the
+         * codec is a video codec.
+         */
+        public static final String MODE_VIDEO = "video";
+
+        /**
+         * Key to extract the flag indicating whether the codec is running
+         * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         * A 0 indicates decoder; 1 indicates encoder.
+         */
+        public static final String ENCODER = "android.media.mediacodec.encoder";
+
+        /**
+         * Key to extract the flag indicating whether the codec is running
+         * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String SECURE = "android.media.mediacodec.secure";
+
+        /**
+         * Key to extract the width (in pixels) of the video track
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String WIDTH = "android.media.mediacodec.width";
+
+        /**
+         * Key to extract the height (in pixels) of the video track
+         * from the {@link MediaCodec#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String HEIGHT = "android.media.mediacodec.height";
+
+        /**
+         * Key to extract the rotation (in degrees) to properly orient the video
+         * from the {@link MediaCodec#getMetrics} return.
+         * The value is a integer.
+         */
+        public static final String ROTATION = "android.media.mediacodec.rotation";
+
+    }
 }
diff --git a/media/java/android/media/MediaDescrambler.java b/media/java/android/media/MediaDescrambler.java
index 2dd1097..b75b7dd8 100644
--- a/media/java/android/media/MediaDescrambler.java
+++ b/media/java/android/media/MediaDescrambler.java
@@ -38,7 +38,7 @@
  * Scrambling schemes are identified by 16-bit unsigned integer as in CA_system_id.
  *
  */
-public final class MediaDescrambler {
+public final class MediaDescrambler implements AutoCloseable {
     private static final String TAG = "MediaDescrambler";
     private IDescrambler mIDescrambler;
 
@@ -141,17 +141,17 @@
      * android.media.MediaCodec#queueSecureInputBuffer} by specifying even
      * or odd key in the {@link android.media.MediaCodec.CryptoInfo#key} field.
      *
-     * @param sessionId the MediaCas sessionId to associate with this
+     * @param session the MediaCas session to associate with this
      * MediaDescrambler instance.
      *
      * @throws IllegalStateException if the descrambler instance is not valid.
      * @throws MediaCasStateException for CAS-specific state exceptions.
      */
-    public final void setMediaCasSession(@NonNull byte[] sessionId) {
+    public final void setMediaCasSession(@NonNull MediaCas.Session session) {
         validateInternalStates();
 
         try {
-            mIDescrambler.setMediaCasSession(sessionId);
+            mIDescrambler.setMediaCasSession(session.mSessionId);
         } catch (ServiceSpecificException e) {
             MediaCasStateException.throwExceptions(e);
         } catch (RemoteException e) {
@@ -163,11 +163,10 @@
      * Descramble a ByteBuffer of data described by a
      * {@link android.media.MediaCodec.CryptoInfo} structure.
      *
-     * @param srcBuf ByteBuffer containing the scrambled data.
-     * @param srcPos position within src where the scrambled data starts.
-     * @param dstBuf ByteBuffer to descramble into. If null, descrambling will happen
-     * in-place and src will be used as dst.
-     * @param dstPos position within dst to put the descrambled data.
+     * @param srcBuf ByteBuffer containing the scrambled data, which starts at
+     * srcBuf.position().
+     * @param dstBuf ByteBuffer to hold the descrambled data, which starts at
+     * dstBuf.position().
      * @param cryptoInfo a {@link android.media.MediaCodec.CryptoInfo} structure
      * describing the subsamples contained in src.
      *
@@ -178,7 +177,7 @@
      * @throws MediaCasStateException for CAS-specific state exceptions.
      */
     public final int descramble(
-            @NonNull ByteBuffer srcBuf, int srcPos, ByteBuffer dstBuf, int dstPos,
+            @NonNull ByteBuffer srcBuf, @NonNull ByteBuffer dstBuf,
             @NonNull MediaCodec.CryptoInfo cryptoInfo) {
         validateInternalStates();
 
@@ -208,14 +207,16 @@
                     cryptoInfo.numSubSamples,
                     cryptoInfo.numBytesOfClearData,
                     cryptoInfo.numBytesOfEncryptedData,
-                    srcBuf, srcPos, dstBuf, dstPos);
+                    srcBuf, srcBuf.position(), srcBuf.limit(),
+                    dstBuf, dstBuf.position(), dstBuf.limit());
         } catch (ServiceSpecificException e) {
             MediaCasStateException.throwExceptions(e);
         }
         return -1;
     }
 
-    public final void release() {
+    @Override
+    public void close() {
         if (mIDescrambler != null) {
             try {
                 mIDescrambler.release();
@@ -229,7 +230,7 @@
 
     @Override
     protected void finalize() {
-        release();
+        close();
     }
 
     private static native final void native_init();
@@ -237,7 +238,8 @@
     private native final void native_release();
     private native final int native_descramble(
             byte key, int numSubSamples, int[] numBytesOfClearData, int[] numBytesOfEncryptedData,
-            @NonNull ByteBuffer srcBuf, int srcOffset, ByteBuffer dstBuf, int dstOffset);
+            @NonNull ByteBuffer srcBuf, int srcOffset, int srcLimit,
+            ByteBuffer dstBuf, int dstOffset, int dstLimit);
 
     static {
         System.loadLibrary("media_jni");
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index b8d1d12..88b1c5f 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -474,6 +474,9 @@
     /**
      * This event type indicates that the licensed usage duration for keys in a session
      * has expired.  The keys are no longer valid.
+     * @deprecated Use {@link OnKeyStatusChangeListener#onKeyStatusChange}
+     * and check for {@link MediaDrm.KeyStatus#STATUS_EXPIRED} in the {@link MediaDrm.KeyStatus}
+     * instead.
      */
     public static final int EVENT_KEY_EXPIRED = 3;
 
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 2ed6668..fe461be 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -25,10 +25,10 @@
 import android.media.MediaCodec;
 import android.media.MediaFormat;
 import android.media.MediaHTTPService;
-import android.media.MediaMetricsSet;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.PersistableBundle;
 
 import com.android.internal.util.Preconditions;
 
@@ -259,11 +259,71 @@
      * @param mediaCas the MediaCas object to use.
      */
     public final void setMediaCas(@NonNull MediaCas mediaCas) {
+        mMediaCas = mediaCas;
         nativeSetMediaCas(mediaCas.getBinder());
     }
 
     private native final void nativeSetMediaCas(@NonNull IBinder casBinder);
 
+    /**
+     * Describes the conditional access system used to scramble a track.
+     */
+    public static final class CasInfo {
+        private final int mSystemId;
+        private final MediaCas.Session mSession;
+
+        CasInfo(int systemId, @Nullable MediaCas.Session session) {
+            mSystemId = systemId;
+            mSession = session;
+        }
+
+        /**
+         * Retrieves the system id of the conditional access system.
+         *
+         * @return CA system id of the CAS used to scramble the track.
+         */
+        public int getSystemId() {
+            return mSystemId;
+        }
+
+        /**
+         * Retrieves the {@link MediaCas.Session} associated with a track. The
+         * session is needed to initialize a descrambler in order to decode the
+         * scrambled track.
+         * <p>
+         * @see MediaDescrambler#setMediaCasSession
+         * <p>
+         * @return a {@link MediaCas.Session} object associated with a track.
+         */
+        public MediaCas.Session getSession() {
+            return mSession;
+        }
+    }
+
+    /**
+     * Retrieves the information about the conditional access system used to scramble
+     * a track.
+     *
+     * @param index of the track.
+     * @return an {@link CasInfo} object describing the conditional access system.
+     */
+    public CasInfo getCasInfo(int index) {
+        Map<String, Object> formatMap = getTrackFormatNative(index);
+        if (formatMap.containsKey(MediaFormat.KEY_CA_SYSTEM_ID)) {
+            int systemId = ((Integer)formatMap.get(MediaFormat.KEY_CA_SYSTEM_ID)).intValue();
+            MediaCas.Session session = null;
+            if (mMediaCas != null && formatMap.containsKey(MediaFormat.KEY_CA_SESSION_ID)) {
+                ByteBuffer buf = (ByteBuffer) formatMap.get(MediaFormat.KEY_CA_SESSION_ID);
+                buf.rewind();
+                final byte[] sessionId = new byte[buf.remaining()];
+                buf.get(sessionId);
+                session = mMediaCas.createFromSessionId(sessionId);
+            }
+            return new CasInfo(systemId, session);
+        }
+        return null;
+    }
+
     @Override
     protected void finalize() {
         native_finalize();
@@ -307,31 +367,6 @@
                     return initDataMap.get(schemeUuid);
                 }
             };
-        } else if (formatMap.containsKey("mime")
-                && "video/mp2ts".equals(formatMap.get("mime"))) {
-            final Map<UUID, DrmInitData.SchemeInitData> initDataMap =
-                    new HashMap<UUID, DrmInitData.SchemeInitData>();
-
-            int numTracks = getTrackCount();
-            for (int i = 0; i < numTracks; ++i) {
-                Map<String, Object> trackFormatMap = getTrackFormatNative(i);
-                if (!trackFormatMap.containsKey("cas")) {
-                    continue;
-                }
-                ByteBuffer buf = (ByteBuffer) trackFormatMap.get("cas");
-                buf.rewind();
-                final byte[] data = new byte[buf.remaining()];
-                buf.get(data);
-                initDataMap.put(new UUID(0, i), new DrmInitData.SchemeInitData("cas", data));
-            }
-            if (initDataMap.isEmpty()) {
-                return null;
-            }
-            return new DrmInitData() {
-                public SchemeInitData get(UUID schemeUuid) {
-                    return initDataMap.get(schemeUuid);
-                }
-            };
         } else {
             int numTracks = getTrackCount();
             for (int i = 0; i < numTracks; ++i) {
@@ -349,8 +384,8 @@
                     }
                 };
             }
-            return null;
         }
+        return null;
     }
 
     /**
@@ -654,22 +689,21 @@
     /**
      *  Return Metrics data about the current media container.
      *
-     * @return a MediaMetricsSet containing the set of attributes and values
+     * @return a {@link PersistableBundle} containing the set of attributes and values
      * available for the media container being handled by this instance
      * of MediaExtractor.
-     * The attributes are descibed in {@link MediaMetricsSet.MediaExtractor}.
+     * The attributes are descibed in {@link MetricsConstants}.
      *
      *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
 
-    public MediaMetricsSet getMetrics() {
-        Bundle bundle = native_getMetrics();
-	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
-	return mSet;
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
     }
 
-    private native Bundle native_getMetrics();
+    private native PersistableBundle native_getMetrics();
 
     private static native final void native_init();
     private native final void native_setup();
@@ -680,5 +714,35 @@
         native_init();
     }
 
+    private MediaCas mMediaCas;
+
     private long mNativeContext;
+
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the container format
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String FORMAT = "android.media.mediaextractor.fmt";
+
+        /**
+         * Key to extract the container MIME type
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String MIME_TYPE = "android.media.mediaextractor.mime";
+
+        /**
+         * Key to extract the number of tracks in the container
+         * from the {@link MediaExtractor#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String TRACKS = "android.media.mediaextractor.ntrk";
+
+    }
+
 }
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index e77c00b..ed5f7d8 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -767,6 +767,29 @@
      */
     public static final String KEY_TRACK_ID = "track-id";
 
+    /**
+     * A key describing the system id of the conditional access system used to scramble
+     * a media track.
+     * <p>
+     * This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
+     * access system.
+     * <p>
+     * The associated value is an integer.
+     * @hide
+     */
+    public static final String KEY_CA_SYSTEM_ID = "ca-system-id";
+
+    /**
+     * A key describing the {@link MediaCas.Session} object associated with a media track.
+     * <p>
+     * This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
+     * access system.
+     * <p>
+     * The associated value is a ByteBuffer.
+     * @hide
+     */
+    public static final String KEY_CA_SESSION_ID = "ca-session-id";
+
     /* package private */ MediaFormat(Map<String, Object> map) {
         mMap = map;
     }
diff --git a/media/java/android/media/MediaMetricsSet.java b/media/java/android/media/MediaMetricsSet.java
deleted file mode 100644
index 5ecbee2..0000000
--- a/media/java/android/media/MediaMetricsSet.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Bundle;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.Runnable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-import java.net.HttpCookie;
-import java.net.HttpURLConnection;
-import java.net.InetSocketAddress;
-import java.net.URL;
-import java.nio.ByteOrder;
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-import java.util.UUID;
-import java.util.Vector;
-
-
-/**
- * MediaMetricsSet contains the results returned by the getMetrics()
- * methods defined in other Media classes such as
- * {@link MediaCodec}, {@link MediaExtractor}, {@link MediaPlayer},
- * and {@link MediaRecorder}.
- *
- * MediaMetricsSet behaves similarly to a {@link Bundle}. It contains
- * a set of keys and values.
- * Methods such as {@link #getInt} and {@link #getString} are provided
- * to extract values of the corresponding types.
- * The {@link #keySet} method can be used to discover all of the keys
- * that are present in the particular instance.
- *
- */
-public final class MediaMetricsSet
-{
-
-    /**
-     * This MediaCodec class holds the constants defining keys related to
-     * the metrics for a MediaCodec.
-     */
-    public final static class MediaCodec
-    {
-        private MediaCodec() {}
-
-        /**
-         * Key to extract the codec being used
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_CODEC = "android.media.mediacodec.codec";
-
-        /**
-         * Key to extract the MIME type
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_MIME = "android.media.mediacodec.mime";
-
-        /**
-         * Key to extract what the codec mode
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is a String. Values will be one of the constants
-	 * MODE_AUDIO or MODE_VIDEO.
-         */
-        public static final String KEY_MODE = "android.media.mediacodec.mode";
-
-	/**
-	 * The value returned for the key {@link #KEY_MODE} when the
-	 * codec is a audio codec.
-	 */
-        public static final String MODE_AUDIO = "audio";
-
-	/**
-	 * The value returned for the key {@link #KEY_MODE} when the
-	 * codec is a video codec.
-	 */
-        public static final String MODE_VIDEO = "video";
-
-        /**
-         * Key to extract the flag indicating whether the codec is running
-         * as an encoder or decoder from the {@link MediaCodec#getMetrics} return value.
-         * The value is an integer.
-         * A 0 indicates decoder; 1 indicates encoder.
-         */
-        public static final String KEY_ENCODER = "android.media.mediacodec.encoder";
-
-        /**
-         * Key to extract the flag indicating whether the codec is running
-         * in secure (DRM) mode from the {@link MediaCodec#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_SECURE = "android.media.mediacodec.secure";
-
-        /**
-         * Key to extract the width (in pixels) of the video track
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_WIDTH = "android.media.mediacodec.width";
-
-        /**
-         * Key to extract the height (in pixels) of the video track
-         * from the {@link MediaCodec#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_HEIGHT = "android.media.mediacodec.height";
-
-        /**
-         * Key to extract the rotation (in degrees) to properly orient the video
-         * from the {@link MediaCodec#getMetrics} return.
-         * The value is a integer.
-         */
-        public static final String KEY_ROTATION = "android.media.mediacodec.rotation";
-
-    }
-
-    /**
-     * This class holds the constants defining keys related to
-     * the metrics for a MediaExtractor.
-     */
-    public final static class MediaExtractor
-    {
-        private MediaExtractor() {}
-
-        /**
-         * Key to extract the container format
-         * from the {@link MediaExtractor#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_FORMAT = "android.media.mediaextractor.fmt";
-
-        /**
-         * Key to extract the container MIME type
-         * from the {@link MediaExtractor#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_MIME = "android.media.mediaextractor.mime";
-
-        /**
-         * Key to extract the number of tracks in the container
-         * from the {@link MediaExtractor#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_TRACKS = "android.media.mediaextractor.ntrk";
-
-    }
-
-    /**
-     * This class holds the constants defining keys related to
-     * the metrics for a MediaPlayer.
-     */
-    public final static class MediaPlayer
-    {
-        private MediaPlayer() {}
-
-        /**
-         * Key to extract the MIME type of the video track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_MIME_VIDEO = "android.media.mediaplayer.video.mime";
-
-        /**
-         * Key to extract the codec being used to decode the video track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_CODEC_VIDEO = "android.media.mediaplayer.video.codec";
-
-        /**
-         * Key to extract the width (in pixels) of the video track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_WIDTH = "android.media.mediaplayer.width";
-
-        /**
-         * Key to extract the height (in pixels) of the video track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_HEIGHT = "android.media.mediaplayer.height";
-
-        /**
-         * Key to extract the count of video frames played
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_FRAMES = "android.media.mediaplayer.frames";
-
-        /**
-         * Key to extract the count of video frames dropped
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_FRAMES_DROPPED = "android.media.mediaplayer.dropped";
-
-        /**
-         * Key to extract the MIME type of the audio track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_MIME_AUDIO = "android.media.mediaplayer.audio.mime";
-
-        /**
-         * Key to extract the codec being used to decode the audio track
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a String.
-         */
-        public static final String KEY_CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
-
-        /**
-         * Key to extract the duration (in milliseconds) of the
-         * media being played
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a long.
-         */
-        public static final String KEY_DURATION = "android.media.mediaplayer.durationMs";
-
-        /**
-         * Key to extract the playing time (in milliseconds) of the
-         * media being played
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is a long.
-         */
-        public static final String KEY_PLAYING = "android.media.mediaplayer.playingMs";
-
-        /**
-         * Key to extract the count of errors encountered while
-         * playing the media
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_ERRORS = "android.media.mediaplayer.err";
-
-        /**
-         * Key to extract an (optional) error code detected while
-         * playing the media
-         * from the {@link MediaPlayer#getMetrics} return value.
-         * The value is an integer.
-         */
-        public static final String KEY_ERROR_CODE = "android.media.mediaplayer.errcode";
-
-    }
-
-    /**
-     * This class holds the constants defining keys related to
-     * the metrics for a MediaRecorder.
-     */
-    public final static class MediaRecorder
-    {
-        private MediaRecorder() {}
-
-        /**
-         * Key to extract the audio bitrate
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
-
-        /**
-         * Key to extract the number of audio channels
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
-
-        /**
-         * Key to extract the audio samplerate
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
-
-        /**
-         * Key to extract the audio timescale
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
-
-        /**
-         * Key to extract the video capture frame rate
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is a double.
-         */
-        public static final String KEY_CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
-
-        /**
-         * Key to extract the video capture framerate enable value
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
-
-        /**
-         * Key to extract the intended playback frame rate
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_FRAMERATE = "android.media.mediarecorder.frame-rate";
-
-        /**
-         * Key to extract the height (in pixels) of the captured video
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_HEIGHT = "android.media.mediarecorder.height";
-
-        /**
-         * Key to extract the recorded movies time units
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         * A value of 1000 indicates that the movie's timing is in milliseconds.
-         */
-        public static final String KEY_MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
-
-        /**
-         * Key to extract the rotation (in degrees) to properly orient the video
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_ROTATION = "android.media.mediarecorder.rotation";
-
-        /**
-         * Key to extract the video bitrate from being used
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
-
-        /**
-         * Key to extract the value for how often video iframes are generated
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
-
-        /**
-         * Key to extract the video encoding level
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
-
-        /**
-         * Key to extract the video encoding profile
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
-
-        /**
-         * Key to extract the recorded video time units
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         * A value of 1000 indicates that the video's timing is in milliseconds.
-         */
-        public static final String KEY_VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
-
-        /**
-         * Key to extract the width (in pixels) of the captured video
-         * from the {@link MediaRecorder#getMetrics} return.
-         * The value is an integer.
-         */
-        public static final String KEY_WIDTH = "android.media.mediarecorder.width";
-
-    }
-
-    /*
-     * Methods that we want
-     */
-
-    private Bundle mBundle;
-
-    MediaMetricsSet(Bundle bundle) {
-        mBundle = bundle;
-    }
-
-    /**
-     * Returns the number of mappings contained in this Bundle.
-     *
-     * @return the number of mappings as an int.
-     */
-    public int size() {
-        return mBundle.size();
-    }
-
-    /**
-     * Returns true if the mapping of this MediaMetricsSet is empty,
-     * false otherwise.
-     */
-    public boolean isEmpty() {
-        return mBundle.isEmpty();
-    }
-
-    /**
-     * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
-     *
-     * @param key a String
-     * @param defaultValue Value to return if key does not exist
-     * @return a double value
-     */
-    public double getDouble(String key, double defaultValue) {
-        return mBundle.getDouble(key, defaultValue);
-    }
-
-    /**
-     * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
-     *
-     * @param key a String
-     * @param defaultValue Value to return if key does not exist
-     * @return an int value
-     */
-    public int getInt(String key, int defaultValue) {
-        return mBundle.getInt(key, defaultValue);
-    }
-
-    /**
-     * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
-     *
-     * @param key a String
-     * @param defaultValue Value to return if key does not exist
-     * @return a long value
-     */
-    public long getLong(String key, long defaultValue) {
-        return mBundle.getLong(key, defaultValue);
-    }
-
-    /**
-     * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key or if a null
-     * value is explicitly associated with the given key.
-     *
-     * @param key a String
-     * @param defaultValue Value to return if key does not exist or if a null
-     *     value is associated with the given key.
-     * @return the String value associated with the given key, or defaultValue
-     *     if no valid String object is currently mapped to that key.
-     */
-    public String getString(String key, String defaultValue) {
-        return mBundle.getString(key, defaultValue);
-    }
-
-    /**
-     * Returns a Set containing the Strings used as keys in this Bundle.
-     *
-     * @return a Set of String keys
-     */
-    public Set<String> keySet() {
-        return mBundle.keySet();
-    }
-
-
-
-    public String toString() {
-        return mBundle.toString();
-    }
-
-}
-
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 71a968b..d5efc97 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -33,6 +33,7 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.PowerManager;
 import android.os.SystemProperties;
@@ -48,7 +49,6 @@
 import android.media.AudioManager;
 import android.media.MediaDrm;
 import android.media.MediaFormat;
-import android.media.MediaMetricsSet;
 import android.media.MediaTimeProvider;
 import android.media.PlaybackParams;
 import android.media.SubtitleController;
@@ -1007,13 +1007,14 @@
      * @param context the Context to use when resolving the Uri
      * @param uri the Content URI of the data you want to play
      * @param headers the headers to be sent together with the request for the data
-     *                Note that the cross domain redirection is allowed by default, but that can be
-     *                changed with key/value pairs through the headers parameter with
-     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
-     *                to disallow or allow cross domain redirection.
      *                The headers must not include cookies. Instead, use the cookies param.
      * @param cookies the cookies to be sent together with the request
      * @throws IllegalStateException if it is called in an invalid state
+     *
+     * <p><strong>Note</strong> that the cross domain redirection is allowed by default,
+     * but that can be changed with key/value pairs through the headers parameter with
+     * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to
+     * disallow or allow cross domain redirection.
      */
     public void setDataSource(@NonNull Context context, @NonNull Uri uri,
             @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies)
@@ -1056,11 +1057,12 @@
      * @param context the Context to use when resolving the Uri
      * @param uri the Content URI of the data you want to play
      * @param headers the headers to be sent together with the request for the data
-     *                Note that the cross domain redirection is allowed by default, but that can be
-     *                changed with key/value pairs through the headers parameter with
-     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
-     *                to disallow or allow cross domain redirection.
      * @throws IllegalStateException if it is called in an invalid state
+     *
+     * <p><strong>Note</strong> that the cross domain redirection is allowed by default,
+     * but that can be changed with key/value pairs through the headers parameter with
+     * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to
+     * disallow or allow cross domain redirection.
      */
     public void setDataSource(@NonNull Context context, @NonNull Uri uri,
             @Nullable Map<String, String> headers)
@@ -1491,20 +1493,19 @@
     /**
      * Return Metrics data about the current player.
      *
-     * @return a MediaMetricsSet containing the set of attributes and values
+     * @return a {@link PersistableBundle} containing the set of attributes and values
      * available for the media being handled by this instance of MediaPlayer
-     * The attributes are descibed in {@link MediaMetricsSet.MediaPlayer}.
+     * The attributes are descibed in {@link MetricsConstants}.
      *
      *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
-    public MediaMetricsSet getMetrics() {
-        Bundle bundle = native_getMetrics();
-	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
-	return mSet;
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
     }
 
-    private native Bundle native_getMetrics();
+    private native PersistableBundle native_getMetrics();
 
     /**
      * Checks whether the MediaPlayer is playing.
@@ -1982,7 +1983,7 @@
         mOnSubtitleDataListener = null;
 
         // Modular DRM clean up
-        mOnDrmConfigListener = null;
+        mOnDrmConfigHelper = null;
         mOnDrmInfoHandlerDelegate = null;
         mOnDrmPreparedHandlerDelegate = null;
         resetDrmState();
@@ -3906,11 +3907,11 @@
      * 'securityLevel', which has to be set after DRM scheme creation but
      * before the DRM session is opened.
      *
-     * The only allowed DRM calls in this listener are getDrmPropertyString
-     * and setDrmPropertyString.
+     * The only allowed DRM calls in this listener are {@code getDrmPropertyString}
+     * and {@code setDrmPropertyString}.
      *
      */
-    public interface OnDrmConfigListener
+    public interface OnDrmConfigHelper
     {
         /**
          * Called to give the app the opportunity to configure DRM before the session is created
@@ -3923,19 +3924,19 @@
     /**
      * Register a callback to be invoked for configuration of the DRM object before
      * the session is created.
-     * The callback will be invoked synchronously half-way into the execution
+     * The callback will be invoked synchronously during the execution
      * of {@link #prepareDrm(UUID uuid)}.
      *
      * @param listener the callback that will be run
      */
-    public void setOnDrmConfigListener(OnDrmConfigListener listener)
+    public void setOnDrmConfigHelper(OnDrmConfigHelper listener)
     {
         synchronized (mDrmLock) {
-            mOnDrmConfigListener = listener;
+            mOnDrmConfigHelper = listener;
         } // synchronized
     }
 
-    private OnDrmConfigListener mOnDrmConfigListener;
+    private OnDrmConfigHelper mOnDrmConfigHelper;
 
     /**
      * Interface definition of a callback to be invoked when the
@@ -3947,7 +3948,7 @@
          * Called to indicate DRM info is available
          *
          * @param mp the {@code MediaPlayer} associated with this callback
-         * @param drmInfo DRM info of the source including PSSH, mimes, and subset
+         * @param drmInfo DRM info of the source including PSSH, and subset
          *                of crypto schemes supported by this device
          */
         public void onDrmInfo(MediaPlayer mp, DrmInfo drmInfo);
@@ -3983,6 +3984,41 @@
 
     private OnDrmInfoHandlerDelegate mOnDrmInfoHandlerDelegate;
 
+
+    /**
+     * The status codes for {@link OnDrmPreparedListener#onDrmPrepared} listener.
+     * <p>
+     *
+     * DRM preparation has succeeded.
+     */
+    public static final int PREPARE_DRM_STATUS_SUCCESS = 0;
+
+    /**
+     * The device required DRM provisioning but couldn't reach the provisioning server.
+     */
+    public static final int PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR = 1;
+
+    /**
+     * The device required DRM provisioning but the provisioning server denied the request.
+     */
+    public static final int PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR = 2;
+
+    /**
+     * The DRM preparation has failed .
+     */
+    public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3;
+
+
+    /** @hide */
+    @IntDef({
+        PREPARE_DRM_STATUS_SUCCESS,
+        PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR,
+        PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR,
+        PREPARE_DRM_STATUS_PREPARATION_ERROR,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PrepareDrmStatusCode {}
+
     /**
      * Interface definition of a callback to notify the app when the
      * DRM is ready for key request/response
@@ -3993,9 +4029,13 @@
          * Called to notify the app that prepareDrm is finished and ready for key request/response
          *
          * @param mp the {@code MediaPlayer} associated with this callback
-         * @param success the result of DRM preparation
+         * @param status the result of DRM preparation which can be
+         * {@link #PREPARE_DRM_STATUS_SUCCESS},
+         * {@link #PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR},
+         * {@link #PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR}, or
+         * {@link #PREPARE_DRM_STATUS_PREPARATION_ERROR}.
          */
-        public void onDrmPrepared(MediaPlayer mp, boolean success);
+        public void onDrmPrepared(MediaPlayer mp, @PrepareDrmStatusCode int status);
     }
 
     /**
@@ -4039,30 +4079,28 @@
             mOnDrmInfoListener = listener;
 
             // find the looper for our new event handler
-            Looper looper = null;
             if (handler != null) {
-                looper = handler.getLooper();
-            }
-
-            // construct the event handler with this looper
-            if (looper != null) {
-                // implement the event handler delegate
-                mHandler = new Handler(looper) {
-                    public void handleMessage(Message msg) {
-                        DrmInfo drmInfo = (DrmInfo)msg.obj;
-                        mOnDrmInfoListener.onDrmInfo(mMediaPlayer, drmInfo);
-                    }
-                };
+                mHandler = handler;
+            } else {
+                // handler == null
+                // Will let OnDrmInfoListener be called in mEventHandler similar to other
+                // legacy notifications. This is because MEDIA_DRM_INFO's notification has to be
+                // sent before MEDIA_PREPARED's (i.e., in the same order they are issued by
+                // mediaserver). As a result, the callback has to be called directly by
+                // EventHandler.handleMessage similar to onPrepared.
             }
         }
 
         void notifyClient(DrmInfo drmInfo) {
-            if ( mHandler != null ) {
-                Message msg = new Message();  // no message type needed
-                msg.obj = drmInfo;
-                mHandler.sendMessage(msg);
+            if (mHandler != null) {
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                       mOnDrmInfoListener.onDrmInfo(mMediaPlayer, drmInfo);
+                    }
+                });
             }
-            else {  // no handler: direct call
+            else {  // no handler: direct call by mEventHandler
                 mOnDrmInfoListener.onDrmInfo(mMediaPlayer, drmInfo);
             }
         }
@@ -4079,31 +4117,26 @@
             mOnDrmPreparedListener = listener;
 
             // find the looper for our new event handler
-            Looper looper = null;
             if (handler != null) {
-                looper = handler.getLooper();
-            }
-
-            // construct the event handler with this looper
-            if (looper != null) {
-                // implement the event handler delegate
-                mHandler = new Handler(looper) {
-                    public void handleMessage(Message msg) {
-                        boolean success = (msg.arg1 == 0) ? false : true;
-                        mOnDrmPreparedListener.onDrmPrepared(mMediaPlayer, success);
-                    }
-                };
+                mHandler = handler;
+            } else if (mEventHandler != null) {
+                // Otherwise, use mEventHandler
+                mHandler = mEventHandler;
+            } else {
+                Log.e(TAG, "OnDrmPreparedHandlerDelegate: Unexpected null mEventHandler");
             }
         }
 
-        void notifyClient(boolean success) {
-            if ( mHandler != null ) {
-                Message msg = new Message();  // no message type needed
-                msg.arg1 = success ? 1 : 0;
-                mHandler.sendMessage(msg);
-            }
-            else {  // no handler: direct call
-                mOnDrmPreparedListener.onDrmPrepared(mMediaPlayer, success);
+        void notifyClient(int status) {
+            if (mHandler != null) {
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mOnDrmPreparedListener.onDrmPrepared(mMediaPlayer, status);
+                    }
+                });
+            } else {
+                Log.e(TAG, "OnDrmPreparedHandlerDelegate:notifyClient: Unexpected null mHandler");
             }
         }
     }
@@ -4138,7 +4171,7 @@
     /**
      * Prepares the DRM for the current source
      * <p>
-     * If {@code OnDrmConfigListener} is registered, it will be called half-way into
+     * If {@code OnDrmConfigHelper} is registered, it will be called during
      * preparation to allow configuration of the DRM properties before opening the
      * DRM session. Note that the callback is called synchronously in the thread that called
      * {@code prepareDrm}. It should be used only for a series of {@code getDrmPropertyString}
@@ -4149,9 +4182,9 @@
      * complete depending on the network connectivity.
      * If {@code OnDrmPreparedListener} is registered, prepareDrm() runs in non-blocking
      * mode by launching the provisioning in the background and returning. The listener
-     * will be called when provisioning and preperation has finished. If a
+     * will be called when provisioning and preparation has finished. If a
      * {@code OnDrmPreparedListener} is not registered, prepareDrm() waits till provisioning
-     * and preperation has finished, i.e., runs in blocking mode.
+     * and preparation has finished, i.e., runs in blocking mode.
      * <p>
      * If {@code OnDrmPreparedListener} is registered, it is called to indicate the DRM
      * session being ready. The application should not make any assumption about its call
@@ -4159,18 +4192,23 @@
      * execute the listener (unless the listener is registered with a handler thread).
      * <p>
      *
-     * @param uuid The UUID of the crypto scheme.
+     * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved
+     * from the source through {@code getDrmInfo} or registering a {@code onDrmInfoListener}.
      *
-     * @throws IllegalStateException       if called before prepare(), or there exists a Drm already
-     * @throws UnsupportedSchemeException  if the crypto scheme is not supported
-     * @throws ResourceBusyException       if required DRM resources are in use
-     * @throws ProvisioningErrorException  if provisioning is required but an attempt failed
+     * @throws IllegalStateException              if called before prepare(), or the DRM was
+     *                                            prepared already
+     * @throws UnsupportedSchemeException         if the crypto scheme is not supported
+     * @throws ResourceBusyException              if required DRM resources are in use
+     * @throws ProvisioningNetworkErrorException  if provisioning is required but failed due to a
+     *                                            network error
+     * @throws ProvisioningServerErrorException   if provisioning is required but failed due to
+     *                                            the request denied by the provisioning server
      */
     public void prepareDrm(@NonNull UUID uuid)
-            throws UnsupportedSchemeException,
-                   ResourceBusyException, ProvisioningErrorException
+            throws UnsupportedSchemeException, ResourceBusyException,
+                   ProvisioningNetworkErrorException, ProvisioningServerErrorException
     {
-        Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigListener: " + mOnDrmConfigListener);
+        Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + mOnDrmConfigHelper);
 
         boolean allDoneWithoutProvisioning = false;
         // get a snapshot as we'll use them outside the lock
@@ -4178,7 +4216,7 @@
 
         synchronized (mDrmLock) {
 
-            // only allowing if tied to a protected source; might releax for releasing offline keys
+            // only allowing if tied to a protected source; might relax for releasing offline keys
             if (mDrmInfo == null) {
                 final String msg = "prepareDrm(): Wrong usage: The player must be prepared and " +
                         "DRM info be retrieved before this call.";
@@ -4227,8 +4265,8 @@
 
 
         // call the callback outside the lock
-        if (mOnDrmConfigListener != null)  {
-            mOnDrmConfigListener.onDrmConfig(this);
+        if (mOnDrmConfigHelper != null)  {
+            mOnDrmConfigHelper.onDrmConfig(this);
         }
 
         synchronized (mDrmLock) {
@@ -4252,15 +4290,33 @@
                 Log.w(TAG, "prepareDrm: NotProvisionedException");
 
                 // handle provisioning internally; it'll reset mPrepareDrmInProgress
-                boolean result = HandleProvisioninig(uuid);
+                int result = HandleProvisioninig(uuid);
 
                 // if blocking mode, we're already done;
                 // if non-blocking mode, we attempted to launch background provisioning
-                if (result == false) {
-                    final String msg = "prepareDrm: Provisioning was required but failed.";
-                    Log.e(TAG, msg);
+                if (result != PREPARE_DRM_STATUS_SUCCESS) {
                     earlyExit = true;
-                    throw new ProvisioningErrorException(msg);
+                    String msg;
+
+                    switch (result) {
+                    case PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR:
+                        msg = "prepareDrm: Provisioning was required but failed " +
+                                "due to a network error.";
+                        Log.e(TAG, msg);
+                        throw new ProvisioningNetworkErrorException(msg);
+
+                    case PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR:
+                        msg = "prepareDrm: Provisioning was required but the request " +
+                                "was denied by the server.";
+                        Log.e(TAG, msg);
+                        throw new ProvisioningServerErrorException(msg);
+
+                    case PREPARE_DRM_STATUS_PREPARATION_ERROR:
+                    default: // default for safeguard
+                        msg = "prepareDrm: Post-provisioning preparation failed.";
+                        Log.e(TAG, msg);
+                        throw new IllegalStateException(msg);
+                    }
                 }
                 // nothing else to do;
                 // if blocking or non-blocking, HandleProvisioninig does the re-attempt & cleanup
@@ -4282,7 +4338,7 @@
         // if finished successfully without provisioning, call the callback outside the lock
         if (allDoneWithoutProvisioning) {
             if (onDrmPreparedHandlerDelegate != null)
-                onDrmPreparedHandlerDelegate.notifyClient(true /*success*/);
+                onDrmPreparedHandlerDelegate.notifyClient(PREPARE_DRM_STATUS_SUCCESS);
         }
 
     }
@@ -4292,6 +4348,10 @@
 
     /**
      * Releases the DRM session
+     * <p>
+     * The player has to have an active DRM session and be in stopped, or prepared
+     * state before this call is made.
+     * A {@code reset()} call will release the DRM session implicitly.
      *
      * @throws NoDrmSchemeException if there is no active DRM session to release
      */
@@ -4308,7 +4368,7 @@
 
             try {
                 // we don't have the player's state in this layer. The below call raises
-                // exception if we're in a non-stopped/idle state.
+                // exception if we're in a non-stopped/prepared state.
 
                 // for cleaning native/mediaserver crypto object
                 _releaseDrm();
@@ -4317,9 +4377,11 @@
                 cleanDrmObj();
 
                 mActiveDrmScheme = false;
-            } catch (Exception e) {
+            } catch (IllegalStateException e) {
                 Log.w(TAG, "releaseDrm: Exception ", e);
-                throw e;
+                throw new IllegalStateException("releaseDrm: The player is not in a valid state.");
+            } catch (Exception e) {
+                Log.e(TAG, "releaseDrm: Exception ", e);
             }
         }   // synchronized
     }
@@ -4338,21 +4400,23 @@
      * it should deliver to the response to the DRM engine plugin using the method
      * {@link #provideKeyResponse}.
      *
-     * @param scope may be a container-specific initialization data or a keySetId,
-     * depending on the specified keyType.
-     * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, scope should be set to
-     * the container-specific initialization data. Its meaning is interpreted based on the
-     * mime type provided in the mimeType parameter.  It could contain, for example,
-     * the content ID, key ID or other data obtained from the content metadata that is
-     * required in generating the key request.
-     * When the keyType is KEY_TYPE_RELEASE, scope should be set to the keySetId of
-     * the keys being released.
+     * @param keySetId is the key-set identifier of the offline keys being released when keyType is
+     * {@link MediaDrm#KEY_TYPE_RELEASE}. It should be set to null for other key requests, when
+     * keyType is {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}.
+     *
+     * @param initData is the container-specific initialization data when the keyType is
+     * {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}. Its meaning is
+     * interpreted based on the mime type provided in the mimeType parameter.  It could
+     * contain, for example, the content ID, key ID or other data obtained from the content
+     * metadata that is required in generating the key request.
+     * When the keyType is {@link MediaDrm#KEY_TYPE_RELEASE}, it should be set to null.
      *
      * @param mimeType identifies the mime type of the content
      *
-     * @param keyType specifes the type of the request. The request may be to acquire
-     * keys for streaming or offline content, or to release previously acquired
-     * keys, which are identified by a keySetId.
+     * @param keyType specifies the type of the request. The request may be to acquire
+     * keys for streaming, {@link MediaDrm#KEY_TYPE_STREAMING}, or for offline content
+     * {@link MediaDrm#KEY_TYPE_OFFLINE}, or to release previously acquired
+     * keys ({@link MediaDrm#KEY_TYPE_RELEASE}), which are identified by a keySetId.
      *
      * @param optionalParameters are included in the key request message to
      * allow a client application to provide additional message parameters to the server.
@@ -4361,12 +4425,13 @@
      * @throws NoDrmSchemeException if there is no active DRM session
      */
     @NonNull
-    public MediaDrm.KeyRequest getKeyRequest(@NonNull byte[] scope, @Nullable String mimeType,
-            @MediaDrm.KeyType int keyType, @Nullable Map<String, String> optionalParameters)
+    public MediaDrm.KeyRequest getKeyRequest(@Nullable byte[] keySetId, @Nullable byte[] initData,
+            @Nullable String mimeType, @MediaDrm.KeyType int keyType,
+            @Nullable Map<String, String> optionalParameters)
             throws NoDrmSchemeException
     {
         Log.v(TAG, "getKeyRequest: " +
-                " scope: " + scope + " mimeType: " + mimeType +
+                " keySetId: " + keySetId + " initData:" + initData + " mimeType: " + mimeType +
                 " keyType: " + keyType + " optionalParameters: " + optionalParameters);
 
         synchronized (mDrmLock) {
@@ -4376,20 +4441,16 @@
             }
 
             try {
-                byte[] scopeOut = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
-                                  mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
-                                  scope;          // keySetId for KEY_TYPE_RELEASE
-
-                byte[] initData = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
-                                  scope :         // initData for KEY_TYPE_STREAMING/OFFLINE
-                                  null;           // not used for KEY_TYPE_RELEASE
+                byte[] scope = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
+                        mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
+                        keySetId;       // keySetId for KEY_TYPE_RELEASE
 
                 HashMap<String, String> hmapOptionalParameters =
                                                 (optionalParameters != null) ?
                                                 new HashMap<String, String>(optionalParameters) :
                                                 null;
 
-                MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scopeOut, initData, mimeType,
+                MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scope, initData, mimeType,
                                                               keyType, hmapOptionalParameters);
                 Log.v(TAG, "getKeyRequest:   --> request: " + request);
 
@@ -4500,8 +4561,8 @@
      * @param propertyName the property name
      *
      * Standard fields names are:
-     * {link #PROPERTY_VENDOR}, {link #PROPERTY_VERSION},
-     * {link #PROPERTY_DESCRIPTION}, {link #PROPERTY_ALGORITHMS}
+     * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION},
+     * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS}
      */
     @NonNull
     public String getDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName)
@@ -4538,8 +4599,8 @@
      * @param value the property value
      *
      * Standard fields names are:
-     * {link #PROPERTY_VENDOR}, {link #PROPERTY_VERSION},
-     * {link #PROPERTY_DESCRIPTION}, {link #PROPERTY_ALGORITHMS}
+     * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION},
+     * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS}
      */
     public void setDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName,
                                      @NonNull String value)
@@ -4566,8 +4627,6 @@
     public static final class DrmInfo {
         private Map<UUID, byte[]> mapPssh;
         private UUID[] supportedSchemes;
-        // TODO: Won't need this in final release. Only keeping it for the existing test app.
-        private String[] mimes;
 
         public Map<UUID, byte[]> getPssh() {
             return mapPssh;
@@ -4575,15 +4634,10 @@
         public UUID[] getSupportedSchemes() {
             return supportedSchemes;
         }
-        // TODO: Won't need this in final release. Only keeping it for the existing test app.
-        public String[] getMimes() {
-            return mimes;
-        }
 
-        private DrmInfo(Map<UUID, byte[]> Pssh, UUID[] SupportedSchemes, String[] Mimes) {
+        private DrmInfo(Map<UUID, byte[]> Pssh, UUID[] SupportedSchemes) {
             mapPssh = Pssh;
             supportedSchemes = SupportedSchemes;
-            mimes = Mimes;
         }
 
         private DrmInfo(Parcel parcel) {
@@ -4609,18 +4663,12 @@
                       supportedSchemes[i]);
             }
 
-            // TODO: Won't need this in final release. Only keeping it for the test app.
-            mimes = parcel.readStringArray();
-            int mimeCount = mimes.length;
-            Log.v(TAG, "DrmInfo() mime: " + Arrays.toString(mimes));
-
             Log.v(TAG, "DrmInfo() Parcel psshsize: " + psshsize +
-                  " supportedDRMsCount: " + supportedDRMsCount +
-                  " mimeCount: " + mimeCount);
+                  " supportedDRMsCount: " + supportedDRMsCount);
         }
 
         private DrmInfo makeCopy() {
-            return new DrmInfo(this.mapPssh, this.supportedSchemes, this.mimes);
+            return new DrmInfo(this.mapPssh, this.supportedSchemes);
         }
 
         private String arrToHex(byte[] bytes) {
@@ -4715,11 +4763,22 @@
 
     /**
      * Thrown when the device requires DRM provisioning but the provisioning attempt has
-     * failed (for example: network timeout, provisioning server error).
+     * failed due to a network error (Internet reachability, timeout, etc.).
      * Extends MediaDrm.MediaDrmException
      */
-    public static final class ProvisioningErrorException extends MediaDrmException {
-        public ProvisioningErrorException(String detailMessage) {
+    public static final class ProvisioningNetworkErrorException extends MediaDrmException {
+        public ProvisioningNetworkErrorException(String detailMessage) {
+            super(detailMessage);
+        }
+    }
+
+    /**
+     * Thrown when the device requires DRM provisioning but the provisioning attempt has
+     * failed due to the provisioning server denying the request.
+     * Extends MediaDrm.MediaDrmException
+     */
+    public static final class ProvisioningServerErrorException extends MediaDrmException {
+        public ProvisioningServerErrorException(String detailMessage) {
             super(detailMessage);
         }
     }
@@ -4771,14 +4830,13 @@
 
         private UUID uuid;
         private String urlStr;
-        private byte[] response;
         private Object drmLock;
         private OnDrmPreparedHandlerDelegate onDrmPreparedHandlerDelegate;
         private MediaPlayer mediaPlayer;
-        private boolean succeeded;
+        private int status;
         private boolean finished;
-        public  boolean succeeded() {
-            return succeeded;
+        public  int status() {
+            return status;
         }
 
         public ProvisioningThread initialize(MediaDrm.ProvisionRequest request,
@@ -4791,12 +4849,15 @@
             urlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
             this.uuid = uuid;
 
+            status = PREPARE_DRM_STATUS_PREPARATION_ERROR;
+
             Log.v(TAG, "HandleProvisioninig: Thread is initialised url: " + urlStr);
             return this;
         }
 
         public void run() {
 
+            byte[] response = null;
             boolean provisioningSucceeded = false;
             try {
                 URL url = new URL(urlStr);
@@ -4814,11 +4875,13 @@
                     Log.v(TAG, "HandleProvisioninig: Thread run: response " +
                             response.length + " " + response);
                 } catch (Exception e) {
+                    status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
                     Log.w(TAG, "HandleProvisioninig: Thread run: connect " + e + " url: " + url);
                 } finally {
                     connection.disconnect();
                 }
             } catch (Exception e)   {
+                status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
                 Log.w(TAG, "HandleProvisioninig: Thread run: openConnection " + e);
             }
 
@@ -4829,12 +4892,15 @@
                             "provideProvisionResponse SUCCEEDED!");
 
                     provisioningSucceeded = true;
-                } catch (Exception e)   {
+                } catch (Exception e) {
+                    status = PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR;
                     Log.w(TAG, "HandleProvisioninig: Thread run: " +
                             "provideProvisionResponse " + e);
                 }
             }
 
+            boolean succeeded = false;
+
             // non-blocking mode needs the lock
             if (onDrmPreparedHandlerDelegate != null) {
 
@@ -4842,6 +4908,9 @@
                     // continuing with prepareDrm
                     if (provisioningSucceeded) {
                         succeeded = mediaPlayer.resumePrepareDrm(uuid);
+                        status = (succeeded) ?
+                                PREPARE_DRM_STATUS_SUCCESS :
+                                PREPARE_DRM_STATUS_PREPARATION_ERROR;
                     }
                     mediaPlayer.mDrmProvisioningInProgress = false;
                     mediaPlayer.mPrepareDrmInProgress = false;
@@ -4851,12 +4920,15 @@
                 } // synchronized
 
                 // calling the callback outside the lock
-                onDrmPreparedHandlerDelegate.notifyClient(succeeded);
+                onDrmPreparedHandlerDelegate.notifyClient(status);
             } else {   // blocking mode already has the lock
 
                 // continuing with prepareDrm
                 if (provisioningSucceeded) {
                     succeeded = mediaPlayer.resumePrepareDrm(uuid);
+                    status = (succeeded) ?
+                            PREPARE_DRM_STATUS_SUCCESS :
+                            PREPARE_DRM_STATUS_PREPARATION_ERROR;
                 }
                 mediaPlayer.mDrmProvisioningInProgress = false;
                 mediaPlayer.mPrepareDrmInProgress = false;
@@ -4870,19 +4942,19 @@
 
     }   // ProvisioningThread
 
-    private boolean HandleProvisioninig(UUID uuid)
+    private int HandleProvisioninig(UUID uuid)
     {
         // the lock is already held by the caller
 
         if (mDrmProvisioningInProgress) {
             Log.e(TAG, "HandleProvisioninig: Unexpected mDrmProvisioningInProgress");
-            return false;
+            return PREPARE_DRM_STATUS_PREPARATION_ERROR;
         }
 
         MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
         if (provReq == null) {
             Log.e(TAG, "HandleProvisioninig: getProvisionRequest returned null.");
-            return false;
+            return PREPARE_DRM_STATUS_PREPARATION_ERROR;
         }
 
         Log.v(TAG, "HandleProvisioninig provReq " +
@@ -4894,11 +4966,11 @@
         mDrmProvisioningThread = new ProvisioningThread().initialize(provReq, uuid, this);
         mDrmProvisioningThread.start();
 
-        boolean result = false;
+        int result;
 
-        // non-blocking
+        // non-blocking: this is not the final result
         if (mOnDrmPreparedHandlerDelegate != null) {
-            result = true;
+            result = PREPARE_DRM_STATUS_SUCCESS;
         } else {
             // if blocking mode, wait till provisioning is done
             try {
@@ -4906,7 +4978,7 @@
             } catch (Exception e) {
                 Log.w(TAG, "HandleProvisioninig: Thread.join Exception " + e);
             }
-            result = mDrmProvisioningThread.succeeded();
+            result = mDrmProvisioningThread.status();
             // no longer need the thread
             mDrmProvisioningThread = null;
         }
@@ -5418,4 +5490,98 @@
             }
         }
     }
+
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the MIME type of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String MIME_TYPE_VIDEO = "android.media.mediaplayer.video.mime";
+
+        /**
+         * Key to extract the codec being used to decode the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String CODEC_VIDEO = "android.media.mediaplayer.video.codec";
+
+        /**
+         * Key to extract the width (in pixels) of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String WIDTH = "android.media.mediaplayer.width";
+
+        /**
+         * Key to extract the height (in pixels) of the video track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String HEIGHT = "android.media.mediaplayer.height";
+
+        /**
+         * Key to extract the count of video frames played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String FRAMES = "android.media.mediaplayer.frames";
+
+        /**
+         * Key to extract the count of video frames dropped
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String FRAMES_DROPPED = "android.media.mediaplayer.dropped";
+
+        /**
+         * Key to extract the MIME type of the audio track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String MIME_TYPE_AUDIO = "android.media.mediaplayer.audio.mime";
+
+        /**
+         * Key to extract the codec being used to decode the audio track
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a String.
+         */
+        public static final String CODEC_AUDIO = "android.media.mediaplayer.audio.codec";
+
+        /**
+         * Key to extract the duration (in milliseconds) of the
+         * media being played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a long.
+         */
+        public static final String DURATION = "android.media.mediaplayer.durationMs";
+
+        /**
+         * Key to extract the playing time (in milliseconds) of the
+         * media being played
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is a long.
+         */
+        public static final String PLAYING = "android.media.mediaplayer.playingMs";
+
+        /**
+         * Key to extract the count of errors encountered while
+         * playing the media
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String ERRORS = "android.media.mediaplayer.err";
+
+        /**
+         * Key to extract an (optional) error code detected while
+         * playing the media
+         * from the {@link MediaPlayer#getMetrics} return value.
+         * The value is an integer.
+         */
+        public static final String ERROR_CODE = "android.media.mediaplayer.errcode";
+
+    }
 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 4675e32..997d562 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -20,14 +20,15 @@
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.hardware.Camera;
-import android.media.MediaMetricsSet;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.util.Log;
 import android.view.Surface;
 
+import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.RandomAccessFile;
@@ -92,6 +93,7 @@
 
     private String mPath;
     private FileDescriptor mFd;
+    private File mFile;
     private EventHandler mEventHandler;
     private OnErrorListener mOnErrorListener;
     private OnInfoListener mOnInfoListener;
@@ -804,10 +806,26 @@
     public void setOutputFile(FileDescriptor fd) throws IllegalStateException
     {
         mPath = null;
+        mFile = null;
         mFd = fd;
     }
 
     /**
+     * Pass in the file object to be written. Call this after setOutputFormat() but before prepare().
+     * File should be seekable. After setting the next output file, application should not use the
+     * file until {@link #stop}. Application is responsible for cleaning up unused files after
+     * {@link #stop} is called.
+     *
+     * @param file the file object to be written into.
+     */
+    public void setOutputFile(File file)
+    {
+        mPath = null;
+        mFd = null;
+        mFile = file;
+    }
+
+    /**
      * Sets the next output file descriptor to be used when the maximum filesize is reached
      * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File descriptor
      * must be seekable and writable. After setting the next output file, application should not
@@ -842,15 +860,16 @@
     public void setOutputFile(String path) throws IllegalStateException
     {
         mFd = null;
+        mFile = null;
         mPath = path;
     }
 
     /**
-     * Sets the next output file path to be used when the maximum filesize is reached
-     * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File should
-     * be seekable. After setting the next output file, application should not use the file
-     * referenced by this file descriptor until {@link #stop}. Application must call this
-     * after receiving on the {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
+     * Sets the next output file to be used when the maximum filesize is reached on the prior
+     * output {@link #setOutputFile} or {@link #setNextOutputFile}). File should be seekable.
+     * After setting the next output file, application should not use the file until {@link #stop}.
+     * Application must call this after receiving on the
+     * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
      * that output. Application will receive {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
@@ -858,19 +877,17 @@
      * the previous one has not been used. Application is responsible for cleaning up unused files
      * after {@link #stop} is called.
      *
-     * @param  path The pathname to use.
+     * @param  file The file to use.
      * @throws IllegalStateException if it is called before prepare().
      * @throws IOException if setNextOutputFile fails otherwise.
      */
-    public void setNextOutputFile(String path) throws IllegalStateException, IOException
+    public void setNextOutputFile(File file) throws IllegalStateException, IOException
     {
-        if (path != null) {
-            RandomAccessFile file = new RandomAccessFile(path, "rws");
-            try {
-                _setNextOutputFile(file.getFD());
-            } finally {
-                file.close();
-            }
+        RandomAccessFile f = new RandomAccessFile(file, "rws");
+        try {
+            _setNextOutputFile(f.getFD());
+        } finally {
+            f.close();
         }
     }
 
@@ -899,6 +916,13 @@
             }
         } else if (mFd != null) {
             _setOutputFile(mFd);
+        } else if (mFile != null) {
+            RandomAccessFile file = new RandomAccessFile(mFile, "rws");
+            try {
+                _setOutputFile(file.getFD());
+            } finally {
+                file.close();
+            }
         } else {
             throw new IOException("No valid output file");
         }
@@ -1267,23 +1291,142 @@
     /**
      *  Return Metrics data about the current Mediarecorder instance.
      *
-     * @return a MediaMetricsSet containing the set of attributes and values
+     * @return a {@link PersistableBundle} containing the set of attributes and values
      * available for the media being generated by this instance of
      * MediaRecorder.
-     * The attributes are descibed in {@link MediaMetricsSet.MediaRecorder}.
+     * The attributes are descibed in {@link MetricsConstants}.
      *
      *  Additional vendor-specific fields may also be present in
      *  the return value.
      */
-    public MediaMetricsSet getMetrics() {
-        Bundle bundle = native_getMetrics();
-	MediaMetricsSet mSet = new MediaMetricsSet(bundle);
-	return mSet;
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
     }
 
-    private native Bundle native_getMetrics();
+    private native PersistableBundle native_getMetrics();
 
     @Override
     protected void finalize() { native_finalize(); }
+
+    public final static class MetricsConstants
+    {
+        private MetricsConstants() {}
+
+        /**
+         * Key to extract the audio bitrate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
+
+        /**
+         * Key to extract the number of audio channels
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
+
+        /**
+         * Key to extract the audio samplerate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
+
+        /**
+         * Key to extract the audio timescale
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
+
+        /**
+         * Key to extract the video capture frame rate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is a double.
+         */
+        public static final String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
+
+        /**
+         * Key to extract the video capture framerate enable value
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
+
+        /**
+         * Key to extract the intended playback frame rate
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String FRAMERATE = "android.media.mediarecorder.frame-rate";
+
+        /**
+         * Key to extract the height (in pixels) of the captured video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String HEIGHT = "android.media.mediarecorder.height";
+
+        /**
+         * Key to extract the recorded movies time units
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         * A value of 1000 indicates that the movie's timing is in milliseconds.
+         */
+        public static final String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
+
+        /**
+         * Key to extract the rotation (in degrees) to properly orient the video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String ROTATION = "android.media.mediarecorder.rotation";
+
+        /**
+         * Key to extract the video bitrate from being used
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
+
+        /**
+         * Key to extract the value for how often video iframes are generated
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
+
+        /**
+         * Key to extract the video encoding level
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
+
+        /**
+         * Key to extract the video encoding profile
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
+
+        /**
+         * Key to extract the recorded video time units
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         * A value of 1000 indicates that the video's timing is in milliseconds.
+         */
+        public static final String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
+
+        /**
+         * Key to extract the width (in pixels) of the captured video
+         * from the {@link MediaRecorder#getMetrics} return.
+         * The value is an integer.
+         */
+        public static final String WIDTH = "android.media.mediarecorder.width";
+
+    }
 }
 
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 5bf205e..789d5e0 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -365,7 +365,7 @@
      * @param parentId The id of the parent media item whose list of children
      *            will be subscribed.
      * @param options The bundle of service-specific arguments to send to the media
-     *            browse service. The contents of this bundle may affect the
+     *            browser service. The contents of this bundle may affect the
      *            information returned when browsing.
      * @param callback The callback to receive the list of children.
      */
@@ -453,7 +453,7 @@
         try {
             mServiceBinder.getMediaItem(mediaId, receiver, mServiceCallbacks);
         } catch (RemoteException e) {
-            Log.i(TAG, "Remote error getting media item.", e);
+            Log.i(TAG, "Remote error getting media item.");
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -463,62 +463,6 @@
         }
     }
 
-    /**
-     * Searches {@link MediaItem media items} from the connected service. Not
-     * all services may support this, and {@link SearchCallback#onError} will be
-     * called if not implemented.
-     *
-     * @param query The search query that contains keywords separated by space. Should not be
-     *            an empty string.
-     * @param extras The bundle of service-specific arguments to send to the media browser
-     *            service. The contents of this bundle may affect the search result.
-     * @param callback The callback to receive the search result.
-     * @throws IllegalStateException if the browser is not connected to the media browser service.
-     */
-    public void search(@NonNull final String query, final Bundle extras, SearchCallback callback) {
-        if (TextUtils.isEmpty(query)) {
-            throw new IllegalArgumentException("query cannot be empty.");
-        }
-        if (callback == null) {
-            throw new IllegalArgumentException("callback cannot be null.");
-        }
-        if (mState != CONNECT_STATE_CONNECTED) {
-            throw new IllegalStateException("search() called while not connected (state="
-                    + getStateLabel(mState) + ")");
-        }
-        ResultReceiver receiver = new ResultReceiver(mHandler) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                if (resultCode != 0 || resultData == null
-                        || !resultData.containsKey(MediaBrowserService.KEY_SEARCH_RESULTS)) {
-                    callback.onError(query, extras);
-                    return;
-                }
-                Parcelable[] items = resultData.getParcelableArray(
-                        MediaBrowserService.KEY_SEARCH_RESULTS);
-                List<MediaItem> results = null;
-                if (items != null) {
-                    results = new ArrayList<>();
-                    for (Parcelable item : items) {
-                        results.add((MediaItem) item);
-                    }
-                }
-                callback.onSearchResult(query, extras, results);
-            }
-        };
-        try {
-            mServiceBinder.search(query, extras, receiver, mServiceCallbacks);
-        } catch (RemoteException e) {
-            Log.i(TAG, "Remote error getting media item.", e);
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    callback.onError(query, extras);
-                }
-            });
-        }
-    }
-
     private void subscribeInternal(String parentId, Bundle options, SubscriptionCallback callback) {
         // Check arguments.
         if (TextUtils.isEmpty(parentId)) {
@@ -945,7 +889,7 @@
          * @param parentId The media id of the parent media item.
          * @param children The children which were loaded.
          * @param options The bundle of service-specific arguments sent to the media
-         *            browse service. The contents of this bundle may affect the
+         *            browser service. The contents of this bundle may affect the
          *            information returned when browsing.
          */
         public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children,
@@ -1004,32 +948,6 @@
     }
 
     /**
-     * Callback for receiving the result of {@link #search}.
-     */
-    public static abstract class SearchCallback {
-        /**
-         * Called when the {@link #search} finished successfully.
-         *
-         * @param query The search query sent for the search request to the connected service.
-         * @param extras The bundle of service-specific arguments sent to the connected service.
-         * @param items The list of media items which contains the search result.
-         */
-        public void onSearchResult(@NonNull String query, Bundle extras,
-                @NonNull List<MediaItem> items) {
-        }
-
-        /**
-         * Called when an error happens while {@link #search} or the connected service doesn't
-         * support {@link #search}.
-         *
-         * @param query The search query sent for the search request to the connected service.
-         * @param extras The bundle of service-specific arguments sent to the connected service.
-         */
-        public void onError(@NonNull String query, Bundle extras) {
-        }
-    }
-
-    /**
      * ServiceConnection to the other app.
      */
     private class MediaServiceConnection implements ServiceConnection {
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index 4f3314c..3affee5c0 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -45,8 +45,6 @@
     void setQueueTitle(CharSequence title);
     void setExtras(in Bundle extras);
     void setRatingType(int type);
-    void setRepeatMode(int repeatMode);
-    void setShuffleModeEnabled(boolean enabled);
 
     // These commands relate to volume handling
     void setPlaybackToLocal(in AudioAttributes attributes);
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index a146c62..893bd3c 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -16,7 +16,6 @@
 package android.media.session;
 
 import android.content.Intent;
-import android.media.MediaDescription;
 import android.media.Rating;
 import android.net.Uri;
 import android.os.Bundle;
@@ -47,13 +46,7 @@
     void onRewind();
     void onSeekTo(long pos);
     void onRate(in Rating rating);
-    void onRepeatMode(int repeatMode);
-    void onShuffleMode(boolean enabled);
     void onCustomAction(String action, in Bundle args);
-    void onAddQueueItem(in MediaDescription description);
-    void onAddQueueItemAt(in MediaDescription description, int index);
-    void onRemoveQueueItem(in MediaDescription description);
-    void onRemoveQueueItemAt(int index);
 
     // These callbacks are for volume handling
     void onAdjustVolume(int direction);
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 7b5233a..249bcdc 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -18,7 +18,6 @@
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
-import android.media.MediaDescription;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.session.ISessionControllerCallback;
@@ -49,19 +48,6 @@
     ParcelableVolumeInfo getVolumeAttributes();
     void adjustVolume(int direction, int flags, String packageName);
     void setVolumeTo(int value, int flags, String packageName);
-    MediaMetadata getMetadata();
-    PlaybackState getPlaybackState();
-    ParceledListSlice getQueue();
-    void addQueueItem(in MediaDescription description);
-    void addQueueItemAt(in MediaDescription description, int index);
-    void removeQueueItem(in MediaDescription description);
-    void removeQueueItemAt(int index);
-
-    CharSequence getQueueTitle();
-    Bundle getExtras();
-    int getRatingType();
-    int getRepeatMode();
-    boolean isShuffleModeEnabled();
 
     // These commands are for the TransportControls
     void prepare();
@@ -81,7 +67,11 @@
     void rewind();
     void seekTo(long pos);
     void rate(in Rating rating);
-    void repeatMode(int repeatMode);
-    void shuffleMode(boolean enabled);
     void sendCustomAction(String action, in Bundle args);
+    MediaMetadata getMetadata();
+    PlaybackState getPlaybackState();
+    ParceledListSlice getQueue();
+    CharSequence getQueueTitle();
+    Bundle getExtras();
+    int getRatingType();
 }
diff --git a/media/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl
index 9517c08..cf31767 100644
--- a/media/java/android/media/session/ISessionControllerCallback.aidl
+++ b/media/java/android/media/session/ISessionControllerCallback.aidl
@@ -36,6 +36,4 @@
     void onQueueTitleChanged(CharSequence title);
     void onExtrasChanged(in Bundle extras);
     void onVolumeInfoChanged(in ParcelableVolumeInfo info);
-    void onRepeatModeChanged(int repeatMode);
-    void onShuffleModeChanged(boolean shuffleMode);
 }
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index bab2af2..622900f 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -23,7 +23,6 @@
 import android.content.pm.ParceledListSlice;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
-import android.media.MediaDescription;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
@@ -39,7 +38,6 @@
 import android.view.KeyEvent;
 
 import java.lang.ref.WeakReference;
-import java.lang.UnsupportedOperationException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -65,9 +63,7 @@
     private static final int MSG_UPDATE_QUEUE = 5;
     private static final int MSG_UPDATE_QUEUE_TITLE = 6;
     private static final int MSG_UPDATE_EXTRAS = 7;
-    private static final int MSG_UPDATE_REPEAT_MODE = 8;
-    private static final int MSG_UPDATE_SHUFFLE_MODE = 9;
-    private static final int MSG_DESTROYED = 10;
+    private static final int MSG_DESTROYED = 8;
 
     private final ISessionController mSessionBinder;
 
@@ -113,7 +109,8 @@
     }
 
     /**
-     * Get a {@link TransportControls} instance to send transport actions to this session.
+     * Get a {@link TransportControls} instance to send transport actions to
+     * the associated session.
      *
      * @return A transport controls instance.
      */
@@ -152,7 +149,7 @@
         try {
             return mSessionBinder.getPlaybackState();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getPlaybackState", e);
+            Log.wtf(TAG, "Error calling getPlaybackState.", e);
             return null;
         }
     }
@@ -166,7 +163,7 @@
         try {
             return mSessionBinder.getMetadata();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getMetadata", e);
+            Log.wtf(TAG, "Error calling getMetadata.", e);
             return null;
         }
     }
@@ -184,103 +181,12 @@
                 return queue.getList();
             }
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getQueue", e);
+            Log.wtf(TAG, "Error calling getQueue.", e);
         }
         return null;
     }
 
     /**
-     * Add a queue item from the given {@code description} at the end of the play queue
-     * of this session. Not all sessions may support this.
-     *
-     * @param description The {@link MediaDescription} for creating the
-     *                    {@link MediaSession.QueueItem} to be inserted.
-     * @throws UnsupportedOperationException If this session doesn't support this.
-     * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
-     */
-    public void addQueueItem(MediaDescription description) {
-        try {
-            long flags = mSessionBinder.getFlags();
-            if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
-                throw new UnsupportedOperationException(
-                        "This session doesn't support queue management operations");
-            }
-            mSessionBinder.addQueueItem(description);
-        } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling addQueueItem", e);
-        }
-    }
-
-    /**
-     * Add a queue item from the given {@code description} at the specified position
-     * in the play queue of this session. Shifts the queue item currently at that position
-     * (if any) and any subsequent queue items to the right (adds one to their indices).
-     * Not all sessions may support this.
-     *
-     * @param description The {@link MediaDescription} for creating the
-     *                    {@link MediaSession.QueueItem} to be inserted.
-     * @param index The index at which the created {@link MediaSession.QueueItem} is to be inserted.
-     * @throws UnsupportedOperationException If this session doesn't support this.
-     * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
-     */
-    public void addQueueItem(MediaDescription description, int index) {
-        try {
-            long flags = mSessionBinder.getFlags();
-            if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
-                throw new UnsupportedOperationException(
-                        "This session doesn't support queue management operations");
-            }
-            mSessionBinder.addQueueItemAt(description, index);
-        } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling addQueueItemAt", e);
-        }
-    }
-
-    /**
-     * Remove the first occurrence of the specified {@link MediaSession.QueueItem}
-     * with the given {@link MediaDescription description} in the play queue of the associated
-     * session. Not all sessions may support this.
-     *
-     * @param description The {@link MediaDescription} for denoting the
-     *                    {@link MediaSession.QueueItem} to be removed.
-     * @throws UnsupportedOperationException If this session doesn't support this.
-     * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
-     */
-    public void removeQueueItem(MediaDescription description) {
-        try {
-            long flags = mSessionBinder.getFlags();
-            if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
-                throw new UnsupportedOperationException(
-                        "This session doesn't support queue management operations");
-            }
-            mSessionBinder.removeQueueItem(description);
-        } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling removeQueueItem", e);
-        }
-    }
-
-    /**
-     * Remove an queue item at the specified position in the play queue
-     * of this session. Not all sessions may support this.
-     *
-     * @param index The index of the element to be removed.
-     * @throws UnsupportedOperationException If this session doesn't support this.
-     * @see MediaSession#FLAG_HANDLES_QUEUE_COMMANDS
-     */
-    public void removeQueueItemAt(int index) {
-        try {
-            long flags = mSessionBinder.getFlags();
-            if ((flags & MediaSession.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
-                throw new UnsupportedOperationException(
-                        "This session doesn't support queue management operations");
-            }
-            mSessionBinder.removeQueueItemAt(index);
-        } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling removeQueueItemAt", e);
-        }
-    }
-
-    /**
      * Get the queue title for this session.
      */
     public @Nullable CharSequence getQueueTitle() {
@@ -322,41 +228,12 @@
         try {
             return mSessionBinder.getRatingType();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getRatingType", e);
+            Log.wtf(TAG, "Error calling getRatingType.", e);
             return Rating.RATING_NONE;
         }
     }
 
     /**
-     * Get the repeat mode for this session.
-     *
-     * @return The latest repeat mode set to the session, or
-     *         {@link PlaybackState#REPEAT_MODE_NONE} if not set.
-     */
-    public int getRepeatMode() {
-        try {
-            return mSessionBinder.getRepeatMode();
-        } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getRepeatMode", e);
-            return PlaybackState.REPEAT_MODE_NONE;
-        }
-    }
-
-    /**
-     * Return whether the shuffle mode is enabled for this session.
-     *
-     * @return {@code true} if the shuffle mode is enabled, {@code false} if disabled or not set.
-     */
-    public boolean isShuffleModeEnabled() {
-        try {
-            return mSessionBinder.isShuffleModeEnabled();
-        } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling isShuffleModeEnabled", e);
-            return false;
-        }
-    }
-
-    /**
      * Get the flags for this session. Flags are defined in {@link MediaSession}.
      *
      * @return The current set of flags for the session.
@@ -365,7 +242,7 @@
         try {
             return mSessionBinder.getFlags();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getFlags", e);
+            Log.wtf(TAG, "Error calling getFlags.", e);
         }
         return 0;
     }
@@ -382,7 +259,7 @@
                     result.maxVolume, result.currentVolume);
 
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getAudioInfo", e);
+            Log.wtf(TAG, "Error calling getAudioInfo.", e);
         }
         return null;
     }
@@ -397,7 +274,7 @@
         try {
             return mSessionBinder.getLaunchPendingIntent();
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling getPendingIntent", e);
+            Log.wtf(TAG, "Error calling getPendingIntent.", e);
         }
         return null;
     }
@@ -426,7 +303,7 @@
         try {
             mSessionBinder.setVolumeTo(value, flags, mContext.getPackageName());
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling setVolumeTo", e);
+            Log.wtf(TAG, "Error calling setVolumeTo.", e);
         }
     }
 
@@ -447,7 +324,7 @@
         try {
             mSessionBinder.adjustVolume(direction, flags, mContext.getPackageName());
         } catch (RemoteException e) {
-            Log.wtf(TAG, "Error calling adjustVolumeBy", e);
+            Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
         }
     }
 
@@ -513,7 +390,7 @@
         try {
             mSessionBinder.sendCommand(command, args, cb);
         } catch (RemoteException e) {
-            Log.d(TAG, "Dead object in sendCommand", e);
+            Log.d(TAG, "Dead object in sendCommand.", e);
         }
     }
 
@@ -527,7 +404,7 @@
             try {
                 mPackageName = mSessionBinder.getPackageName();
             } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in getPackageName", e);
+                Log.d(TAG, "Dead object in getPackageName.", e);
             }
         }
         return mPackageName;
@@ -544,7 +421,7 @@
             try {
                 mTag = mSessionBinder.getTag();
             } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in getTag", e);
+                Log.d(TAG, "Dead object in getTag.", e);
             }
         }
         return mTag;
@@ -702,25 +579,6 @@
          */
         public void onAudioInfoChanged(PlaybackInfo info) {
         }
-
-        /**
-         * Override to handle changes to the repeat mode.
-         *
-         * @param repeatMode The repeat mode. It should be one of followings:
-         *                   {@link PlaybackState#REPEAT_MODE_NONE},
-         *                   {@link PlaybackState#REPEAT_MODE_ONE},
-         *                   {@link PlaybackState#REPEAT_MODE_ALL}
-         */
-        public void onRepeatModeChanged(@PlaybackState.RepeatMode int repeatMode) {
-        }
-
-        /**
-         * Override to handle changes to the shuffle mode.
-         *
-         * @param enabled {@code true} if the shuffle mode is enabled, {@code false} otherwise.
-         */
-        public void onShuffleModeChanged(boolean enabled) {
-        }
     }
 
     /**
@@ -744,7 +602,7 @@
             try {
                 mSessionBinder.prepare();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling prepare", e);
+                Log.wtf(TAG, "Error calling prepare.", e);
             }
         }
 
@@ -763,12 +621,12 @@
         public void prepareFromMediaId(String mediaId, Bundle extras) {
             if (TextUtils.isEmpty(mediaId)) {
                 throw new IllegalArgumentException(
-                        "You must specify a non-empty String for prepareFromMediaId");
+                        "You must specify a non-empty String for prepareFromMediaId.");
             }
             try {
                 mSessionBinder.prepareFromMediaId(mediaId, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling prepare(" + mediaId + ")", e);
+                Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
             }
         }
 
@@ -794,7 +652,7 @@
             try {
                 mSessionBinder.prepareFromSearch(query, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling prepare(" + query + ")", e);
+                Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
             }
         }
 
@@ -813,12 +671,12 @@
         public void prepareFromUri(Uri uri, Bundle extras) {
             if (uri == null || Uri.EMPTY.equals(uri)) {
                 throw new IllegalArgumentException(
-                        "You must specify a non-empty Uri for prepareFromUri");
+                        "You must specify a non-empty Uri for prepareFromUri.");
             }
             try {
                 mSessionBinder.prepareFromUri(uri, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling prepare(" + uri + ")", e);
+                Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
             }
         }
 
@@ -829,7 +687,7 @@
             try {
                 mSessionBinder.play();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play", e);
+                Log.wtf(TAG, "Error calling play.", e);
             }
         }
 
@@ -843,12 +701,12 @@
         public void playFromMediaId(String mediaId, Bundle extras) {
             if (TextUtils.isEmpty(mediaId)) {
                 throw new IllegalArgumentException(
-                        "You must specify a non-empty String for playFromMediaId");
+                        "You must specify a non-empty String for playFromMediaId.");
             }
             try {
                 mSessionBinder.playFromMediaId(mediaId, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play(" + mediaId + ")", e);
+                Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
             }
         }
 
@@ -870,7 +728,7 @@
             try {
                 mSessionBinder.playFromSearch(query, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play(" + query + ")", e);
+                Log.wtf(TAG, "Error calling play(" + query + ").", e);
             }
         }
 
@@ -884,12 +742,12 @@
         public void playFromUri(Uri uri, Bundle extras) {
             if (uri == null || Uri.EMPTY.equals(uri)) {
                 throw new IllegalArgumentException(
-                        "You must specify a non-empty Uri for playFromUri");
+                        "You must specify a non-empty Uri for playFromUri.");
             }
             try {
                 mSessionBinder.playFromUri(uri, extras);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling play(" + uri + ")", e);
+                Log.wtf(TAG, "Error calling play(" + uri + ").", e);
             }
         }
 
@@ -901,7 +759,7 @@
             try {
                 mSessionBinder.skipToQueueItem(id);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling skipToItem(" + id + ")", e);
+                Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
             }
         }
 
@@ -913,7 +771,7 @@
             try {
                 mSessionBinder.pause();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling pause", e);
+                Log.wtf(TAG, "Error calling pause.", e);
             }
         }
 
@@ -925,7 +783,7 @@
             try {
                 mSessionBinder.stop();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling stop", e);
+                Log.wtf(TAG, "Error calling stop.", e);
             }
         }
 
@@ -938,7 +796,7 @@
             try {
                 mSessionBinder.seekTo(pos);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling seekTo", e);
+                Log.wtf(TAG, "Error calling seekTo.", e);
             }
         }
 
@@ -950,7 +808,7 @@
             try {
                 mSessionBinder.fastForward();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling fastForward", e);
+                Log.wtf(TAG, "Error calling fastForward.", e);
             }
         }
 
@@ -961,7 +819,7 @@
             try {
                 mSessionBinder.next();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling next", e);
+                Log.wtf(TAG, "Error calling next.", e);
             }
         }
 
@@ -973,7 +831,7 @@
             try {
                 mSessionBinder.rewind();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling rewind", e);
+                Log.wtf(TAG, "Error calling rewind.", e);
             }
         }
 
@@ -984,7 +842,7 @@
             try {
                 mSessionBinder.previous();
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling previous", e);
+                Log.wtf(TAG, "Error calling previous.", e);
             }
         }
 
@@ -999,36 +857,7 @@
             try {
                 mSessionBinder.rate(rating);
             } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling rate", e);
-            }
-        }
-
-        /**
-         * Set the repeat mode for this session.
-         *
-         * @param repeatMode The repeat mode. Must be one of the followings:
-         *                   {@link PlaybackState#REPEAT_MODE_NONE},
-         *                   {@link PlaybackState#REPEAT_MODE_ONE},
-         *                   {@link PlaybackState#REPEAT_MODE_ALL}
-         */
-        public void setRepeatMode(@PlaybackState.RepeatMode int repeatMode) {
-            try {
-                mSessionBinder.repeatMode(repeatMode);
-            } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling setRepeatMode", e);
-            }
-        }
-
-        /**
-         * Set the shuffle mode for this session.
-         *
-         * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable.
-         */
-        public void setShuffleModeEnabled(boolean enabled) {
-            try {
-                mSessionBinder.shuffleMode(enabled);
-            } catch (RemoteException e) {
-                Log.wtf(TAG, "Error calling shuffleMode", e);
+                Log.wtf(TAG, "Error calling rate.", e);
             }
         }
 
@@ -1042,7 +871,7 @@
         public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction,
                     @Nullable Bundle args) {
             if (customAction == null) {
-                throw new IllegalArgumentException("CustomAction cannot be null");
+                throw new IllegalArgumentException("CustomAction cannot be null.");
             }
             sendCustomAction(customAction.getAction(), args);
         }
@@ -1058,12 +887,12 @@
          */
         public void sendCustomAction(@NonNull String action, @Nullable Bundle args) {
             if (TextUtils.isEmpty(action)) {
-                throw new IllegalArgumentException("CustomAction cannot be null");
+                throw new IllegalArgumentException("CustomAction cannot be null.");
             }
             try {
                 mSessionBinder.sendCustomAction(action, args);
             } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in sendCustomAction", e);
+                Log.d(TAG, "Dead object in sendCustomAction.", e);
             }
         }
     }
@@ -1233,21 +1062,6 @@
             }
         }
 
-        @Override
-        public void onRepeatModeChanged(int repeatMode) {
-            MediaController controller = mController.get();
-            if (controller != null) {
-                controller.postMessage(MSG_UPDATE_REPEAT_MODE, repeatMode, null);
-            }
-        }
-
-        @Override
-        public void onShuffleModeChanged(boolean enabled) {
-            MediaController controller = mController.get();
-            if (controller != null) {
-                controller.postMessage(MSG_UPDATE_SHUFFLE_MODE, enabled, null);
-            }
-        }
     }
 
     private final static class MessageHandler extends Handler {
@@ -1286,12 +1100,6 @@
                 case MSG_UPDATE_VOLUME:
                     mCallback.onAudioInfoChanged((PlaybackInfo) msg.obj);
                     break;
-                case MSG_UPDATE_REPEAT_MODE:
-                    mCallback.onRepeatModeChanged((int) msg.obj);
-                    break;
-                case MSG_UPDATE_SHUFFLE_MODE:
-                    mCallback.onShuffleModeChanged((boolean) msg.obj);
-                    break;
                 case MSG_DESTROYED:
                     mCallback.onSessionDestroyed();
                     break;
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index f10f442..dfd2bb35 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -93,12 +93,6 @@
     public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1;
 
     /**
-     * Set this flag on the session to indicate that it handles queue
-     * management commands through its {@link Callback}.
-     */
-    public static final int FLAG_HANDLES_QUEUE_COMMANDS = 1 << 2;
-
-    /**
      * System only flag for a session that needs to have priority over all other
      * sessions. This flag ensures this session will receive media button events
      * regardless of the current ordering in the system.
@@ -112,7 +106,6 @@
     @IntDef(flag = true, value = {
             FLAG_HANDLES_MEDIA_BUTTONS,
             FLAG_HANDLES_TRANSPORT_CONTROLS,
-            FLAG_HANDLES_QUEUE_COMMANDS,
             FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
     public @interface SessionFlags { }
 
@@ -493,41 +486,6 @@
     }
 
     /**
-     * Set the repeat mode for this session.
-     * <p>
-     * Note that if this method is not called before, {@link MediaController#getRepeatMode}
-     * will return {@link PlaybackState#REPEAT_MODE_NONE}.
-     *
-     * @param repeatMode The repeat mode. Must be one of the followings:
-     *                   {@link PlaybackState#REPEAT_MODE_NONE},
-     *                   {@link PlaybackState#REPEAT_MODE_ONE},
-     *                   {@link PlaybackState#REPEAT_MODE_ALL}
-     */
-    public void setRepeatMode(@PlaybackState.RepeatMode int repeatMode) {
-        try {
-            mBinder.setRepeatMode(repeatMode);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error in setRepeatMode.", e);
-        }
-    }
-
-    /**
-     * Set the shuffle mode for this session.
-     * <p>
-     * Note that if this method is not called before, {@link MediaController#isShuffleModeEnabled}
-     * will return {@code false}.
-     *
-     * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable.
-     */
-    public void setShuffleModeEnabled(boolean enabled) {
-        try {
-            mBinder.setShuffleModeEnabled(enabled);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error in setShuffleModeEnabled.", e);
-        }
-    }
-
-    /**
      * Set some extras that can be associated with the {@link MediaSession}. No assumptions should
      * be made as to how a {@link MediaController} will handle these extras.
      * Keys should be fully qualified (e.g. com.example.MY_EXTRA) to avoid conflicts.
@@ -646,34 +604,10 @@
         postToCallback(CallbackMessageHandler.MSG_RATE, rating);
     }
 
-    private void dispatchRepeatMode(int repeatMode) {
-        postToCallback(CallbackMessageHandler.MSG_REPEAT_MODE, repeatMode);
-    }
-
-    private void dispatchShuffleMode(boolean enabled) {
-        postToCallback(CallbackMessageHandler.MSG_SHUFFLE_MODE, enabled);
-    }
-
     private void dispatchCustomAction(String action, Bundle args) {
         postToCallback(CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args);
     }
 
-    private void dispatchAddQueueItem(MediaDescription description) {
-        postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM, description);
-    }
-
-    private void dispatchAddQueueItem(MediaDescription description, int index) {
-        postToCallback(CallbackMessageHandler.MSG_ADD_QUEUE_ITEM_AT, description, index);
-    }
-
-    private void dispatchRemoveQueueItem(MediaDescription description) {
-        postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM, description);
-    }
-
-    private void dispatchRemoveQueueItemAt(int index) {
-        postToCallback(CallbackMessageHandler.MSG_REMOVE_QUEUE_ITEM_AT, index);
-    }
-
     private void dispatchMediaButton(Intent mediaButtonIntent) {
         postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent);
     }
@@ -695,22 +629,10 @@
         postToCallback(CallbackMessageHandler.MSG_COMMAND, cmd);
     }
 
-    private void postToCallback(int what, int arg1) {
-        postToCallback(what, null, arg1);
-    }
-
     private void postToCallback(int what, Object obj) {
         postToCallback(what, obj, null);
     }
 
-    private void postToCallback(int what, Object obj, int arg1) {
-        synchronized (mLock) {
-            if (mCallback != null) {
-                mCallback.post(what, obj, arg1);
-            }
-        }
-    }
-
     private void postToCallback(int what, Object obj, Bundle extras) {
         synchronized (mLock) {
             if (mCallback != null) {
@@ -1048,33 +970,6 @@
         }
 
         /**
-         * Override to handle the setting of the repeat mode.
-         * <p>
-         * You should call {@link #setRepeatMode} before end of this method in order to notify
-         * the change to the {@link MediaController}, or {@link MediaController#getRepeatMode}
-         * could return an invalid value.
-         *
-         * @param repeatMode The repeat mode which is one of followings:
-         *                   {@link PlaybackState#REPEAT_MODE_NONE},
-         *                   {@link PlaybackState#REPEAT_MODE_ONE},
-         *                   {@link PlaybackState#REPEAT_MODE_ALL}
-         */
-        public void onSetRepeatMode(@PlaybackState.RepeatMode int repeatMode) {
-        }
-
-        /**
-         * Override to handle the setting of the shuffle mode.
-         * <p>
-         * You should call {@link #setShuffleModeEnabled} before the end of this method in order to
-         * notify the change to the {@link MediaController}, or
-         * {@link MediaController#isShuffleModeEnabled} could return an invalid value.
-         *
-         * @param enabled true when the shuffle mode is enabled, false otherwise.
-         */
-        public void onSetShuffleModeEnabled(boolean enabled) {
-        }
-
-        /**
          * Called when a {@link MediaController} wants a {@link PlaybackState.CustomAction} to be
          * performed.
          *
@@ -1084,47 +979,6 @@
          */
         public void onCustomAction(@NonNull String action, @Nullable Bundle extras) {
         }
-
-        /**
-         * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given
-         * {@link MediaDescription description} at the end of the play queue.
-         *
-         * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be
-         *                    inserted.
-         */
-        public void onAddQueueItem(MediaDescription description) {
-        }
-
-        /**
-         * Called when a {@link MediaController} wants to add a {@link QueueItem} with the given
-         * {@link MediaDescription description} at the specified position in the play queue.
-         *
-         * @param description The {@link MediaDescription} for creating the {@link QueueItem} to be
-         *                    inserted.
-         * @param index The index at which the created {@link QueueItem} is to be inserted.
-         */
-        public void onAddQueueItem(MediaDescription description, int index) {
-        }
-
-        /**
-         * Called when a {@link MediaController} wants to remove the first occurrence of the
-         * specified {@link QueueItem} with the given {@link MediaDescription description}
-         * in the play queue.
-         *
-         * @param description The {@link MediaDescription} for denoting the {@link QueueItem} to be
-         *                    removed.
-         */
-        public void onRemoveQueueItem(MediaDescription description) {
-        }
-
-        /**
-         * Called when a {@link MediaController} wants to remove a {@link QueueItem} at the
-         * specified position in the play queue.
-         *
-         * @param index The index of the element to be removed.
-         */
-        public void onRemoveQueueItemAt(int index) {
-        }
     }
 
     /**
@@ -1297,22 +1151,6 @@
         }
 
         @Override
-        public void onRepeatMode(int repeatMode) {
-            MediaSession session = mMediaSession.get();
-            if (session != null) {
-                session.dispatchRepeatMode(repeatMode);
-            }
-        }
-
-        @Override
-        public void onShuffleMode(boolean enabled) {
-            MediaSession session = mMediaSession.get();
-            if (session != null) {
-                session.dispatchShuffleMode(enabled);
-            }
-        }
-
-        @Override
         public void onCustomAction(String action, Bundle args) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
@@ -1321,38 +1159,6 @@
         }
 
         @Override
-        public void onAddQueueItem(MediaDescription description) {
-            MediaSession session = mMediaSession.get();
-            if (session != null) {
-                session.dispatchAddQueueItem(description);
-            }
-        }
-
-        @Override
-        public void onAddQueueItemAt(MediaDescription description, int index) {
-            MediaSession session = mMediaSession.get();
-            if (session != null) {
-                session.dispatchAddQueueItem(description, index);
-            }
-        }
-
-        @Override
-        public void onRemoveQueueItem(MediaDescription description) {
-            MediaSession session = mMediaSession.get();
-            if (session != null) {
-                session.dispatchRemoveQueueItem(description);
-            }
-        }
-
-        @Override
-        public void onRemoveQueueItemAt(int index) {
-            MediaSession session = mMediaSession.get();
-            if (session != null) {
-                session.dispatchRemoveQueueItemAt(index);
-            }
-        }
-
-        @Override
         public void onAdjustVolume(int direction) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
@@ -1376,7 +1182,7 @@
      */
     public static final class QueueItem implements Parcelable {
         /**
-         * This id is reserved. No items can be explicitly asigned this id.
+         * This id is reserved. No items can be explicitly assigned this id.
          */
         public static final int UNKNOWN_ID = -1;
 
@@ -1485,15 +1291,9 @@
         private static final int MSG_REWIND = 17;
         private static final int MSG_SEEK_TO = 18;
         private static final int MSG_RATE = 19;
-        private static final int MSG_REPEAT_MODE = 20;
-        private static final int MSG_SHUFFLE_MODE = 21;
-        private static final int MSG_CUSTOM_ACTION = 22;
-        private static final int MSG_ADJUST_VOLUME = 23;
-        private static final int MSG_SET_VOLUME = 24;
-        private static final int MSG_ADD_QUEUE_ITEM = 25;
-        private static final int MSG_ADD_QUEUE_ITEM_AT = 26;
-        private static final int MSG_REMOVE_QUEUE_ITEM = 27;
-        private static final int MSG_REMOVE_QUEUE_ITEM_AT = 28;
+        private static final int MSG_CUSTOM_ACTION = 20;
+        private static final int MSG_ADJUST_VOLUME = 21;
+        private static final int MSG_SET_VOLUME = 22;
 
         private MediaSession.Callback mCallback;
 
@@ -1582,33 +1382,15 @@
                 case MSG_RATE:
                     mCallback.onSetRating((Rating) msg.obj);
                     break;
-                case MSG_REPEAT_MODE:
-                    mCallback.onSetRepeatMode(msg.arg1);
-                    break;
-                case MSG_SHUFFLE_MODE:
-                    mCallback.onSetShuffleModeEnabled((boolean) msg.obj);
-                    break;
                 case MSG_CUSTOM_ACTION:
                     mCallback.onCustomAction((String) msg.obj, msg.getData());
                     break;
-                case MSG_ADD_QUEUE_ITEM:
-                    mCallback.onAddQueueItem((MediaDescription) msg.obj);
-                    break;
-                case MSG_ADD_QUEUE_ITEM_AT:
-                    mCallback.onAddQueueItem((MediaDescription) msg.obj, msg.arg1);
-                    break;
-                case MSG_REMOVE_QUEUE_ITEM:
-                    mCallback.onRemoveQueueItem((MediaDescription) msg.obj);
-                    break;
-                case MSG_REMOVE_QUEUE_ITEM_AT:
-                    mCallback.onRemoveQueueItemAt(msg.arg1);
-                    break;
                 case MSG_ADJUST_VOLUME:
                     synchronized (mLock) {
                         vp = mVolumeProvider;
                     }
                     if (vp != null) {
-                        vp.onAdjustVolume(msg.arg1);
+                        vp.onAdjustVolume((int) msg.obj);
                     }
                     break;
                 case MSG_SET_VOLUME:
@@ -1616,7 +1398,7 @@
                         vp = mVolumeProvider;
                     }
                     if (vp != null) {
-                        vp.onSetVolumeTo(msg.arg1);
+                        vp.onSetVolumeTo((int) msg.obj);
                     }
                     break;
             }
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 1ea6109..8283c8b 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -45,8 +45,7 @@
             ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
             ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
             ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
-            ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI,
-            ACTION_SET_REPEAT_MODE, ACTION_SET_SHUFFLE_MODE_ENABLED})
+            ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Actions {}
 
@@ -177,20 +176,6 @@
     public static final long ACTION_PREPARE_FROM_URI = 1 << 17;
 
     /**
-     * Indicates this session supports the set repeat mode command.
-     *
-     * @see Builder#setActions(long)
-     */
-    public static final long ACTION_SET_REPEAT_MODE = 1 << 18;
-
-    /**
-     * Indicates this session supports the set shuffle mode enabled command.
-     *
-     * @see Builder#setActions(long)
-     */
-    public static final long ACTION_SET_SHUFFLE_MODE_ENABLED = 1 << 19;
-
-    /**
      * @hide
      */
     @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING,
@@ -296,30 +281,6 @@
      */
     public final static long PLAYBACK_POSITION_UNKNOWN = -1;
 
-    /**
-     * @hide
-     */
-    @IntDef({REPEAT_MODE_NONE, REPEAT_MODE_ONE, REPEAT_MODE_ALL})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface RepeatMode {}
-    /**
-     * Use this value with {@link MediaController.TransportControls#setRepeatMode}
-     * to indicate that the playback will be stopped at the end of the playing media list.
-     */
-    public final static int REPEAT_MODE_NONE = 0;
-
-    /**
-     * Use this value with {@link MediaController.TransportControls#setRepeatMode}
-     * to indicate that the playback of the current playing media item will be repeated.
-     */
-    public final static int REPEAT_MODE_ONE = 1;
-
-    /**
-     * Use this value with {@link MediaController.TransportControls#setRepeatMode}
-     * to indicate that the playback of the playing media list will be repeated.
-     */
-    public final static int REPEAT_MODE_ALL = 2;
-
     private final int mState;
     private final long mPosition;
     private final long mBufferedPosition;
@@ -466,8 +427,6 @@
      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li>
      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li>
      * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
-     * <li> {@link PlaybackState#ACTION_SET_REPEAT_MODE}</li>
-     * <li> {@link PlaybackState#ACTION_SET_SHUFFLE_MODE_ENABLED}</li>
      * </ul>
      */
     @Actions
@@ -1002,8 +961,6 @@
          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li>
          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li>
          * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
-         * <li> {@link PlaybackState#ACTION_SET_REPEAT_MODE}</li>
-         * <li> {@link PlaybackState#ACTION_SET_SHUFFLE_MODE_ENABLED}</li>
          * </ul>
          *
          * @param actions The set of actions allowed.
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index af4a5be..b076bb6 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -107,6 +107,7 @@
     List<DvbDeviceInfo> getDvbDeviceList();
     ParcelFileDescriptor openDvbDevice(in DvbDeviceInfo info, int device);
 
-    // For preview programs
+    // For preview channels and programs
     void sendTvInputNotifyIntent(in Intent intent, int userId);
+    void requestChannelBrowsable(in Uri channelUri, int userId);
 }
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 6635b5f..71f9ba25 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -21,9 +21,11 @@
 import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.annotation.SystemApi;
+import android.app.Activity;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentUris;
+import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
@@ -75,8 +77,9 @@
     private static final String PATH_PASSTHROUGH = "passthrough";
 
     /**
-     * Activity Action: sent by an application telling the system to set the given channel as
-     * browsable. This is only relevant to channels with {@link Channels#TYPE_PREVIEW} type.
+     * Broadcast Action: sent when an application requests the system to make the given channel
+     * browsable.  The operation is performed in the background without user interaction. This
+     * is only relevant to channels with {@link Channels#TYPE_PREVIEW} type.
      *
      * <p>The intent must contain the following bundle parameters:
      * <ul>
@@ -84,9 +87,26 @@
      *     integer.</li>
      *     <li>{@link #EXTRA_PACKAGE_NAME}: the package name of the requesting application.</li>
      * </ul>
+     * @hide
      */
-    public static final String ACTION_MAKE_CHANNEL_BROWSABLE =
-            "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
+    @SystemApi
+    public static final String ACTION_CHANNEL_BROWSABLE_REQUESTED =
+            "android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED";
+
+    /**
+     * Activity Action: sent by an application telling the system to make the given channel
+     * browsable with user interaction. The system may show UI to ask user to approve the channel.
+     * This is only relevant to channels with {@link Channels#TYPE_PREVIEW} type. Use
+     * {@link Activity#startActivityForResult} to get the result of the request.
+     *
+     * <p>The intent must contain the following bundle parameters:
+     * <ul>
+     *     <li>{@link #EXTRA_CHANNEL_ID}: ID for the {@link Channels#TYPE_PREVIEW} channel as a long
+     *     integer.</li>
+     * </ul>
+     */
+    public static final String ACTION_REQUEST_CHANNEL_BROWSABLE =
+            "android.media.tv.action.REQUEST_CHANNEL_BROWSABLE";
 
     /**
      * Broadcast Action: sent by the system to tell the target TV input that one of its preview
@@ -146,10 +166,16 @@
     public static final String ACTION_INITIALIZE_PROGRAMS =
             "android.media.tv.action.INITIALIZE_PROGRAMS";
 
-    /** The key for a bundle parameter containing a channel ID as a long integer */
+    /**
+     * The key for a bundle parameter containing a channel ID as a long integer
+     */
     public static final String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
 
-    /** The key for a bundle parameter containing a package name as a string. */
+    /**
+     * The key for a bundle parameter containing a package name as a string.
+     * @hide
+     */
+    @SystemApi
     public static final String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
 
     /** The key for a bundle parameter containing a program ID as a long integer. */
@@ -161,6 +187,38 @@
             "android.media.tv.extra.WATCH_NEXT_PROGRAM_ID";
 
     /**
+     * The key for a bundle parameter containing the result code of a method call as an integer.
+     *
+     * @see #RESULT_OK
+     * @see #RESULT_ERROR_IO
+     * @see #RESULT_ERROR_INVALID_ARGUMENT
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_RESULT_CODE = "android.media.tv.extra.RESULT_CODE";
+
+    /**
+     * The result code for a successful execution without error.
+     * @hide
+     */
+    @SystemApi
+    public static final int RESULT_OK = 0;
+
+    /**
+     * The result code for a failure from I/O operation.
+     * @hide
+     */
+    @SystemApi
+    public static final int RESULT_ERROR_IO = 1;
+
+    /**
+     * The result code for a failure from invalid argument.
+     * @hide
+     */
+    @SystemApi
+    public static final int RESULT_ERROR_INVALID_ARGUMENT = 2;
+
+    /**
      * The method name to get existing columns in the given table of the specified content provider.
      *
      * <p>The method caller must provide the following parameter:
@@ -209,6 +267,78 @@
     public static final String METHOD_ADD_COLUMN = "add_column";
 
     /**
+     * The method name to get all the blocked packages. When a package is blocked, all the data for
+     * preview programs/channels and watch next programs belonging to this package in the content
+     * provider will be cleared. Once a package is blocked, {@link SecurityException} will be thrown
+     * for all the requests to preview programs/channels and watch next programs via
+     * {@link android.content.ContentProvider} from it.
+     *
+     * <p>The returned {@link android.os.Bundle} will include all the blocked package names with the
+     * key {@link #EXTRA_BLOCKED_PACKAGES}.
+     *
+     * @see ContentResolver#call(Uri, String, String, Bundle)
+     * @see #EXTRA_BLOCKED_PACKAGES
+     * @see #METHOD_BLOCK_PACKAGE
+     * @see #METHOD_UNBLOCK_PACKAGE
+     * @hide
+     */
+    @SystemApi
+    public static final String METHOD_GET_BLOCKED_PACKAGES = "get_blocked_packages";
+
+    /**
+     * The method name to block the access from the given package. When a package is blocked, all
+     * the data for preview programs/channels and watch next programs belonging to this package in
+     * the content provider will be cleared. Once a package is blocked, {@link SecurityException}
+     * will be thrown for all the requests to preview programs/channels and watch next programs via
+     * {@link android.content.ContentProvider} from it.
+     *
+     * <p>The method caller must provide the following parameter:
+     * <ul>
+     *     <li>{@code arg}: The package name to be added as blocked package {@link String}.</li>
+     * </ul>
+     *
+     * <p>The returned {@link android.os.Bundle} will include an integer code denoting whether the
+     * execution is successful or not with the key {@link #EXTRA_RESULT_CODE}. If {@code arg} is
+     * empty, the result code will be {@link #RESULT_ERROR_INVALID_ARGUMENT}. If success, the result
+     * code will be {@link #RESULT_OK}. Otherwise, the result code will be {@link #RESULT_ERROR_IO}.
+     *
+     * @see ContentResolver#call(Uri, String, String, Bundle)
+     * @see #EXTRA_RESULT_CODE
+     * @see #METHOD_GET_BLOCKED_PACKAGES
+     * @see #METHOD_UNBLOCK_PACKAGE
+     * @hide
+     */
+    @SystemApi
+    public static final String METHOD_BLOCK_PACKAGE = "block_package";
+
+    /**
+     * The method name to unblock the access from the given package. When a package is blocked, all
+     * the data for preview programs/channels and watch next programs belonging to this package in
+     * the content provider will be cleared. Once a package is blocked, {@link SecurityException}
+     * will be thrown for all the requests to preview programs/channels and watch next programs via
+     * {@link android.content.ContentProvider} from it.
+     *
+     * <p>The method caller must provide the following parameter:
+     * <ul>
+     *     <li>{@code arg}: The package name to be removed from blocked list as a {@link String}.
+     *     </li>
+     * </ul>
+     *
+     * <p>The returned {@link android.os.Bundle} will include an integer code denoting whether the
+     * execution is successful or not with the key {@link #EXTRA_RESULT_CODE}. If {@code arg} is
+     * empty, the result code will be {@link #RESULT_ERROR_INVALID_ARGUMENT}. If success, the result
+     * code will be {@link #RESULT_OK}. Otherwise, the result code will be {@link #RESULT_ERROR_IO}.
+     *
+     * @see ContentResolver#call(Uri, String, String, Bundle)
+     * @see #EXTRA_RESULT_CODE
+     * @see #METHOD_GET_BLOCKED_PACKAGES
+     * @see #METHOD_BLOCK_PACKAGE
+     * @hide
+     */
+    @SystemApi
+    public static final String METHOD_UNBLOCK_PACKAGE = "unblock_package";
+
+    /**
      * The key for a returned {@link Bundle} value containing existing column names in the given
      * table as an {@link ArrayList} of {@link String}.
      *
@@ -253,6 +383,16 @@
     public static final String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
 
     /**
+     * The key for a returned {@link Bundle} value containing all the blocked package names as an
+     * {@link ArrayList} of {@link String}.
+     *
+     * @see #METHOD_GET_BLOCKED_PACKAGES
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_BLOCKED_PACKAGES = "android.media.tv.extra.BLOCKED_PACKAGES";
+
+    /**
      * An optional query, update or delete URI parameter that allows the caller to specify TV input
      * ID to filter channels.
      * @hide
@@ -296,6 +436,14 @@
     public static final String PARAM_CANONICAL_GENRE = "canonical_genre";
 
     /**
+     * A query, update or delete URI parameter that allows the caller to operate only on preview or
+     * non-preview channels. If set to "true", the operation affects the rows for preview channels
+     * only. If set to "false", the operation affects the rows for non-preview channels only.
+     * @hide
+     */
+    public static final String PARAM_PREVIEW = "preview";
+
+    /**
      * Builds an ID that uniquely identifies a TV input service.
      *
      * @param name The {@link ComponentName} of the TV input service to build ID for.
@@ -565,6 +713,24 @@
         return isTvUri(uri) && isTwoSegmentUriStartingWith(uri, PATH_PROGRAM);
     }
 
+    /**
+     * Requests to make a channel browsable.
+     *
+     * <p>Once called, the system will review the request and make the channel browsable based on
+     * its policy. The first request from a package is guaranteed to be approved. This is only
+     * relevant to channels with {@link Channels#TYPE_PREVIEW} type.
+     *
+     * @param context The context for accessing content provider.
+     * @param channelId The channel ID to be browsable.
+     * @see Channels#COLUMN_BROWSABLE
+     */
+    public static void requestChannelBrowsable(Context context, long channelId) {
+        TvInputManager manager = (TvInputManager) context.getSystemService(
+            Context.TV_INPUT_SERVICE);
+        if (manager != null) {
+            manager.requestChannelBrowsable(buildChannelUri(channelId));
+        }
+    }
 
     private TvContract() {}
 
@@ -1024,6 +1190,7 @@
                 ASPECT_RATIO_3_2,
                 ASPECT_RATIO_1_1,
                 ASPECT_RATIO_2_3,
+                ASPECT_RATIO_4_3,
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface AspectRatio {}
@@ -1045,12 +1212,20 @@
         int ASPECT_RATIO_3_2 = 1;
 
         /**
+         * The aspect ratio for 4:3.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        int ASPECT_RATIO_4_3 = 2;
+
+        /**
          * The aspect ratio for 1:1.
          *
          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
          */
-        int ASPECT_RATIO_1_1 = 2;
+        int ASPECT_RATIO_1_1 = 3;
 
         /**
          * The aspect ratio for 2:3.
@@ -1058,7 +1233,7 @@
          * @see #COLUMN_POSTER_ART_ASPECT_RATIO
          * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
          */
-        int ASPECT_RATIO_2_3 = 3;
+        int ASPECT_RATIO_2_3 = 4;
 
         /** @hide */
         @IntDef({
@@ -1183,6 +1358,7 @@
          * <p>The value should match one of the followings:
          * {@link #ASPECT_RATIO_16_9},
          * {@link #ASPECT_RATIO_3_2},
+         * {@link #ASPECT_RATIO_4_3},
          * {@link #ASPECT_RATIO_1_1}, and
          * {@link #ASPECT_RATIO_2_3}.
          *
@@ -1196,6 +1372,7 @@
          * <p>The value should match one of the followings:
          * {@link #ASPECT_RATIO_16_9},
          * {@link #ASPECT_RATIO_3_2},
+         * {@link #ASPECT_RATIO_4_3},
          * {@link #ASPECT_RATIO_1_1}, and
          * {@link #ASPECT_RATIO_2_3}.
          *
@@ -2184,19 +2361,6 @@
          */
         public static final String COLUMN_TRANSIENT = "transient";
 
-        /**
-         * The flag indicating whether this TV channel is approved to be shown by the system.
-         *
-         * <p>A value of 1 indicates that the channel is approved to be shown by the system, and a
-         * value of 0 indicates that the channel is blocked by system. If not specified, this value
-         * is set to 0 (not approved) by default.
-         *
-         * <p>Type: INTEGER (boolean)
-         * @hide
-         */
-        @SystemApi
-        public static final String COLUMN_SYSTEM_APPROVED = "system_approved";
-
         private Channels() {}
 
         /**
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 276a0dc..68ee02c 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1681,6 +1681,23 @@
     }
 
     /**
+     * Requests to make a channel browsable.
+     *
+     * <p>Once called, the system will review the request and make the channel browsable based on
+     * its policy. The first request from a package is guaranteed to be approved.
+     *
+     * @param channelUri The URI for the channel to be browsable.
+     * @hide
+     */
+    public void requestChannelBrowsable(Uri channelUri) {
+        try {
+            mService.requestChannelBrowsable(channelUri, mUserId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * The Session provides the per-session functionality of TV inputs.
      * @hide
      */
diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index e95154f..84f41f6 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -19,10 +19,8 @@
 
     void addSubscriptionDeprecated(String uri, IMediaBrowserServiceCallbacks callbacks);
     void removeSubscriptionDeprecated(String uri, IMediaBrowserServiceCallbacks callbacks);
-    void getMediaItem(String uri, in ResultReceiver cb, IMediaBrowserServiceCallbacks callbacks);
-    void search(String query, in Bundle extras, in ResultReceiver cb,
-            IMediaBrowserServiceCallbacks callbacks);
 
+    void getMediaItem(String uri, in ResultReceiver cb, IMediaBrowserServiceCallbacks callbacks);
     void addSubscription(String uri, in IBinder token, in Bundle options,
             IMediaBrowserServiceCallbacks callbacks);
     void removeSubscription(String uri, in IBinder token, IMediaBrowserServiceCallbacks callbacks);
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index d372efb..b52906d 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -89,15 +89,8 @@
      */
     public static final String KEY_MEDIA_ITEM = "media_item";
 
-    /**
-     * A key for passing the list of MediaItems to the ResultReceiver in search.
-     * @hide
-     */
-    public static final String KEY_SEARCH_RESULTS = "search_results";
-
     private static final int RESULT_FLAG_OPTION_NOT_HANDLED = 1 << 0;
     private static final int RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED = 1 << 1;
-    private static final int RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED = 1 << 2;
 
     private static final int RESULT_ERROR = -1;
     private static final int RESULT_OK = 0;
@@ -105,7 +98,7 @@
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED,
-            RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED, RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED })
+            RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED })
     private @interface ResultFlags { }
 
     private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>();
@@ -137,7 +130,6 @@
      *
      * @see #onLoadChildren
      * @see #onLoadItem
-     * @see #onSearch
      */
     public class Result<T> {
         private Object mDebug;
@@ -330,23 +322,6 @@
                 }
             });
         }
-
-        @Override
-        public void search(final String query, Bundle extras, ResultReceiver receiver,
-                final IMediaBrowserServiceCallbacks callbacks) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    final IBinder b = callbacks.asBinder();
-                    ConnectionRecord connection = mConnections.get(b);
-                    if (connection == null) {
-                        Log.w(TAG, "search for callback that isn't registered query=" + query);
-                        return;
-                    }
-                    performSearch(query, extras, connection, receiver);
-                }
-            });
-        }
     }
 
     @Override
@@ -472,32 +447,6 @@
     }
 
     /**
-     * Called to get the search result.
-     * <p>
-     * Implementations must call {@link Result#sendResult result.sendResult}. If
-     * the search will be an expensive operation {@link Result#detach result.detach}
-     * may be called before returning from this function, and then {@link Result#sendResult
-     * result.sendResult} called when the search has been completed.
-     * </p><p>
-     * In case there are no search results, call {@link Result#sendResult} with an empty list.
-     * In case there are some errors happened, call {@link Result#sendResult result.sendResult}
-     * with {@code null}, which will invoke {@link MediaBrowser.SearchCallback#onError}.
-     * </p><p>
-     * The default implementation will invoke {@link MediaBrowser.SearchCallback#onError}.
-     * </p>
-     *
-     * @param query The search query sent from the media browser. It contains keywords separated
-     *            by space.
-     * @param extras The bundle of service-specific arguments sent from the media browser.
-     * @param result The {@link Result} to send the search result.
-     */
-    public void onSearch(@NonNull String query, Bundle extras,
-            Result<List<MediaBrowser.MediaItem>> result) {
-        result.setFlags(RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED);
-        result.sendResult(null);
-    }
-
-    /**
      * Call to set the media session.
      * <p>
      * This should be called as soon as possible during the service's startup.
@@ -545,16 +494,16 @@
      * media browser service when connecting and retrieving the root id for browsing, or null if
      * none. The contents of this bundle may affect the information returned when browsing.
      *
-     * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren},
-     *             {@link #onLoadItem} or {@link #onSearch}.
+     * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren} or
+     *             {@link #onLoadItem}.
      * @see MediaBrowserService.BrowserRoot#EXTRA_RECENT
      * @see MediaBrowserService.BrowserRoot#EXTRA_OFFLINE
      * @see MediaBrowserService.BrowserRoot#EXTRA_SUGGESTED
      */
     public final Bundle getBrowserRootHints() {
         if (mCurConnection == null) {
-            throw new IllegalStateException("This should be called inside of onLoadChildren,"
-                    + " onLoadItem or onSearch methods");
+            throw new IllegalStateException("This should be called inside of onLoadChildren or"
+                    + " onLoadItem methods");
         }
         return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
     }
@@ -771,34 +720,6 @@
         }
     }
 
-    private void performSearch(String query, Bundle extras, final ConnectionRecord connection,
-            final ResultReceiver receiver) {
-        final Result<List<MediaBrowser.MediaItem>> result =
-                new Result<List<MediaBrowser.MediaItem>>(query) {
-            @Override
-            void onResultSent(List<MediaBrowser.MediaItem> items, @ResultFlags int flag) {
-                if ((flag & RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED) != 0
-                        || items == null) {
-                    receiver.send(RESULT_ERROR, null);
-                    return;
-                }
-                Bundle bundle = new Bundle();
-                bundle.putParcelableArray(KEY_SEARCH_RESULTS,
-                        items.toArray(new MediaBrowser.MediaItem[0]));
-                receiver.send(RESULT_OK, bundle);
-            }
-        };
-
-        mCurConnection = connection;
-        onSearch(query, extras, result);
-        mCurConnection = null;
-
-        if (!result.isDone()) {
-            throw new IllegalStateException("onSearch must call detach() or sendResult()"
-                    + " before returning for query=" + query);
-        }
-    }
-
     /**
      * Contains information that the browser service needs to send to the client
      * when first connected.
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index a8dd313..2178607 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -2002,7 +2002,7 @@
     { "getName", "()Ljava/lang/String;",
       (void *)android_media_MediaCodec_getName },
 
-    { "native_getMetrics", "()Landroid/os/Bundle;",
+    { "native_getMetrics", "()Landroid/os/PersistableBundle;",
       (void *)android_media_MediaCodec_native_getMetrics},
 
     { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
diff --git a/media/jni/android_media_MediaDescrambler.cpp b/media/jni/android_media_MediaDescrambler.cpp
index f031dbb..85d33b7 100644
--- a/media/jni/android_media_MediaDescrambler.cpp
+++ b/media/jni/android_media_MediaDescrambler.cpp
@@ -54,11 +54,10 @@
 }
 
 static status_t getBufferAndSize(
-        JNIEnv *env, jobject byteBuf, jint offset, size_t length,
+        JNIEnv *env, jobject byteBuf, jint offset, jint limit, size_t length,
         void **outPtr, jbyteArray *outByteArray) {
     void *ptr = env->GetDirectBufferAddress(byteBuf);
 
-    size_t bufSize;
     jbyteArray byteArray = NULL;
 
     ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
@@ -78,13 +77,9 @@
 
         jboolean isCopy;
         ptr = env->GetByteArrayElements(byteArray, &isCopy);
-
-        bufSize = (size_t) env->GetArrayLength(byteArray);
-    } else {
-        bufSize = (size_t) env->GetDirectBufferCapacity(byteBuf);
     }
 
-    if (length + offset > bufSize) {
+    if ((jint)length + offset > limit) {
         if (byteArray != NULL) {
             env->ReleaseByteArrayElements(byteArray, (jbyte *)ptr, 0);
         }
@@ -294,7 +289,8 @@
 static jint android_media_MediaDescrambler_native_descramble(
         JNIEnv *env, jobject thiz, jbyte key, jint numSubSamples,
         jintArray numBytesOfClearDataObj, jintArray numBytesOfEncryptedDataObj,
-        jobject srcBuf, jint srcOffset, jobject dstBuf, jint dstOffset) {
+        jobject srcBuf, jint srcOffset, jint srcLimit,
+        jobject dstBuf, jint dstOffset, jint dstLimit) {
     sp<JDescrambler> descrambler = getDescrambler(env, thiz);
     if (descrambler == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -307,7 +303,7 @@
             numBytesOfEncryptedDataObj, &subSamples);
     if (totalLength < 0) {
         jniThrowException(env, "java/lang/IllegalArgumentException",
-                "Invalid sub sample info!");
+                "Invalid subsample info!");
         return -1;
     }
 
@@ -315,16 +311,23 @@
     void *srcPtr = NULL, *dstPtr = NULL;
     jbyteArray srcArray = NULL, dstArray = NULL;
     status_t err = getBufferAndSize(
-            env, srcBuf, srcOffset, totalLength, &srcPtr, &srcArray);
+            env, srcBuf, srcOffset, srcLimit, totalLength, &srcPtr, &srcArray);
 
     if (err == OK) {
         if (dstBuf == NULL) {
             dstPtr = srcPtr;
         } else {
             err = getBufferAndSize(
-                    env, dstBuf, dstOffset, totalLength, &dstPtr, &dstArray);
+                    env, dstBuf, dstOffset, dstLimit, totalLength, &dstPtr, &dstArray);
         }
     }
+
+    if (err != OK) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "Invalid buffer offset and/or size for subsamples!");
+        return -1;
+    }
+
     Status status;
     if (err == OK) {
         status = descrambler->descramble(
@@ -394,7 +397,7 @@
             (void *)android_media_MediaDescrambler_native_init },
     { "native_setup", "(Landroid/os/IBinder;)V",
             (void *)android_media_MediaDescrambler_native_setup },
-    { "native_descramble", "(BI[I[ILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;I)I",
+    { "native_descramble", "(BI[I[ILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)I",
             (void *)android_media_MediaDescrambler_native_descramble },
 };
 
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index c2cfed9..9e5d3d1 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -905,7 +905,7 @@
     { "hasCacheReachedEndOfStream", "()Z",
       (void *)android_media_MediaExtractor_hasCacheReachedEOS },
 
-    {"native_getMetrics",          "()Landroid/os/Bundle;",
+    {"native_getMetrics",          "()Landroid/os/PersistableBundle;",
       (void *)android_media_MediaExtractor_native_getMetrics},
 };
 
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index f4e940d..0a3ce21d 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -302,13 +302,11 @@
     SkBitmap bitmap;
     GraphicsJNI::getSkBitmap(env, jBitmap, &bitmap);
 
-    bitmap.lockPixels();
     rotate((uint16_t*)bitmap.getPixels(),
            (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)),
            videoFrame->mWidth,
            videoFrame->mHeight,
            videoFrame->mRotationAngle);
-    bitmap.unlockPixels();
 
     if (videoFrame->mDisplayWidth  != videoFrame->mWidth ||
         videoFrame->mDisplayHeight != videoFrame->mHeight) {
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
index fb606ba..8979cec 100644
--- a/media/jni/android_media_MediaMetricsJNI.cpp
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -24,15 +24,12 @@
 
 namespace android {
 
-// place the attributes into a java Bundle object
-// decide whether this is appropriately scoped here.
-// if we do it somewhere else, we have to figure a "give me all the attrs"
-// access to the inside of MediaAnalyticsItem
+// place the attributes into a java PersistableBundle object
 jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
 
-    jclass clazzBundle = env->FindClass("android/os/Bundle");
+    jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
     if (clazzBundle==NULL) {
-        ALOGD("can't find android/os/Bundle");
+        ALOGD("can't find android/os/PersistableBundle");
         return NULL;
     }
     // sometimes the caller provides one for us to fill
@@ -58,7 +55,7 @@
     // -- get name, get type, get value
     // -- insert appropriately into the bundle
     for (size_t i = 0 ; i < item->mPropCount; i++ ) {
-	    MediaAnalyticsItem::Prop *prop = &item->mProps[i];
+            MediaAnalyticsItem::Prop *prop = &item->mProps[i];
             // build the key parameter from prop->mName
             jstring keyName = env->NewStringUTF(prop->mName);
             // invoke the appropriate method to insert
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 1b52cf5..2fc4afd 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1393,7 +1393,7 @@
     {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},
     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},
     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
-    {"native_getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaPlayer_native_getMetrics},
+    {"native_getMetrics",   "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer_native_getMetrics},
     {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
     {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
     {"setSyncParams",     "(Landroid/media/SyncParams;)V",  (void *)android_media_MediaPlayer_setSyncParams},
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 7a63e00..2c1e834 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -688,7 +688,7 @@
     {"native_finalize",      "()V",                             (void *)android_media_MediaRecorder_native_finalize},
     {"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface },
 
-    {"native_getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaRecorder_native_getMetrics},
+    {"native_getMetrics",    "()Landroid/os/PersistableBundle;", (void *)android_media_MediaRecorder_native_getMetrics},
 };
 
 // This function only registers the native methods, and is called from
diff --git a/media/mca/samples/CameraEffectsRecordingSample/java/android/media/filterfw/samples/CameraEffectsRecordingSample.java b/media/mca/samples/CameraEffectsRecordingSample/java/android/media/filterfw/samples/CameraEffectsRecordingSample.java
index c0c3034..0b62bca 100644
--- a/media/mca/samples/CameraEffectsRecordingSample/java/android/media/filterfw/samples/CameraEffectsRecordingSample.java
+++ b/media/mca/samples/CameraEffectsRecordingSample/java/android/media/filterfw/samples/CameraEffectsRecordingSample.java
@@ -45,8 +45,8 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
-        mRunButton = (Button) findViewById(R.id.runbutton);
-        mCameraView = (SurfaceView) findViewById(R.id.cameraview);
+        mRunButton = findViewById(R.id.runbutton);
+        mCameraView = findViewById(R.id.cameraview);
         mRunButton.setOnClickListener(mRunButtonClick);
 
         Intent intent = getIntent();
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
index 444705c..ece700d 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
@@ -100,8 +100,8 @@
                 int newState) {
             String intentAction;
             if (newState == BluetoothProfile.STATE_CONNECTED) {
-                Log.i(TAG, "Connected to GATT server.");
-                Log.i(TAG, "Attempting to start service discovery:" +
+                Log.d(TAG, "Connected to GATT server.");
+                Log.d(TAG, "Attempting to start service discovery:" +
                         mBluetoothGatt.discoverServices());
             } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                 Log.i(TAG, "Disconnected from GATT server.");
@@ -112,24 +112,24 @@
         @Override
         public void onServicesDiscovered(BluetoothGatt gatt, int status) {
             if (status == BluetoothGatt.GATT_SUCCESS) {
-                List<BluetoothGattService> services = mBluetoothGatt.getServices();
-                for (BluetoothGattService service : services) {
-                    if (MIDI_SERVICE.equals(service.getUuid())) {
-                        Log.d(TAG, "found MIDI_SERVICE");
-                        List<BluetoothGattCharacteristic> characteristics
-                            = service.getCharacteristics();
-                        for (BluetoothGattCharacteristic characteristic : characteristics) {
-                            if (MIDI_CHARACTERISTIC.equals(characteristic.getUuid())) {
-                                Log.d(TAG, "found MIDI_CHARACTERISTIC");
-                                mCharacteristic = characteristic;
+                BluetoothGattService service = gatt.getService(MIDI_SERVICE);
+                if (service != null) {
+                    Log.d(TAG, "found MIDI_SERVICE");
+                    BluetoothGattCharacteristic characteristic
+                            = service.getCharacteristic(MIDI_CHARACTERISTIC);
+                    if (characteristic != null) {
+                        Log.d(TAG, "found MIDI_CHARACTERISTIC");
+                        mCharacteristic = characteristic;
 
-                                // Specification says to read the characteristic first and then
-                                // switch to receiving notifications
-                                mBluetoothGatt.readCharacteristic(characteristic);
-                                break;
-                            }
-                        }
-                        break;
+                        // Request a lower Connection Interval for better latency.
+                        boolean result = gatt.requestConnectionPriority(
+                                BluetoothGatt.CONNECTION_PRIORITY_HIGH);
+                        Log.d(TAG, "requestConnectionPriority(CONNECTION_PRIORITY_HIGH):"
+                            + result);
+
+                        // Specification says to read the characteristic first and then
+                        // switch to receiving notifications
+                        mBluetoothGatt.readCharacteristic(characteristic);
                     }
                 }
             } else {
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
index 1a10d64..cce2acc 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/BassBoostTest.java
@@ -70,7 +70,7 @@
 
         setContentView(R.layout.bassboosttest);
 
-        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText = findViewById(R.id.sessionEdit);
         mSessionText.setOnKeyListener(mSessionKeyListener);
 
         mSessionText.setText(Integer.toString(sSession));
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
index 594e844..1731dba 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EnvReverbTest.java
@@ -73,9 +73,9 @@
         ToggleButton button;
         setContentView(R.layout.envreverbtest);
 
-        ImageView playPause = (ImageView) findViewById(R.id.playPause1);
-        ImageView stop = (ImageView) findViewById(R.id.stop1);
-        textView = (TextView) findViewById(R.id.sessionText);
+        ImageView playPause = findViewById(R.id.playPause1);
+        ImageView stop = findViewById(R.id.stop1);
+        textView = findViewById(R.id.sessionText);
         if (sPlayerController == null) {
             sPlayerController = new SimplePlayer(this, R.id.playPause1, playPause,
                     R.id.stop1, stop, textView,
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
index f30a26f..fd56956 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/EqualizerTest.java
@@ -72,7 +72,7 @@
 
         setContentView(R.layout.equalizertest);
 
-        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText = findViewById(R.id.sessionEdit);
         mSessionText.setOnKeyListener(mSessionKeyListener);
 
         mSessionText.setText(Integer.toString(sSession));
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
index bb32e6f..4f2180f 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VirtualizerTest.java
@@ -70,7 +70,7 @@
 
         setContentView(R.layout.virtualizertest);
 
-        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText = findViewById(R.id.sessionEdit);
         mSessionText.setOnKeyListener(mSessionKeyListener);
         mSessionText.setText(Integer.toString(sSession));
 
diff --git a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
index 60583e0..7db1d8d 100644
--- a/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
+++ b/media/tests/EffectsTest/src/com/android/effectstest/VisualizerTest.java
@@ -72,7 +72,7 @@
 
         setContentView(R.layout.visualizertest);
 
-        mSessionText = (EditText) findViewById(R.id.sessionEdit);
+        mSessionText = findViewById(R.id.sessionEdit);
         mSessionText.setOnKeyListener(mSessionKeyListener);
         mSessionText.setText(Integer.toString(sSession));
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewActivity.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewActivity.java
index c3dd842..963b20d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewActivity.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/Camera2SurfaceViewActivity.java
@@ -43,7 +43,7 @@
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.surface_view_2);
-        mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
+        mSurfaceView = findViewById(R.id.surface_view);
         mSurfaceView.getHolder().addCallback(this);
 
         //Acquire the full wake lock to keep the device up
diff --git a/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java b/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java
index 0969b10..b0ca0bb7 100644
--- a/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java
+++ b/media/tests/NativeMidiDemo/java/com/example/android/nativemididemo/NativeMidi.java
@@ -269,12 +269,12 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
 
-        mCallbackStatusTextView = (TextView) findViewById(R.id.callback_status);
-        mJavaMidiStatusTextView = (TextView) findViewById(R.id.java_midi_status);
-        mMessagesTextView = (TextView) findViewById(R.id.messages);
-        mMessagesContainer = (TouchableScrollView) findViewById(R.id.messages_scroll);
-        mMidiDevicesRadioGroup = (RadioGroup) findViewById(R.id.devices);
-        RadioButton deviceNone = (RadioButton) findViewById(R.id.device_none);
+        mCallbackStatusTextView = findViewById(R.id.callback_status);
+        mJavaMidiStatusTextView = findViewById(R.id.java_midi_status);
+        mMessagesTextView = findViewById(R.id.messages);
+        mMessagesContainer = findViewById(R.id.messages_scroll);
+        mMidiDevicesRadioGroup = findViewById(R.id.devices);
+        RadioButton deviceNone = findViewById(R.id.device_none);
         deviceNone.setOnClickListener(new MidiOutputPortSelector());
 
         AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
diff --git a/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java b/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java
index 7e21876..8427d16 100644
--- a/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java
+++ b/media/tests/ScoAudioTest/src/com/android/scoaudiotest/ScoAudioTest.java
@@ -97,8 +97,8 @@
         
         setContentView(R.layout.scoaudiotest);
 
-        mScoStateTxt = (TextView) findViewById(R.id.scoStateTxt);
-        mVdStateTxt = (TextView) findViewById(R.id.vdStateTxt);
+        mScoStateTxt = findViewById(R.id.scoStateTxt);
+        mVdStateTxt = findViewById(R.id.vdStateTxt);
 
         IntentFilter intentFilter =
             new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
@@ -112,7 +112,7 @@
         
         mMediaControllers[0] = new SimplePlayerController(this, R.id.playPause1, R.id.stop1,
                 R.raw.sine440_mo_16b_16k, AudioManager.STREAM_BLUETOOTH_SCO);
-        TextView name = (TextView) findViewById(R.id.playPause1Text);
+        TextView name = findViewById(R.id.playPause1Text);
         name.setText("VOICE_CALL stream");
         
         mScoButton = (ToggleButton)findViewById(R.id.ForceScoButton);
@@ -135,7 +135,7 @@
         mTtsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
                 UTTERANCE);
 
-        mSpeakText = (EditText) findViewById(R.id.speakTextEdit);        
+        mSpeakText = findViewById(R.id.speakTextEdit);
         mSpeakText.setOnKeyListener(mSpeakKeyListener);
         mSpeakText.setText("sco audio test sentence");
         mTtsToFileButton = (ToggleButton)findViewById(R.id.TtsToFileButton);
@@ -143,7 +143,7 @@
         mTtsToFile = true;
         mTtsToFileButton.setChecked(mTtsToFile);
 
-        mModeSpinner = (Spinner) findViewById(R.id.modeSpinner);
+        mModeSpinner = findViewById(R.id.modeSpinner);
         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                 android.R.layout.simple_spinner_item, mModeStrings);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -208,12 +208,12 @@
                 mForceScoOn = isChecked;
                 AudioManager mngr = mAudioManager;
                 boolean useVirtualCall = false;
-                CheckBox box = (CheckBox) findViewById(R.id.useSecondAudioManager);
+                CheckBox box = findViewById(R.id.useSecondAudioManager);
                 if (box.isChecked()) {
                     Log.i(TAG, "Using 2nd audio manager");
                     mngr = mAudioManager2;
                 }
-                box = (CheckBox) findViewById(R.id.useVirtualCallCheckBox);
+                box = findViewById(R.id.useVirtualCallCheckBox);
                 useVirtualCall = box.isChecked();
 
                 if (mForceScoOn) {
@@ -278,8 +278,8 @@
             mPlayPauseButtonId = playPausebuttonId;
             mStopButtonId = stopButtonId;
             mFileNameBase = fileName;
-            mPlayPauseButton = (ImageButton) findViewById(playPausebuttonId);
-            ImageButton stop = (ImageButton) findViewById(stopButtonId);
+            mPlayPauseButton = findViewById(playPausebuttonId);
+            ImageButton stop = findViewById(stopButtonId);
 
             mPlayPauseButton.setOnClickListener(this);
             mPlayPauseButton.requestFocus();
@@ -294,8 +294,8 @@
             mStopButtonId = stopButtonId;
             mFileNameBase = "";
             mFileResId = fileResId;
-            mPlayPauseButton = (ImageButton) findViewById(playPausebuttonId);
-            ImageButton stop = (ImageButton) findViewById(stopButtonId);
+            mPlayPauseButton = findViewById(playPausebuttonId);
+            ImageButton stop = findViewById(stopButtonId);
 
             mPlayPauseButton.setOnClickListener(this);
             mPlayPauseButton.requestFocus();
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index ae16949..8e58210 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "sensor"
 #include <utils/Log.h>
 
-#include <android/hardware_buffer.h>
 #include <android/looper.h>
 #include <android/sensor.h>
 #include <android/sharedmem.h>
@@ -28,6 +27,7 @@
 #include <utils/Looper.h>
 #include <utils/RefBase.h>
 #include <utils/Timers.h>
+#include <vndk/hardware_buffer.h>
 
 #include <poll.h>
 
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index 7fa5736..9fa7a664 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -173,13 +173,13 @@
         setContentView(layoutId);
 
         // Same resource IDs for each layout variant (backup / restore)
-        mStatusView = (TextView) findViewById(R.id.package_name);
-        mAllowButton = (Button) findViewById(R.id.button_allow);
-        mDenyButton = (Button) findViewById(R.id.button_deny);
+        mStatusView = findViewById(R.id.package_name);
+        mAllowButton = findViewById(R.id.button_allow);
+        mDenyButton = findViewById(R.id.button_deny);
 
-        mCurPassword = (TextView) findViewById(R.id.password);
-        mEncPassword = (TextView) findViewById(R.id.enc_password);
-        TextView curPwDesc = (TextView) findViewById(R.id.password_desc);
+        mCurPassword = findViewById(R.id.password);
+        mEncPassword = findViewById(R.id.enc_password);
+        TextView curPwDesc = findViewById(R.id.password_desc);
 
         mAllowButton.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -214,7 +214,7 @@
             curPwDesc.setVisibility(View.GONE);
             mCurPassword.setVisibility(View.GONE);
             if (layoutId == R.layout.confirm_backup) {
-                TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
+                TextView encPwDesc = findViewById(R.id.enc_password_desc);
                 if (mIsEncrypted) {
                     encPwDesc.setText(R.string.backup_enc_password_required);
                     monitorEncryptionPassword();
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 6394c64..5d20cf3 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -117,7 +117,7 @@
         }
         mCm.registerNetworkCallback(builder.build(), mNetworkCallback);
 
-        final WebView myWebView = (WebView) findViewById(R.id.webview);
+        final WebView myWebView = findViewById(R.id.webview);
         myWebView.clearCache(true);
         WebSettings webSettings = myWebView.getSettings();
         webSettings.setJavaScriptEnabled(true);
@@ -184,7 +184,7 @@
 
     @Override
     public void onBackPressed() {
-        WebView myWebView = (WebView) findViewById(R.id.webview);
+        WebView myWebView = findViewById(R.id.webview);
         if (myWebView.canGoBack() && mWebViewClient.allowBack()) {
             myWebView.goBack();
         } else {
@@ -326,7 +326,7 @@
             // For internally generated pages, leave URL bar listing prior URL as this is the URL
             // the page refers to.
             if (!url.startsWith(INTERNAL_ASSETS)) {
-                final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
+                final TextView myUrlBar = findViewById(R.id.url_bar);
                 myUrlBar.setText(url);
             }
             testForCaptivePortal();
@@ -407,7 +407,7 @@
     private class MyWebChromeClient extends WebChromeClient {
         @Override
         public void onProgressChanged(WebView view, int newProgress) {
-            final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+            final ProgressBar myProgressBar = findViewById(R.id.progress_bar);
             myProgressBar.setProgress(newProgress);
         }
     }
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index a5820f2..6276ce3 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -91,7 +91,7 @@
         setContentView(R.layout.activity_captive_portal_login);
         getActionBar().setDisplayShowHomeEnabled(false);
 
-        mWebView = (WebView) findViewById(R.id.webview);
+        mWebView = findViewById(R.id.webview);
         mWebView.clearCache(true);
         WebSettings webSettings = mWebView.getSettings();
         webSettings.setJavaScriptEnabled(true);
@@ -113,7 +113,7 @@
 
     @Override
     public void onBackPressed() {
-        WebView myWebView = (WebView) findViewById(R.id.webview);
+        WebView myWebView = findViewById(R.id.webview);
         if (myWebView.canGoBack() && mWebViewClient.allowBack()) {
             myWebView.goBack();
         } else {
@@ -328,7 +328,7 @@
             // For internally generated pages, leave URL bar listing prior URL as this is the URL
             // the page refers to.
             if (!url.startsWith(INTERNAL_ASSETS)) {
-                final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
+                final TextView myUrlBar = findViewById(R.id.url_bar);
                 myUrlBar.setText(url);
             }
             if (mNetwork != null) {
@@ -412,7 +412,7 @@
     private class MyWebChromeClient extends WebChromeClient {
         @Override
         public void onProgressChanged(WebView view, int newProgress) {
-            final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+            final ProgressBar myProgressBar = findViewById(R.id.progress_bar);
             myProgressBar.setProgress(newProgress);
         }
     }
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 316ea8a..b145290 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -66,7 +66,7 @@
         } else {
             setContentView(R.layout.device_chooser);
             setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0));
-            mDeviceListView = (ListView) findViewById(R.id.device_list);
+            mDeviceListView = findViewById(R.id.device_list);
             final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
             mDeviceListView.setAdapter(adapter);
             adapter.registerDataSetObserver(new DataSetObserver() {
@@ -115,7 +115,7 @@
 
     @Override
     public void setTitle(CharSequence title) {
-        final TextView titleView = (TextView) findViewById(R.id.title);
+        final TextView titleView = findViewById(R.id.title);
         final int padding = getPadding(getResources());
         titleView.setPadding(padding, padding, padding, padding);
         titleView.setText(title);
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index 246bd2b..5beb412 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -314,8 +314,8 @@
     }
 
     class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> {
-        //TODO wifi icon
         private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
+        private Drawable WIFI_ICON = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
 
         private Drawable icon(int drawableRes) {
             Drawable icon = getResources().getDrawable(drawableRes, null);
@@ -345,6 +345,11 @@
                     device.equals(mSelectedDevice)
                             ? Color.GRAY
                             : Color.TRANSPARENT);
+            textView.setCompoundDrawablesWithIntrinsicBounds(
+                    device.device instanceof android.net.wifi.ScanResult
+                        ? WIFI_ICON
+                        : BLUETOOTH_ICON,
+                    null, null, null);
             textView.setOnClickListener((view) -> {
                 mSelectedDevice = device;
                 notifyDataSetChanged();
@@ -357,8 +362,6 @@
             textView.setTextColor(Color.BLACK);
             final int padding = DeviceChooserActivity.getPadding(getResources());
             textView.setPadding(padding, padding, padding, padding);
-            textView.setCompoundDrawablesWithIntrinsicBounds(
-                    BLUETOOTH_ICON, null, null, null);
             textView.setCompoundDrawablePadding(padding);
             return textView;
         }
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index 55d000c..e399fb17 100644
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -1,5 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.defcontainer" coreApp="true">
+    <uses-permission android:name="android.permission.ALLOCATE_AGGRESSIVE"/>
     <uses-permission android:name="android.permission.ASEC_ACCESS"/>
     <uses-permission android:name="android.permission.ASEC_CREATE"/>
     <uses-permission android:name="android.permission.ASEC_DESTROY"/>
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 37a68e0..9347877 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.res.ObbInfo;
 import android.content.res.ObbScanner;
+import android.os.Binder;
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
@@ -179,6 +180,15 @@
                 return ret;
             }
 
+            final int recommendedInstallLocation;
+            final long token = Binder.clearCallingIdentity();
+            try {
+                recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
+                        pkg.packageName, pkg.installLocation, sizeBytes, flags);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+
             ret.packageName = pkg.packageName;
             ret.splitNames = pkg.splitNames;
             ret.versionCode = pkg.versionCode;
@@ -186,8 +196,7 @@
             ret.splitRevisionCodes = pkg.splitRevisionCodes;
             ret.installLocation = pkg.installLocation;
             ret.verifiers = pkg.verifiers;
-            ret.recommendedInstallLocation = PackageHelper.resolveInstallLocation(context,
-                    pkg.packageName, pkg.installLocation, sizeBytes, flags);
+            ret.recommendedInstallLocation = recommendedInstallLocation;
             ret.multiArch = pkg.multiArch;
 
             return ret;
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
index f59f0d9..689e381 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
@@ -82,7 +82,7 @@
 
         mPrefs = new PrefState(this);
         mPrefs.setListener(this);
-        final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.holder);
+        final RecyclerView recyclerView = findViewById(R.id.holder);
         mAdapter = new CatAdapter();
         recyclerView.setAdapter(mAdapter);
         recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
diff --git a/packages/Osu/src/com/android/hotspot2/app/MainActivity.java b/packages/Osu/src/com/android/hotspot2/app/MainActivity.java
index ae0a45c..7fd2238 100644
--- a/packages/Osu/src/com/android/hotspot2/app/MainActivity.java
+++ b/packages/Osu/src/com/android/hotspot2/app/MainActivity.java
@@ -123,7 +123,7 @@
         if (osuData.size() > 0) {
             noOsuView.setVisibility(View.GONE);
             osuListAdapter = new OsuListAdapter(this, osuData);
-            osuListView = (ListView) findViewById(R.id.profile_list);
+            osuListView = findViewById(R.id.profile_list);
             osuListView.setAdapter(osuListAdapter);
             osuListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                 @Override
diff --git a/packages/Osu/src/com/android/hotspot2/osu/OSUWebView.java b/packages/Osu/src/com/android/hotspot2/osu/OSUWebView.java
index afbd0d1..a6778c8 100644
--- a/packages/Osu/src/com/android/hotspot2/osu/OSUWebView.java
+++ b/packages/Osu/src/com/android/hotspot2/osu/OSUWebView.java
@@ -37,7 +37,7 @@
         setContentView(R.layout.osu_web_view);
         getActionBar().setDisplayShowHomeEnabled(false);
 
-        final WebView myWebView = (WebView) findViewById(R.id.webview);
+        final WebView myWebView = findViewById(R.id.webview);
         myWebView.clearCache(true);
         WebSettings webSettings = myWebView.getSettings();
         webSettings.setJavaScriptEnabled(true);
diff --git a/packages/PrintSpooler/res/values-km/strings.xml b/packages/PrintSpooler/res/values-km/strings.xml
index 2bc7baa..4409856 100644
--- a/packages/PrintSpooler/res/values-km/strings.xml
+++ b/packages/PrintSpooler/res/values-km/strings.xml
@@ -61,8 +61,8 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ព័ត៌មានបន្ថែមអំពីម៉ាស៊ីបោះពុម្ពនេះ"</string>
-    <string name="notification_channel_progress" msgid="872788690775721436">"កំពុង​ដំណើរការ​កិច្ចការ​បោះពុម្ព"</string>
-    <string name="notification_channel_failure" msgid="9042250774797916414">"មិនអាច​ដំណើរការ​កិច្ចការ​បោះពុម្ព​បាន​ទេ"</string>
+    <string name="notification_channel_progress" msgid="872788690775721436">"កំពុង​បោះពុម្ព"</string>
+    <string name="notification_channel_failure" msgid="9042250774797916414">"មិនអាច​បោះពុម្ព​បាន​"</string>
     <string name="could_not_create_file" msgid="3425025039427448443">"មិនអាចបង្កើតឯកសារបានទេ"</string>
     <string name="print_services_disabled_toast" msgid="9089060734685174685">"សេវាកម្មបោះពុម្ពមួយចំនួនត្រូវបានបិទដំណើរការ"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"ស្វែងរក​ម៉ាស៊ីន​បោះពុម្ព"</string>
diff --git a/packages/PrintSpooler/res/values-pa/strings.xml b/packages/PrintSpooler/res/values-pa/strings.xml
index 6fd021b..d7885ad 100644
--- a/packages/PrintSpooler/res/values-pa/strings.xml
+++ b/packages/PrintSpooler/res/values-pa/strings.xml
@@ -61,8 +61,8 @@
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="printer_info_desc" msgid="7181988788991581654">"ਇਸ ਪ੍ਰਿੰਟਰ ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ"</string>
-    <string name="notification_channel_progress" msgid="872788690775721436">"ਚੱਲ ਰਹੇ ਪ੍ਰਿੰਟ ਕੰਮ"</string>
-    <string name="notification_channel_failure" msgid="9042250774797916414">"ਪ੍ਰਿੰਟ ਦੇ ਕੰਮ ਅਸਫਲ ਰਹੇ"</string>
+    <string name="notification_channel_progress" msgid="872788690775721436">"ਚੱਲ ਰਹੇ ਪ੍ਰਿੰਟ ਕਾਰਜ"</string>
+    <string name="notification_channel_failure" msgid="9042250774797916414">"ਅਸਫਲ ਰਹੇ ਪ੍ਰਿੰਟ ਕਾਰਜ"</string>
     <string name="could_not_create_file" msgid="3425025039427448443">"ਫ਼ਾਈਲ ਨੂੰ ਬਣਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ"</string>
     <string name="print_services_disabled_toast" msgid="9089060734685174685">"ਕੁਝ ਪ੍ਰਿੰਟ ਸੇਵਾਵਾਂ ਅਯੋਗ ਬਣਾਈਆਂ ਗਈਆਂ ਹਨ"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"ਪ੍ਰਿੰਟਰ ਖੋਜ ਰਿਹਾ ਹੈ"</string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 4cce166..ccdec62 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -1290,11 +1290,11 @@
     private void bindUi() {
         // Summary
         mSummaryContainer = findViewById(R.id.summary_content);
-        mSummaryCopies = (TextView) findViewById(R.id.copies_count_summary);
-        mSummaryPaperSize = (TextView) findViewById(R.id.paper_size_summary);
+        mSummaryCopies = findViewById(R.id.copies_count_summary);
+        mSummaryPaperSize = findViewById(R.id.paper_size_summary);
 
         // Options container
-        mOptionsContent = (PrintContentView) findViewById(R.id.options_content);
+        mOptionsContent = findViewById(R.id.options_content);
         mOptionsContent.setOptionsStateChangeListener(this);
         mOptionsContent.setOpenOptionsController(this);
 
@@ -1302,7 +1302,7 @@
         OnClickListener clickListener = new MyClickListener();
 
         // Copies
-        mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
+        mCopiesEditText = findViewById(R.id.copies_edittext);
         mCopiesEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
         mCopiesEditText.setText(MIN_COPIES_STRING);
         mCopiesEditText.setSelection(mCopiesEditText.getText().length());
@@ -1311,28 +1311,28 @@
         // Destination.
         mPrintersObserver = new PrintersObserver();
         mDestinationSpinnerAdapter.registerDataSetObserver(mPrintersObserver);
-        mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
+        mDestinationSpinner = findViewById(R.id.destination_spinner);
         mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
         mDestinationSpinner.setOnItemSelectedListener(itemSelectedListener);
 
         // Media size.
         mMediaSizeSpinnerAdapter = new ArrayAdapter<>(
                 this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
-        mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
+        mMediaSizeSpinner = findViewById(R.id.paper_size_spinner);
         mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
         mMediaSizeSpinner.setOnItemSelectedListener(itemSelectedListener);
 
         // Color mode.
         mColorModeSpinnerAdapter = new ArrayAdapter<>(
                 this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
-        mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
+        mColorModeSpinner = findViewById(R.id.color_spinner);
         mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
         mColorModeSpinner.setOnItemSelectedListener(itemSelectedListener);
 
         // Duplex mode.
         mDuplexModeSpinnerAdapter = new ArrayAdapter<>(
                 this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
-        mDuplexModeSpinner = (Spinner) findViewById(R.id.duplex_spinner);
+        mDuplexModeSpinner = findViewById(R.id.duplex_spinner);
         mDuplexModeSpinner.setAdapter(mDuplexModeSpinnerAdapter);
         mDuplexModeSpinner.setOnItemSelectedListener(itemSelectedListener);
 
@@ -1345,32 +1345,32 @@
                 ORIENTATION_PORTRAIT, orientationLabels[0]));
         mOrientationSpinnerAdapter.add(new SpinnerItem<>(
                 ORIENTATION_LANDSCAPE, orientationLabels[1]));
-        mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
+        mOrientationSpinner = findViewById(R.id.orientation_spinner);
         mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
         mOrientationSpinner.setOnItemSelectedListener(itemSelectedListener);
 
         // Range options
         ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter = new ArrayAdapter<>(
                 this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
-        mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
+        mRangeOptionsSpinner = findViewById(R.id.range_options_spinner);
         mRangeOptionsSpinner.setAdapter(rangeOptionsSpinnerAdapter);
         mRangeOptionsSpinner.setOnItemSelectedListener(itemSelectedListener);
         updatePageRangeOptions(PrintDocumentInfo.PAGE_COUNT_UNKNOWN);
 
         // Page range
-        mPageRangeTitle = (TextView) findViewById(R.id.page_range_title);
-        mPageRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
+        mPageRangeTitle = findViewById(R.id.page_range_title);
+        mPageRangeEditText = findViewById(R.id.page_range_edittext);
         mPageRangeEditText.setVisibility(View.GONE);
         mPageRangeTitle.setVisibility(View.GONE);
         mPageRangeEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
         mPageRangeEditText.addTextChangedListener(new RangeTextWatcher());
 
         // Advanced options button.
-        mMoreOptionsButton = (Button) findViewById(R.id.more_options_button);
+        mMoreOptionsButton = findViewById(R.id.more_options_button);
         mMoreOptionsButton.setOnClickListener(clickListener);
 
         // Print button
-        mPrintButton = (ImageView) findViewById(R.id.print_button);
+        mPrintButton = findViewById(R.id.print_button);
         mPrintButton.setOnClickListener(clickListener);
 
         // The UI is now initialized
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
index 6f0caa2..a9a6cbd 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/SelectPrinterActivity.java
@@ -134,7 +134,7 @@
                 LOADER_ID_PRINT_REGISTRY_INT);
 
         // Hook up the list view.
-        mListView = (ListView) findViewById(android.R.id.list);
+        mListView = findViewById(android.R.id.list);
         final DestinationAdapter adapter = new DestinationAdapter();
         adapter.registerDataSetObserver(new DataSetObserver() {
             @Override
@@ -411,7 +411,7 @@
             View emptyView = findViewById(R.id.empty_print_state);
             mListView.setEmptyView(emptyView);
         }
-        TextView titleView = (TextView) findViewById(R.id.title);
+        TextView titleView = findViewById(R.id.title);
         View progressBar = findViewById(R.id.progress_bar);
         if (mEnabledPrintServices.size() == 0) {
             titleView.setText(R.string.print_no_print_services);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index 0bb4bfa..8b00ed0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -136,12 +136,12 @@
     @Override
     protected void onFinishInflate() {
         mStaticContent = findViewById(R.id.static_content);
-        mSummaryContent = (ViewGroup) findViewById(R.id.summary_content);
+        mSummaryContent = findViewById(R.id.summary_content);
         mDynamicContent = findViewById(R.id.dynamic_content);
         mDraggableContent = findViewById(R.id.draggable_content);
         mPrintButton = findViewById(R.id.print_button);
         mMoreOptionsButton = findViewById(R.id.more_options_button);
-        mOptionsContainer = (ViewGroup) findViewById(R.id.options_container);
+        mOptionsContainer = findViewById(R.id.options_container);
         mEmbeddedContentContainer = findViewById(R.id.embedded_content_container);
         mEmbeddedContentScrim = findViewById(R.id.embedded_content_scrim);
         mExpandCollapseHandle = findViewById(R.id.expand_collapse_handle);
diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml
index e9c175f..55c192d 100644
--- a/packages/SettingsLib/res/layout/settings_with_drawer.xml
+++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml
@@ -25,17 +25,13 @@
         android:layout_height="match_parent"
         android:orientation="vertical"
         android:fitsSystemWindows="true">
-        <FrameLayout
+        <Toolbar
+            android:id="@+id/action_bar"
             style="?android:attr/actionBarStyle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:theme="?android:attr/actionBarTheme">
-            <Toolbar
-                android:id="@+id/action_bar"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:navigationContentDescription="@*android:string/action_bar_up_description"/>
-        </FrameLayout>
+            android:theme="?android:attr/actionBarTheme"
+            android:navigationContentDescription="@*android:string/action_bar_up_description"/>
         <FrameLayout
             android:id="@+id/content_header_container"
             style="?android:attr/actionBarStyle"
diff --git a/packages/SettingsLib/res/layout/usage_view.xml b/packages/SettingsLib/res/layout/usage_view.xml
index 1d56668..151d1ee 100644
--- a/packages/SettingsLib/res/layout/usage_view.xml
+++ b/packages/SettingsLib/res/layout/usage_view.xml
@@ -76,17 +76,23 @@
             android:id="@+id/bottom_label_space"
             android:layout_width="@dimen/usage_graph_labels_width"
             android:layout_height="wrap_content"/>
-        <include android:id="@+id/label_start"
-            layout="@layout/usage_side_label" />
-
-        <Space
+        <LinearLayout
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:layout_weight="1" />
+            android:layout_weight="1"
+            android:orientation="horizontal"
+            android:layoutDirection="ltr">
+            <include android:id="@+id/label_start"
+                     layout="@layout/usage_side_label" />
 
-        <include android:id="@+id/label_end"
-            layout="@layout/usage_side_label" />
+            <Space
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1" />
 
+            <include android:id="@+id/label_end"
+                     layout="@layout/usage_side_label" />
+        </LinearLayout>
     </LinearLayout>
 
 </LinearLayout>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 98ad04f..4b3fab6 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Laat altyd Wi-Fi-swerfskanderings toe"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data is altyd aktief"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Deaktiveer absolute volume"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-weergawe"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Kies Bluetooth AVRCP-weergawe"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-oudiokodek"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifieer programme oor USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontroleer programme wat via ADB/ADT geïnstalleer is vir skadelike gedrag."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiveer die Bluetooth-kenmerk vir absolute volume indien daar volumeprobleme met afgeleë toestelle is, soos onaanvaarbare harde klank of geen beheer nie."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Plaaslike terminaal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Aktiveer terminaalprogram wat plaaslike skermtoegang bied"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontrolering"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 5526835..e879871 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ሁልጊዜ የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"የተንቀሳቃሽ ስልክ ውሂብ ሁልጊዜ ገቢር ነው"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ፍጹማዊ ድምፅን አሰናክል"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"የብሉቱዝ AVRCP ስሪት"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"የብሉቱዝ AVRCP ስሪት ይምረጡ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"የብሉቱዝ ኦዲዮ ኮዴክ"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"መተግበሪያዎች በUSB በኩል ያረጋግጡ"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"በADB/ADT በኩል የተጫኑ መተግበሪያዎች ጎጂ ባህሪ ካላቸው ያረጋግጡ።"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"እንደ ተቀባይነት በሌለው ደረጃ ድምፁ ከፍ ማለት ወይም መቆጣጠር አለመቻል ያሉ ከሩቅ መሣሪያዎች ጋር የድምፅ ችግር በሚኖርበት ጊዜ የብሉቱዝ ፍጹማዊ ድምፅን ባሕሪ ያሰናክላል።"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"አካባቢያዊ ተርሚናል"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"የአካባቢያዊ ሼል መዳረሻ የሚያቀርብ የተርሚናል መተግበሪያ አንቃ"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"የHDCP ምልከታ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 361c872..817d25d 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏السماح دائمًا بعمليات فحص Wi-Fi للتجوال"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"بيانات الجوّال نشطة دائمًا"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"تعطيل مستوى الصوت المطلق"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"‏إصدار Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"‏اختيار إصدار Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ترميز صوت بلوتوث"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"‏التحقق من التطبيقات عبر USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"‏التحقق من التطبيقات المثبتة عبر ADB/ADT لكشف السلوك الضار"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"لتعطيل ميزة مستوى الصوت المطلق للبلوتوث في حالة حدوث مشكلات متعلقة بمستوى الصوت مع الأجهزة البعيدة مثل مستوى صوت عالٍ بشكل غير مقبول أو نقص إمكانية التحكم في الصوت."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"تطبيق طرفي محلي"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"تمكين تطبيق طرفي يوفر إمكانية الدخول إلى واجهة النظام المحلية"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"‏التحقق من HDCP"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index debc97b..ff7d1dd 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi axtarışlarına həmişə icazə verin"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil data həmişə aktiv"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Mütləq səs həcmi deaktiv edin"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Versiya"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP Versiyasını seçin"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Kodek"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB üzərindən tətbiqləri yoxlayın"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT vasitəsi ilə quraşdırılmış tətbiqləri zərərli davranış üzrə yoxlayın."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Uzaqdan idarə olunan cihazlarda dözülməz yüksək səs həcmi və ya nəzarət çatışmazlığı kimi səs problemləri olduqda Bluetooth mütləq səs həcmi xüsusiyyətini deaktiv edir."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Yerli terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Yerli örtük girişini təklif edən terminal tətbiqi aktiv edin"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP yoxlanılır"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 94c3907..445afd3 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -125,7 +125,7 @@
     <string name="tts_engine_settings_title" msgid="3499112142425680334">"Podešavanja za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
     <string name="tts_engine_settings_button" msgid="1030512042040722285">"Pokreni podešavanja mašine"</string>
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Željena mašina"</string>
-    <string name="tts_general_section_title" msgid="4402572014604490502">"Opšte"</string>
+    <string name="tts_general_section_title" msgid="4402572014604490502">"Opšta"</string>
     <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Resetujte visinu tona govora"</string>
     <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Resetujte visinu tona kojom se tekst izgovara na podrazumevanu."</string>
   <string-array name="tts_rate_entries">
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvek dozvoli skeniranje Wi‑Fi-ja u romingu"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci su uvek aktivni"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući glavno podešavanje jačine zvuka"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzija Bluetooth AVRCP-a"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Izaberite verziju Bluetooth AVRCP-a"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodek"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifikuj aplikacije preko USB-a"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Proverava da li su aplikacije instalirane preko ADB-a/ADT-a štetne."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućava glavno podešavanje jačine zvuka na Bluetooth uređaju u slučaju problema sa jačinom zvuka na daljinskim uređajima, kao što su izuzetno velika jačina zvuka ili nedostatak kontrole."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Omogući aplik. terminala za pristup lokalnom komandnom okruženju"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP provera"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index f340232..ab70274 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Заўсёды дазваляць роўмінгавае сканіраванне Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мабільная перадача даных заўсёды актыўная"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Адключыць абсалютны гук"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версія Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Выбраць версію Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодэк Bluetooth Audio"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Праверце прыкладаннi па USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Праверце прыкладаннi, усталяваныя з дапамогай ADB/ADT, на нестабiльныя паводзiны."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Адключыць функцыю абсалютнага гуку Bluetooth у выпадку праблем з гукам на аддаленых прыладах, напр., пры непрымальна высокай гучнасці або адсутнасці кіравання."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Лакальны тэрмінал"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Уключэнне прыкладання тэрмінала, якое прапануе доступ да лакальнай абалонкі"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Праверка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index acc0ce0..82fcf60 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Сканирането за роуминг на Wi-Fi да е разрешено винаги"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Винаги активни мобилни данни"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Деактивиране на пълната сила на звука"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версия на AVRCP за Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Избиране на версия на AVRCP за Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Аудиокодек за Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Потвържд. на прил. през USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Проверка на инсталираните чрез ADB/ADT приложения за опасно поведение."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Деактивира функцията на Bluetooth за пълна сила на звука в случай на проблеми със звука на отдалечени устройства, като например неприемливо висока сила на звука или липса на управление."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Локален терминал"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Актив. на прил. за терминал с достъп до локалния команден ред"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Проверка с HDCP"</string>
@@ -316,7 +320,7 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Корекция на цветове"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Тази функция е експериментална и може да се отрази на ефективността."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Оставащо време: Около <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Оставащо време: около <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Оставащо време: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> – около <xliff:g id="TIME">%2$s</xliff:g> оставащо време"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index e638982..23ab924 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"সর্বদা Wifi রোম স্ক্যানকে অনুমতি দিন"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"চূড়ান্ত ভলিউম অক্ষম করুন"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ব্লুটুথ AVRCP সংস্করণ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ব্লুটুথ AVRCP সংস্করণ বেছে নিন"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ব্লুটুথ অডিও কোডেক"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB এর অ্যাপ্লিকেশানগুলি যাচাই করুন"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ক্ষতিকারক ক্রিয়াকলাপ করছে কিনা তার জন্য ADB/ADT মারফত ইনস্টল করা অ্যাপ্লিকেশানগুলি চেক করুন।"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"অপ্রত্যাশিত উচ্চ ভলিউম বা নিয়ন্ত্রণের অভাবের মত দূরবর্তী ডিভাইসের ভলিউম সমস্যাগুলির ক্ষেত্রে, ব্লুটুথ চুড়ান্ত ভলিউম বৈশিষ্ট্য অক্ষম করে৷"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"স্থানীয় টার্মিনাল"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"স্থানীয় শেল অ্যাক্সেসের প্রস্তাব করে এমন টার্মিনাল অ্যাপ্লিকেশন সক্ষম করুন"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP পরীক্ষণ"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 6a41f74..fccf084 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogućite apsolutnu jačinu zvuka"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP verzija"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Odaberite Bluetooth AVRCP verziju"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio kodek"</string>
@@ -209,6 +211,8 @@
     <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="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućava opciju Bluetooth apsolutne jačine zvuka u slučaju problema s jačinom zvuka na udaljenim uređajima, kao što je neprihvatljivo glasan zvuk ili nedostatak kontrole."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <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>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 6ecde2e..23b1da7 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permet sempre cerca de Wi-Fi en ininerància"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dades mòbils sempre actives"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactiva el volum absolut"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versió AVRCP de Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versió AVRCP de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Còdec d\'àudio per Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifica aplicacions per USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprova les aplicacions instal·lades mitjançant ADB/ADT per detectar possibles comportaments perillosos"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desactiva la funció de volum absolut de Bluetooth en cas que es produeixin problemes de volum amb dispositius remots, com ara un volum massa alt o una manca de control."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Activa l\'aplicació de terminal que ofereix accés al shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Comprovació HDCP"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 98d3d61..987d238 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povolit Wi-Fi roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilní data jsou vždy aktivní"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázat absolutní hlasitost"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verze profilu Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Vyberte verzi profilu Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio – kodek"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Ověřit aplikace z USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolovat škodlivost aplikací nainstalovaných pomocí nástroje ADB/ADT"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Zakáže funkci absolutní hlasitosti Bluetooth. Zabrání tak problémům s hlasitostí vzdálených zařízení (jako je příliš vysoká hlasitost nebo nemožnost ovládání)."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Místní terminál"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Aktivovat terminálovou aplikaci pro místní přístup k prostředí shell"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Kontrola HDCP"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index de2a6e6..00881b7 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillad altid scanning af Wi-Fi-roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er altid aktiveret"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Deaktiver absolut lydstyrke"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"AVRCP-version for Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Vælg AVRCP-version for Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-lydcodec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificer apps via USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollér apps, der er installeret via ADB/ADT, for skadelig adfærd."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiverer funktionen til absolut lydstyrke via Bluetooth i tilfælde af problemer med lydstyrken på eksterne enheder, f.eks. uacceptabel høj lyd eller manglende kontrol."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Aktivér terminalappen, der giver lokal shell-adgang"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontrol"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index c3f3690..2cf142b 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"WLAN-Roamingsuchen immer zulassen"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile Datennutzung immer aktiviert"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Maximallautstärke deaktivieren"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-Version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP-Version auswählen"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-Audio-Codec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Apps über USB bestätigen"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Überprüft installierte Apps über ADB/ADT auf schädliches Verhalten"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Deaktiviert die Bluetooth-Maximallautstärkefunktion, falls auf Remote-Geräten Probleme mit der Lautstärke auftreten, wie beispielsweise übermäßig laute Wiedergabe oder fehlende Kontrolle bei der Steuerung."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokales Terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Terminal-App mit Zugriff auf lokale Shell aktivieren"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-Prüfung"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 3af71256..09381a4 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Να επιτρέπεται πάντα η σάρωση Wi-Fi κατά την περιαγωγή"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Πάντα ενεργά δεδομένα κινητής τηλεφωνίας"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Απενεργοποίηση απόλυτης έντασης"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Έκδοση AVRCP Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Επιλογή έκδοσης AVRCP Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Κωδικοποιητής ήχου Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Επαλήθευση εφαρμογών μέσω USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Έλεγχος εφαρμογών που έχουν εγκατασταθεί μέσω ADB/ADT για επιβλαβή συμπεριφορά."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Απενεργοποιεί τη δυνατότητα απόλυτης έντασης του Bluetooth σε περίπτωση προβλημάτων έντασης με απομακρυσμένες συσκευές, όπως όταν υπάρχει μη αποδεκτά υψηλή ένταση ή απουσία ελέγχου."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Τοπική τερματική εφαρμογή"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Ενεργοπ.τερμ.εφαρμογής που προσφέρει πρόσβαση στο τοπικό κέλυφος"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Έλεγχος HDCP"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 65bf3d8..2e6dc05 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verify apps over USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 65bf3d8..2e6dc05 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verify apps over USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 65bf3d8..2e6dc05 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disable absolute volume"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Version"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Select Bluetooth AVRCP Version"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verify apps over USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Check apps installed via ADB/ADT for harmful behaviour."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Disables the Bluetooth absolute volume feature in case of volume issues with remote devices such as unacceptably loud volume or lack of control."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Local terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Enable terminal app that offers local shell access"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP checking"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index d003ff2..be646f7 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activados"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión de AVRCP del Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versión de AVRCP del Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec del audio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicaciones por USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprobar que las aplicaciones instaladas mediante ADB/ADT no ocasionen daños"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Habilitar aplicac. de terminal que ofrece acceso al shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Comprobación HDCP"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index dd7c729..ea7a030 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activos"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP del Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona la versión AVRCP del Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio por Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicaciones por USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprueba las aplicaciones instaladas mediante ADB/ADT para detectar comportamientos dañinos"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inhabilita la función de volumen absoluto de Bluetooth si se producen problemas de volumen con dispositivos remotos (por ejemplo, volumen demasiado alto o falta de control)."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Habilitar aplicación de terminal que ofrece acceso a shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Comprobación de HDCP"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index b69c55a1..7229197 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luba alati WiFi-rändluse skannimine"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilne andmeside on alati aktiivne"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Keela absoluutne helitugevus"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetoothi AVRCP versioon"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Valige Bluetoothi AVRCP versioon"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetoothi heli kodek"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Kinnita rakendus USB kaudu"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolli, kas ADB/ADT-ga installitud rakendused on ohtlikud."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Keelatakse Bluetoothi absoluutse helitugevuse funktsioon, kui kaugseadmetega on helitugevuse probleeme (nt liiga vali heli või juhitavuse puudumine)."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Kohalik terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Luba kohalikku turvalist juurdepääsu pakkuv terminalirakendus"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontrollimine"</string>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 2b762dfa..444ffbc 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -246,7 +246,7 @@
   </string-array>
   <string-array name="usb_configuration_titles">
     <item msgid="488237561639712799">"Kargatzen"</item>
-    <item msgid="5220695614993094977">"MTP (multimedia-elementuak transferitzeko protokoloa)"</item>
+    <item msgid="5220695614993094977">"MTP (multimedia-edukia transferitzeko protokoloa)"</item>
     <item msgid="2086000968159047375">"PTP (irudiak transferitzeko protokoloa)"</item>
     <item msgid="7398830860950841822">"RNDIS (USB bidezko Ethernet konexioa)"</item>
     <item msgid="1718924214939774352">"Audio-iturburua"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 2f92ecd..c98f8ac 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Onartu beti ibiltaritzan Wi-Fi sareak bilatzea"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Datu mugikorrak beti aktibo"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desgaitu bolumen absolutua"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP bertsioa"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Hautatu Bluetooth AVRCP bertsioa"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth bidezko audioaren kodeka"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Egiaztatu USBko aplikazioak."</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Egiaztatu ADB/ADT bidez instalatutako aplikazioak portaera kaltegarriak antzemateko."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desgaitu egiten du Bluetooth bidezko bolumen absolutuaren eginbidea urruneko gailuetan arazoak hautematen badira; esaterako, bolumena ozenegia bada edo ezin bada kontrolatu."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Tokiko terminala"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Gaitu tokiko shell-sarbidea duen terminal-aplikazioa"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP egiaztapena"</string>
@@ -317,7 +321,7 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Eginbidea esperimentala da eta eragina izan dezake funtzionamenduan."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"<xliff:g id="TIME">%1$s</xliff:g> inguru gelditzen dira"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g> gelditzen dira guztiz kargatu arte"</string>
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
     <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen dira"</string>
     <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 89ac8c5..0278d01 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏اسکن‌های رومینگ Wi‑Fi همیشه مجاز است"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"داده تلفن همراه همیشه فعال باشد"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"غیرفعال کردن میزان صدای مطلق"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"‏نسخه AVRCP بلوتوث"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"‏انتخاب نسخه AVRCP بلوتوث"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"کدک بلوتوث صوتی"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"‏تأیید برنامه‌های نصب شده از طریق USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"‏برنامه‌های نصب شده از طریق ADB/ADT را ازنظر رفتار مخاطره‌آمیز بررسی کنید."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"در صورت وجود مشکل میزان صدا با دستگاه‌های راه دور مثل میزان صدای بلند ناخوشایند یا عدم کنترل صدا، قابلیت میزان صدای کامل بلوتوث را غیرفعال کنید."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"ترمینال محلی"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"فعال کردن ترمینال برنامه‌ کاربردی که دسترسی به برنامه محلی را پیشنهاد می‌کند"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"‏بررسی HDCP"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 73a6a87..6ec2e02 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Salli Wi-Fi-verkkovierailuskannaus aina"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilidata aina käytössä"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Poista yleinen äänenvoimakkuuden säätö käytöstä"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetoothin AVRCP-versio"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Valitse Bluetoothin AVRCP-versio"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-äänen koodekki"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Tarkista USB:n kautta asennetut"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tarkista ADB:n/ADT:n kautta asennetut sovellukset haitallisen toiminnan varalta."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Bluetoothin yleinen äänenvoimakkuuden säätö poistetaan käytöstä ongelmien välttämiseksi esimerkiksi silloin, kun laitteen äänenvoimakkuus on liian kova tai sitä ei voi säätää."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Paikallinen pääte"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Ota käyttöön päätesov. joka mahdollistaa paikall. liittymäkäytön"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-tarkistus"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 79dff3c..14c4af3 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Données cellulaires toujours actives"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Désactiver le volume absolu"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Version du profil Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Sélectionner la version du profil Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Vérifier les applis via USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Vérifiez que les applications installées par ADB/ADT ne présentent pas de comportement dangereux."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Désactive la fonctionnalité de volume absolu par Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Activer l\'application Terminal permettant l\'accès au shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Vérification HDCP"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index bbee22d..768ef5e 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Données mobiles toujours actives"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Désactiver le volume absolu"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Version Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Sélectionner la version Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Vérifier les applis via USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Vérifiez que les applications installées par ADB/ADT ne présentent pas de comportement dangereux."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Désactive la fonctionnalité de volume absolu du Bluetooth en cas de problème de volume sur les appareils à distance, par exemple si le volume est trop élevé ou s\'il ne peut pas être contrôlé."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Activer l\'application Terminal permettant l\'accès au shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Vérification HDCP"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index ecbffc6..3a5afba9 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre buscas de itinerancia da wifi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móbiles sempre activados"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactivar volume absoluto"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versión AVRCP de Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecciona a versión AVRCP de Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio por Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicacións por USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Comprobar as aplicacións instaladas a través de ADB/ADT para detectar comportamento perigoso."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desactiva a función do volume absoluto do Bluetooth en caso de que se produzan problemas de volume cos dispositivos remotos, como volume demasiado alto ou falta de control."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Activa a aplicación terminal que ofrece acceso ao shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Comprobación HDCP"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 2f4ac52..e7505de 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"હંમેશા Wi‑Fi રોમ સ્કૅન્સને મંજૂરી આપો"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ચોક્કસ વૉલ્યૂમને અક્ષમ કરો"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP સંસ્કરણ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP સંસ્કરણ પસંદ કરો"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth ઑડિઓ કોડેક"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB પર ઍપ્લિકેશનો ચકાસો"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"હાનિકારક વર્તણૂંક માટે ADB/ADT મારફતે ઇન્સ્ટોલ કરવામાં આવેલી ઍપ્લિકેશનો તપાસો."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"રિમોટ ઉપકરણોમાં વધુ પડતું ઊંચું વૉલ્યૂમ અથવા નિયંત્રણની કમી જેવી વૉલ્યૂમની સમસ્યાઓની સ્થિતિમાં Bluetooth ચોક્કસ વૉલ્યૂમ સુવિધાને અક્ષમ કરે છે."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"સ્થાનિક ટર્મિનલ"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"સ્થાનિક શેલ અ‍ૅક્સેસની ઑફર કરતી ટર્મિનલ એપ્લિકેશનને સક્ષમ કરો"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP તપાસણી"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 1c79ccf..47950db 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"हमेशा वाई-फ़ाई रोम स्कैन करने दें"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा हमेशा सक्रिय"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"पूर्ण वॉल्यूम अक्षम करें"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लूटूथ AVRCP वर्शन"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लूटूथ AVRCP वर्शन चुनें"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लूटूथ ऑडियो कोडेक"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB पर ऐप्स  सत्यापित करें"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"नुकसानदेह व्यवहार के लिए ADB/ADT के द्वारा इंस्टॉल किए गए ऐप्स  जांचें."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूरस्थ डिवाइस के साथ वॉल्यूम की समस्याओं जैसे अस्वीकार्य तेज़ वॉल्यूम या नियंत्रण की कमी की स्थिति में ब्लूटूथ पूर्ण वॉल्यूम सुविधा को अक्षम करता है."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"स्थानीय टर्मिनल"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"स्थानीय शेल एक्सेस ऑफ़र करने वाला टर्मिनल ऐप्स  सक्षम करें"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP जांच"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 13150ff..0c81032 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopusti slobodno traženje Wi-Fi mreže"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci uvijek aktivni"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući apsolutnu glasnoću"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzija AVRCP-a za Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Odaberite verziju AVRCP-a za Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodek za Bluetooth Audio"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Potvrdi aplikacije putem USB-a"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Provjerite uzrokuju li aplikacije instalirane putem ADB-a/ADT-a poteškoće."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogućuje Bluetoothovu značajku apsolutne glasnoće ako udaljeni uređaji imaju poteškoća sa zvukom, kao što su, primjerice, neprihvatljiva glasnoća ili nepostojanje kontrole."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Omogući aplikaciju terminala koja nudi pristup lokalnoj ovojnici"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP provjera"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 0e2b9b1..12a0370 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi-roaming ellenőrzésének engedélyezése mindig"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"A mobilhálózati kapcsolat mindig aktív"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Abszolút hangerő funkció letiltása"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"A Bluetooth AVRCP-verziója"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"A Bluetooth AVRCP-verziójának kiválasztása"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth hang – Kodek"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB-n keresztül telepített alkalmazások ellenőrzése"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Az ADB/ADT útján telepített alkalmazások ellenőrzése kártékony viselkedésre."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Letiltja a Bluetooth abszolút hangerő funkcióját a távoli eszközökkel kapcsolatos hangerőproblémák – például elfogadhatatlanul magas vagy nem vezérelhető hangerő – esetén."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Helyi végpont"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Végalkalmazás engedélyezése a helyi rendszerhéj eléréséhez"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ellenőrzés"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index a3d11e4..3309764 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Միշտ թույլատրել Wi‑Fi ռոումինգի որոնումը"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Բջջային ինտերնետը միշտ ակտիվ է"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Անջատել ձայնի բացարձակ ուժգնությունը"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP տարբերակը"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Ընտրել Bluetooth AVRCP տարբերակը"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth աուդիո կոդեկ"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Ստուգել հավելվածները USB-ի նկատմամբ"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Ստուգեք տեղադրված հավելվածը ADB/ADT-ի միջոցով կասկածելի աշխատանքի պատճառով:"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Կասեցնում է Bluetooth-ի ձայնի բացարձակ ուժգնության գործառույթը՝ հեռավոր սարքերի հետ ձայնի ուժգնությանը վերաբերող խնդիրներ ունենալու դեպքում (օրինակ՝ երբ ձայնի ուժգնությունն անընդունելի է կամ դրա կառավարումը հնարավոր չէ):"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Տեղային տերմինալ"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Միացնել տերմինալային հավելվածը, որն առաջարկում է մուտք տեղային խեցի"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ստուգում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 701d80d..700b69d 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Selalu izinkan Pemindaian Roaming Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Data seluler selalu aktif"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Nonaktifkan volume absolut"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versi AVRCP Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Pilih Versi AVRCP Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec Audio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifikasi aplikasi melalui USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Periksa perilaku membahayakan dalam aplikasi yang terpasang melalui ADB/ADT."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Menonaktifkan fitur volume absolut Bluetooth jika ada masalah volume dengan perangkat jarak jauh, misalnya volume terlalu keras atau kurangnya kontrol."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal lokal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Aktifkan aplikasi terminal yang menawarkan akses kerangka lokal"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Pemeriksaan HDCP"</string>
@@ -254,7 +258,7 @@
     <string name="force_rtl_layout_all_locales_summary" msgid="9192797796616132534">"Paksa arah tata letak layar RTL untuk semua lokal"</string>
     <string name="force_hw_ui" msgid="6426383462520888732">"Paksa perenderan GPU"</string>
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"Paksa penggunaan GPU untuk gambar 2d"</string>
-    <string name="force_msaa" msgid="7920323238677284387">"Force 4x MSAA"</string>
+    <string name="force_msaa" msgid="7920323238677284387">"Paksa 4x MSAA"</string>
     <string name="force_msaa_summary" msgid="9123553203895817537">"Aktifkan 4x MSAA dalam aplikasi OpenGL ES 2.0"</string>
     <string name="show_non_rect_clip" msgid="505954950474595172">"Debug operasi klip non-kotak"</string>
     <string name="track_frame_time" msgid="6146354853663863443">"Penguraian GPU profil"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index ef0a652..3644237 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Leyfa alltaf reikileit með Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Alltaf kveikt á farsímagögnum"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slökkva á samstillingu hljóðstyrks"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-útgáfa"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Velja Bluetooth AVRCP-útgáfu"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth hljóðkóðari"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Staðfesta forrit gegnum USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kanna skaðlega hegðun forrita sem sett eru upp frá ADB/ADT."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Slekkur á samstillingu Bluetooth-hljóðstyrks ef vandamál koma upp með hljóðstyrk hjá fjartengdum tækjum, svo sem of hár hljóðstyrkur eða erfiðleikar við stjórnun."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Staðbundin skipanalína"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Virkja skipanalínuforrit sem leyfir staðbundinn skeljaraðgang"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-athugun"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index f7c95f0..29088ae 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Consenti sempre scansioni roaming Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dati mobili sempre attivi"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disattiva volume assoluto"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versione Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Seleziona versione Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifica app tramite USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Controlla che le app installate tramite ADB/ADT non abbiano un comportamento dannoso."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Consente di disattivare la funzione del volume assoluto Bluetooth in caso di problemi con il volume dei dispositivi remoti, ad esempio un volume troppo alto o la mancanza di controllo."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminale locale"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Abilita l\'app Terminale che offre l\'accesso alla shell locale"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Verifica HDCP"</string>
@@ -316,7 +320,7 @@
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"Correzione del colore"</string>
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"Questa funzione è sperimentale e potrebbe influire sulle prestazioni."</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only" msgid="845431008899029842">"Quasi scarica. Tempo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_only" msgid="845431008899029842">"Tempo approssimativo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"Tempo rimanente: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - ancora circa <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index e7364dba..1ee0e87 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏התר תמיד סריקות נדידה של Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"חבילת הגלישה פעילה תמיד"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"השבת עוצמת קול מוחלטת"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"‏Bluetooth גרסה AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"‏בחר Bluetooth גרסה AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"‏Codec אודיו ל-Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"‏אמת אפליקציות באמצעות USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"‏בדוק אפליקציות שהותקנו באמצעות ADB/ADT לאיתור התנהגות מזיקה."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"‏משבית את תכונת עוצמת הקול המוחלטת ב-Bluetooth במקרה של בעיות בעוצמת הקול במכשירים מרוחקים, כגון עוצמת קול רמה מדי או חוסר שליטה ברמת העוצמה."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"מסוף מקומי"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"הפעל אפליקציית מסוף המציעה גישה מקומית למעטפת"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"‏בדיקת HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index aea586b..e1e14ec 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fiローミングスキャンを常に許可する"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"モバイルデータを常に ON にする"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"絶対音量を無効にする"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP バージョン"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP バージョンを選択する"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth オーディオ コーデック"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB経由のアプリを確認"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT経由でインストールされたアプリに不正な動作がないかを確認する"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"リモート端末で音量に関する問題(音量が大きすぎる、制御できないなど)が発生した場合に、Bluetooth の絶対音量の機能を無効にする。"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"ローカルターミナル"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"ローカルシェルアクセスを提供するターミナルアプリを有効にします"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCPチェック"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index b63cc81..a3dab5b 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Roam სკანირების მუდამ დაშვება"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"მობილური ინტერნეტის ყოველთვის გააქტიურება"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ხმის აბსოლუტური სიძლიერის გათიშვა"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth-ის AVRCP-ის ვერსია"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"აირჩიეთ Bluetooth-ის AVRCP-ის ვერსია"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth აუდიოს კოდეკი"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"აპლიკაციების USB-ს საშუალებით შემოწმება"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"შეამოწმეთ, რამდენად უსაფრთხოა ADB/ADT-ის საშუალებით ინსტალირებული აპლიკაციები."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"გათიშავს Bluetooth-ის ხმის აბსოლუტური სიძლიერის ფუნქციას დისტანციურ მოწყობილობებზე ხმასთან დაკავშირებული ისეთი პრობლემების არსებობის შემთხვევაში, როგორიცაა ხმის დაუშვებლად მაღალი სიძლიერე ან კონტროლის შეუძლებლობა."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"ადგილობრივი ტერმინალი"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"ლოკალურ გარსზე წვდომის ტერმინალური აპლიკაციის ჩართვა"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP შემოწმება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 9af8fc6..2851c25 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi роумингін іздеулерге әрқашан рұқсат ету"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобильдік деректер әрқашан қосулы"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Абсолютті дыбыс деңгейін өшіру"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP нұсқасы"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP нұсқасын таңдау"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудимазмұн кодегі"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB арқылы орнатылған қолданбаларды растау"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT арқылы орнатылған қолданбалардың залалды болмауын тексеру."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Қолайсыз қатты дыбыс деңгейі немесе басқарудың болмауы сияқты қашықтағы құрылғыларда дыбыс деңгейімен мәселелер жағдайында Bluetooth абсолютті дыбыс деңгейі функциясын өшіреді."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Жергілікті терминал"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Жергілікті шелл-код қол жетімділігін ұсынатын терминалды қолданбаны қосу"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP (жоғары кең жолақты сандық мазмұнды қорғау) тексеру"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 0174ae5..5de319d 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"តែងតែ​អនុញ្ញាត​​​ការវិភាគ​រ៉ូម​វ៉ាយហ្វាយ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ទិន្នន័យទូរសព្ទចល័តដំណើរការជានិច្ច"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"បិទកម្រិតសំឡេងលឺខ្លាំង"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"កំណែប្ល៊ូធូស AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ជ្រើសរើសកំណែប្ល៊ូធូស AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"កូឌិក​សំឡេង​ប៊្លូធូស"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ផ្ទៀងផ្ទាត់​កម្មវិធី​តាម​យូអេសប៊ី"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ពិនិត្យ​កម្មវិធី​បាន​ដំឡើង​តាម​រយៈ ADB/ADT សម្រាប់​ឥរិយាបថ​ដែល​គ្រោះ​ថ្នាក់។"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"បិទលក្ខណៈពិសេសកម្រិតសំឡេងលឺខ្លាំងពេលភ្ជាប់ប៊្លូធូសក្នុងករណីមានបញ្ហាជាមួយឧបករណ៍បញ្ជាពីចម្ងាយ ដូចជាកម្រិតសំឡេងលឺខ្លាំងដែលមិនអាចទទួលយកបាន ឬខ្វះការគ្រប់គ្រង។"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"ស្ថានីយ​មូលដ្ឋាន"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"បើក​កម្មវិធី​ស្ថានីយ​ដែល​ផ្ដល់​ការ​ចូល​សែល​មូលដ្ឋាន"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"ពិនិត្យ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index e80318b..d73683ec 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ವೈ-ಫೈ ರೋಮ್ ಸ್ಕ್ಯಾನ್‌ಗಳನ್ನು ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್‌ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ಬ್ಲೂಟೂತ್ AVRCP ಆವೃತ್ತಿಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ಮೂಲಕ ಆಪ್‌ ಪರಿಶೀಲಿಸಿ"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ಹಾನಿಮಾಡುವಂತಹ ವರ್ತನೆಗಾಗಿ ADB/ADT ಮೂಲಕ ಸ್ಥಾಪಿಸಲಾದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ರಿಮೋಟ್ ಸಾಧನಗಳೊಂದಿಗೆ ಒಪ್ಪಲಾಗದ ಜೋರಾದ ವಾಲ್ಯೂಮ್ ಅಥವಾ ನಿಯಂತ್ರಣದ ಕೊರತೆಯಂತಹ ವಾಲ್ಯೂಮ್ ಸಮಸ್ಯೆಗಳಂತಹ ಸಂದರ್ಭದಲ್ಲಿ ಬ್ಲೂಟೂತ್ ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್ ವೈಶಿಷ್ಟ್ಯವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಬಹುದು."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"ಸ್ಥಳೀಯ ಟರ್ಮಿನಲ್"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"ಸ್ಥಳೀಯ ಶೆಲ್ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುವ ಟರ್ಮಿನಲ್ ಅಪ್ಲಿಕೇಶನ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ಪರೀಕ್ಷಿಸುವಿಕೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index d32707c..2d49d89 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi 로밍 스캔 항상 허용"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"항상 모바일 데이터 활성화"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"절대 볼륨 사용 안함"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"블루투스 AVRCP 버전"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"블루투스 AVRCP 버전 선택"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"블루투스 오디오 코덱"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB를 통해 설치된 앱 확인"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT을 통해 설치된 앱에 유해한 동작이 있는지 확인"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"참기 어려울 정도로 볼륨이 크거나 제어가 되지 않는 등 원격 기기에서 볼륨 문제가 발생할 경우 블루투스 절대 볼륨 기능을 사용 중지합니다."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"로컬 터미널"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"로컬 셸 액세스를 제공하는 터미널 앱 사용"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP 확인"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index ba098e5..1418dab 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi Роуминг Скандоо мүмкүнчүлүгүнө ар дайым уруксат берилсин"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилдик дайындар ар дайым иштетилсин"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үндүн абсолюттук деңгээли өчүрүлсүн"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP версиясы"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP версиясын тандоо"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодек"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB аркылуу келген колдонмолорду ырастоо"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT аркылуу орнотулган колдонмолорду зыянкечтикке текшерүү."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Алыскы түзмөктөр өтө катуу добуш чыгарып же көзөмөлдөнбөй жатса Bluetooth \"Үндүн абсолюттук деңгээли\" функциясын өчүрөт."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Жергиликтүү терминал"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Жергиликтүү буйрук кабыгын сунуштаган терминалга уруксат берүү"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP текшерүү"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 5f78888..3839b35 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ອະ​ນຸ​ຍາດ​ການ​ສະ​ແກນ​ການ​ໂຣມ Wi‑Fi ​ສະ​ເໝີ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ເປີດໃຊ້ອິນເຕີເນັດມືຖືຕະຫຼອດເວລາ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ປິດໃຊ້ລະດັບສຽງສົມບູນ"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ເວີຊັນ Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ເລືອກເວີຊັນ Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ຢືນຢັນແອັບຯຜ່ານທາງ USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ກວດສອບແອັບຯທີ່ຕິດຕັ້ງແລ້ວຜ່ານທາງ ADB/ADT ເພື່ອກວດຫາພຶດຕິກຳທີ່ເປັນອັນຕະລາຍ."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ປິດໃຊ້ຄຸນສົມບັດລະດັບສຽງສົມບູນຂອງ Bluetooth ໃນກໍລະນີເກີດບັນຫາລະດັບສຽງສົມບູນກັບອຸປະກອນທາງໄກ ເຊັ່ນວ່າ ລະດັບສຽງດັງເກີນຍອມຮັບໄດ້ ຫຼື ຄວບຄຸມບໍ່ໄດ້."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal ໃນໂຕເຄື່ອງ"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"ເປີດນຳໃຊ້ແອັບຯ Terminal ທີ່ໃຫ້ການເຂົ້າເຖິງ shell ໃນໂຕເຄື່ອງໄດ້"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"ການກວດສອບ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index be32f56..df4c290 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Visada leisti „Wi-Fi“ tarptiklinio ryšio nuskaitymą"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiliojo ryšio duomenys visada suaktyvinti"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Išjungti didžiausią garsą"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"„Bluetooth“ AVRCP versija"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Pasirinkite „Bluetooth“ AVRCP versiją"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"„Bluetooth“ garso kodekas"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Patvirtinti progr. naudojant USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Patikrinkite, ar programų, įdiegtų naudojant ADB / ADT, veikimas nėra žalingas."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Išjungiama „Bluetooth“ didžiausio garso funkcija, jei naudojant nuotolinio valdymo įrenginius kyla problemų dėl garso, pvz., garsas yra per didelis arba jo negalima tinkamai valdyti."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Vietinis terminalas"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Įgal. terminalo progr., siūlančią prieigą prie viet. apvalkalo"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP tikrinimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index e0db1e6..6910534 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vienmēr atļaut Wi‑Fi meklēšanu"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Vienmēr aktīvs mobilo datu savienojums"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Atspējot absolūto skaļumu"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP versija"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Atlasiet Bluetooth AVRCP versiju"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodeks"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificēt, ja instalētas no USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Pārbaudīt, vai lietotņu, kuru instalēšanai izmantots ADB/ADT, darbība nav kaitīga."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Atspējo Bluetooth absolūtā skaļuma funkciju skaļuma problēmu gadījumiem attālajās ierīcēs, piemēram, ja ir nepieņemami liels skaļums vai nav iespējas kontrolēt skaļumu."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Vietējā beigu lietotne"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Iespējot beigu lietotni, kurā piedāvāta vietējā čaulas piekļuve"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP pārbaude"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index f903153..c7c9ac8 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Секогаш дозволувај Wi‑Fi скенирање во роаминг"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилниот интернет е секогаш активен"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Оневозможете апсолутна јачина на звук"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Верзија Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Изберете верзија Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодек за аудио преку Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Потврди апликации преку УСБ"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Провери апликации инсталирани преку ADB/ADT за штетно однесување."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Ја оневозможува карактеристиката за апсолутна јачина на звук преку Bluetooth во случај кога ќе настанат проблеми со далечинските уреди, како на пр., неприфатливо силен звук или недоволна контрола."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Локален терминал"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Овозможи апликација на терминал што овозможува локален пристап кон школка."</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Проверување HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 68b0a50..d91614e 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"എപ്പോഴും വൈഫൈ റോം സ്‌‌കാൻ അനുവദിക്കൂ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"മൊബൈൽ ഡാറ്റ എല്ലായ്‌പ്പോഴും സജീവം"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"അബ്‌സൊല്യൂട്ട് വോളിയം പ്രവർത്തനരഹിതമാക്കുക"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP പതിപ്പ്"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP പതിപ്പ് തിരഞ്ഞെടുക്കുക"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth ഓഡിയോ കോഡെക്"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB വഴി ആപ്സ് പരിശോധിച്ചുറപ്പിക്കൂ"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"കേടാക്കുന്ന പ്രവർത്തനരീതിയുള്ള ADB/ADT വഴി ഇൻസ്റ്റാളുചെയ്‌ത അപ്ലിക്കേഷനുകൾ പരിശോധിക്കുക."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"അസ്വീകാര്യമായ തരത്തിൽ ഉയർന്ന വോളിയമോ ശബ്ദ നിയന്ത്രണത്തിന്റെ അഭാവമോ പോലെ, വിദൂര ഉപകരണങ്ങളുമായി ബന്ധപ്പെട്ട വോളിയം പ്രശ്നങ്ങൾ ഉണ്ടാകുന്ന സാഹചര്യത്തിൽ, Bluetooth അബ്‌സൊല്യൂട്ട് വോളിയം ഫീച്ചർ പ്രവർത്തനരഹിതമാക്കുന്നു."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"പ്രാദേശിക ടെർമിനൽ"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"പ്രാദേശിക ഷെൽ ആക്‌സസ് നൽകുന്ന ടെർമിനൽ അപ്ലിക്കേഷൻ പ്രവർത്തനക്ഷമമാക്കുക"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP പരിശോധന"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index dd9adb7..27e984e 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Роум сканыг байнга зөвшөөрөх"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобайл дата байнга идэвхтэй"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үнэмлэхүй дууны түвшинг идэвхгүй болгох"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP хувилбар"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP хувилбарыг сонгох"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодлогч"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Апп-г USB-р тулгах"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT-р суулгасан апп-уудыг хорлонтой авиртай эсэхийг шалгах."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Хэт чанга дуугаралт эсвэл муу тохиргоо зэрэг алсын зайн төхөөрөмжийн дуугаралттай холбоотой асуудлын үед Bluetooth-ийн үнэмлэхүй дууны түвшинг идэвхгүй болго."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Локал терминал"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Локал суурьт хандалт хийх боломж олгодог терминалын апп-г идэвхжүүлэх"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP шалгах"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 89bbc71..10d9205 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"वाय-फाय रोम स्‍कॅनला नेहमी अनुमती द्या"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा नेहमी सक्रिय"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"संपूर्ण आवाज अक्षम करा"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लूटुथ AVRCP आवृत्ती"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लूटुथ AVRCP आवृत्ती निवडा"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लूटूथ ऑडिओ कोडेक"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB वरील अॅप्स सत्यापित करा"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक वर्तनासाठी ADB/ADT द्वारे स्थापित अॅप्स तपासा."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"दूरस्थ डिव्हाइसेसमध्ये सहन न होणारा मोठा आवाज किंवा नियंत्रणचा अभाव यासारखी आवाजाची समस्या असल्यास ब्लूटुथ संपूर्ण आवाज वैशिष्ट्य अक्षम करते."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"स्थानिक टर्मिनल"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"स्थानिक शेल प्रवेश देणारा टर्मिनल अॅप सक्षम करा"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP तपासणी"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 4dd2e1a..ff5b507 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sentiasa benarkan Imbasan Perayauan Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Data mudah alih sentiasa aktif"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Lumpuhkan kelantangan mutlak"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versi AVRCP Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Pilih Versi AVRCP Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec Audio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Sahkan apl melalui USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Semak apl yang dipasang melalui ADB/ADT untuk tingkah laku yang berbahaya."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Lumpuhkan ciri kelantangan mutlak Bluetooth dalam kes isu kelantangan menggunakan peranti kawalan jauh seperti kelantangan yang sangat kuat atau tidak dapat mengawal."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal setempat"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Dayakan apl terminal yang menawarkan akses shell tempatan"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Penyemakan HDCP"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index de4c831..ab2d41e 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi ရွမ်းရှာဖွေမှုကို အမြဲတမ်း ခွင့်ပြုမည်"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"မိုဘိုင်းဒေတာကို အမြဲဖွင့်ထားရန်"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ပကတိ အသံနှုန်း သတ်မှတ်ချက် ပိတ်ရန်"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ဘလူးတုသ် AVRCP ဗားရှင်း"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ဘလူးတုသ် AVRCP ဗားရှင်းကို ရွေးပါ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ဘလူးတုသ်အသံ ကိုးဒက်ခ်"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USBပေါ်မှ အပလီကေးရှင်းများကို အတည်ပြုစိစစ်ရန်"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT မှတဆင့် ထည့်သွင်းသော အပလီကေးရှင်းများကို အန္တရာယ်ဖြစ်နိုင်ခြင်း ရှိမရှိ စစ်ဆေးရန်။"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ချိတ်ဆက်ထားသည့် ကိရိယာတွင် လက်မခံနိုင်လောက်အောင် ဆူညံ သို့မဟုတ် ထိန်းညှိမရနိုင်သော အသံပိုင်းပြဿနာ ရှိခဲ့လျှင် ဘလူးတုသ် ပကတိ အသံနှုန်းကို ပိတ်ပါ။"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"လိုကယ်တာမီနယ်"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"local shell အသုံးပြုခွင့်ကမ်းလှမ်းသော တာမင်နယ်အပလီကေးရှင်းဖွင့်ပါ"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP စစ်ဆေးမှု"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 2e574dc..b6d325f 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillat alltid skanning for Wi-Fi-roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er alltid aktiv"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slå av funksjonen for absolutt volum"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP-versjon"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Velg Bluetooth AVRCP-versjon"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodek for Bluetooth-lyd"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Bekreft apper via USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Sjekk apper som er installert via ADB/ADT for skadelig adferd."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Slår av funksjonen for absolutt volum via Bluetooth i tilfelle det oppstår volumrelaterte problemer med eksterne enheter, for eksempel uakseptabelt høyt volum eller mangel på kontroll."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Aktiver terminalappen som gir lokal kommandolistetilgang"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontroll"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 35d8363..f5eaa71b 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi घुम्ने स्क्यान गर्न सधैँ अनुमति दिनुहोस्"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा सधैँ सक्रिय राख्नुहोस्"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"निरपेक्ष आवाज असक्षम गर्नुहोस्"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ब्लुटुथको AVRCP संस्करण"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ब्लुटुथको AVRCP संस्करण चयन गर्नुहोस्"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लुटुथ अडियोको कोडेक"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB मा अनुप्रयोगहरू रुजु गर्नुहोस्"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक व्यवहारको लागि ADB/ADT को माध्यमबाट स्थापित अनुप्रयोगहरूको जाँच गर्नुहोस्।"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"रिमोट यन्त्रहरूमा अस्वीकार्य चर्को आवाज वा नियन्त्रणमा कमी जस्ता आवाज सम्बन्धी समस्याहरूको अवस्थामा ब्लुटुथ निरपेक्ष आवाज सुविधालाई असक्षम गराउँछ।"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"स्थानीय टर्मिनल"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"स्थानीय सेल पहुँच प्रदान गर्ने टर्मिनल अनुप्रयोग सक्षम गर्नुहोस्"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP जाँच गर्दै"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 902c5df..8c279f3 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Altijd roamingscans voor wifi toestaan"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data altijd actief"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Absoluut volume uitschakelen"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth-AVRCP-versie"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth-AVRCP-versie selecteren"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-audiocodec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Apps verifiëren via USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Apps die zijn geïnstalleerd via ADB/ADT, controleren op schadelijk gedrag"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Hiermee wordt de functie voor absoluut volume van Bluetooth uitgeschakeld in geval van volumeproblemen met externe apparaten, zoals een onacceptabel hoog volume of geen volumeregeling."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokale terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Terminal-app inschakelen die lokale shell-toegang biedt"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-controle"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index dc949c3..c9d7068 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ Wi‑Fi Roam Scans ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ਮੋਬਾਈਲ ਡੈਟਾ ਹਮੇਸ਼ਾਂ ਕਿਰਿਆਸ਼ੀਲ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ਪੂਰਨ ਵੌਲਿਊਮ ਨੂੰ ਅਯੋਗ ਬਣਾਓ"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"ਬਲੂਟੁੱਥ AVRCP ਰੂਪ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"ਬਲੂਟੁੱਥ AVRCP ਰੂਪ ਚੁਣੋ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਕੋਡੇਕ"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ਤੇ ਐਪਸ ਨੂੰ ਪ੍ਰਮਾਣਿਤ ਕਰੋ"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ਹਾਨੀਕਾਰਕ ਵਿਵਹਾਰ ਲਈ ADB/ADT ਰਾਹੀਂ ਇੰਸਟੌਲ ਕੀਤੇ ਐਪਸ ਦੀ ਜਾਂਚ ਕਰੋ।"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ਰਿਮੋਟ ਡੀਵਾਈਸਾਂ ਨਾਲ ਵੌਲਿਊਮ ਸਮੱਸਿਆਵਾਂ ਜਿਵੇਂ ਕਿ ਨਾ ਪਸੰਦ ਕੀਤੀ ਜਾਣ ਵਾਲੀ ਉੱਚੀ ਵੌਲਿਊਮ ਜਾਂ ਕੰਟਰੋਲ ਦੀ ਕਮੀ ਵਰਗੀ ਹਾਲਤ ਵਿੱਚ ਬਲੂਟੁੱਥ ਪੂਰਨ ਵੌਲਿਊਮ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਅਯੋਗ ਬਣਾਉਂਦਾ ਹੈ।"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"ਸਥਾਨਕ ਟਰਮੀਨਲ"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"ਟਰਮੀਨਲ ਐਪ ਨੂੰ ਸਮਰੱਥ ਬਣਾਓ ਜੋ ਸਥਾਨਕ ਸ਼ੈਲ ਪਹੁੰਚ ਆੱਫਰ ਕਰਦਾ ਹੈ"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ਜਾਂਚ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index f54375b..0b366dc 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Zawsze szukaj Wi-Fi w roamingu"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna transmisja danych zawsze aktywna"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Wyłącz głośność bezwzględną"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Wersja AVRCP Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Wybierz wersję AVRCP Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodek dźwięku Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Zweryfikuj aplikacje przez USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Sprawdź, czy aplikacje zainstalowane przez ADB/ADT nie zachowują się w szkodliwy sposób"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Wyłącza funkcję Głośność bezwzględna Bluetooth, jeśli występują problemy z urządzeniami zdalnymi, np. zbyt duża głośność lub brak kontroli."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal lokalny"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Włącz terminal, który umożliwia dostęp do powłoki lokalnej"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Sprawdzanie HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 975a807..51288859 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão do Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecionar versão do Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar apps por USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar comportamento nocivo em apps instalados via ADB/ADT."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Ativar o app terminal que oferece acesso ao shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 89f82af..bcd5a48 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -168,10 +168,12 @@
     <string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
     <string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de display sem fios"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar o registo verboso de Wi-Fi"</string>
-    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transm. agressiva de Wi‑Fi p/ rede móvel"</string>
+    <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança brusca de Wi‑Fi para rede móvel"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre a deteção de Wi-Fi em roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão de Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecionar versão de Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar aplicações de USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar as aplicações instaladas via ADB/ADT para detetar comportamento perigoso."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa a funcionalidade de volume absoluto do Bluetooth caso existam problemas de volume com dispositivos remotos, como um volume insuportavelmente alto ou a ausência de controlo."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Ativar aplicação terminal que oferece acesso local à shell"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 975a807..51288859 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versão do Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selecionar versão do Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verificar apps por USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Verificar comportamento nocivo em apps instalados via ADB/ADT."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Desativa o recurso Bluetooth de volume absoluto em caso de problemas com o volume em dispositivos remotos, como volume excessivamente alto ou falta de controle."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminal local"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Ativar o app terminal que oferece acesso ao shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Verificação HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 982a5bf..e6988b9 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Se permite întotdeauna scanarea traficului Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Date mobile permanent active"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Dezactivați volumul absolut"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versiunea AVRCP pentru Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Selectați versiunea AVRCP pentru Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
@@ -209,6 +211,8 @@
     <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>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Dezactivează funcția Bluetooth de volum absolut în cazul problemelor de volum apărute la dispozitivele la distanță, cum ar fi volumul mult prea ridicat sau lipsa de control asupra acestuia."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Aplicație terminal locală"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Activați aplicația terminal care oferă acces la shell local"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Verificare HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 6bc2520..a043e6f 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Всегда включать поиск сетей Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Не отключать мобильный Интернет"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Отключить абсолютный уровень громкости"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версия Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Выберите версию Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Аудиокодек для передачи через Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Проверять приложения при установке"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Выполнять проверку безопасности приложений при установке через ADB/ADT"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Отключить абсолютный уровень громкости Bluetooth при возникновении проблем на удаленных устройствах, например при слишком громком звучании или невозможности контролировать настройку."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Локальный терминальный доступ"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Разрешить терминальный доступ к локальной оболочке"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Проверка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index a8fd5bd..3d75e1d 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi රෝම් පරිලෝකන වෙතට සැමවිට අවසර දෙන්න"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"ජංගම දත්ත සැමවිට ක්‍රියාකාරීය"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"නිරපේක්ෂ හඩ පරිමාව අබල කරන්න"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"බ්ලූටූත් AVRCP අනුවාදය"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"බ්ලූටූත් AVRCP අනුවාදය තෝරන්න"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"බ්ලූටූත් ශ්‍රව්‍ය Codec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ඔස්සේ යෙදුම් සත්‍යාපනය කරගන්න"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT හරහා ස්ථාපනය වූ යෙදුම්, විනාශකාරී ක්‍රියාවන් ඇත්දැයි පරික්ෂාකර බලන්න."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"පිළිගත නොහැකි ලෙස වැඩි හඩ පරිමාව හෝ පාලනය නොමැති වීම යනාදී දුරස්ථ උපාංග සමගින් වන හඬ පරිමා ගැටලුවලදී බ්ලූටූත් නිරපේක්ෂ හඬ පරිමා විශේෂාංගය අබල කරයි."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"අභ්‍යන්තර අන්තය"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"දේශීය ෂෙල් ප්‍රවේශනය පිරිනමන ටර්මිනල් යෙදුම සබල කරන්න"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP පරික්ෂාව"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 686fe01d..6eff612 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povoliť funkciu Wi-Fi Roam Scans"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilné dáta ponechať vždy aktívne"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázať absolútnu hlasitosť"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Verzia rozhrania Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Zvoľte verziu rozhrania Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio – kodek"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Overovať aplikácie z USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrolovať škodlivosť aplikácií nainštalovaných pomocou nástroja ADB alebo ADT"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Umožňuje zakázať funkciu absolútnej hlasitosti rozhrania Bluetooth v prípade problémov s hlasitosťou na vzdialených zariadeniach, ako je napríklad neprijateľne vysoká hlasitosť alebo absencia ovládacích prvkov."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Miestny terminál"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Povoliť terminálovú apl. na miestny prístup k prostrediu shell"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Kontrola HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index d9b5125..4dedf23 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vedno omogoči iskanje omrežij Wi-Fi za gostovanje"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Prenos podatkov v mobilnem omrežju je vedno aktiven"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogočanje absolutnega praga glasnosti"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Različica profila AVRCP za Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Izberite različico profila AVRCP za Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Zvočni kodek za Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Preveri aplikacije prek USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Preveri, ali so aplikacije, nameščene prek ADB/ADT, škodljive."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Onemogoči funkcijo absolutnega praga glasnosti za Bluetooth, če pride do težav z glasnostjo z oddaljenimi napravami, kot je nesprejemljivo visoka glasnost ali pomanjkanje nadzora."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokalni terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Omogočanje terminalske aplikacije za dostop do lokalne lupine"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Preverjanje HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index b0ff3d1..42f7e76 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Lejo gjithmonë skanimet për Wi-Fi edhe kur je në lëvizje"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Të dhënat celulare gjithmonë aktive"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Çaktivizo volumin absolut"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Versioni AVRCP i Bluetooth-it"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Zgjidh versionin AVRCP të Bluetooth-it"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodeku Bluetooth Audio"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifiko apl. përmes USB-së"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollo aplikacionet e instaluara nëpërmjet ADB/ADT për sjellje të dëmshme."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Çaktivizon funksionin e volumit absolut të Bluetooth në rast të problemeve të volumit me pajisjet në largësi, si p.sh. një volum i lartë i papranueshëm ose mungesa e kontrollit."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Terminali lokal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Aktivizo aplikacionin terminal që ofron qasje në guaskën lokale"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Kontrolli HDCP"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 67412cf..1b80a81 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -125,7 +125,7 @@
     <string name="tts_engine_settings_title" msgid="3499112142425680334">"Подешавања за <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
     <string name="tts_engine_settings_button" msgid="1030512042040722285">"Покрени подешавања машине"</string>
     <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Жељена машина"</string>
-    <string name="tts_general_section_title" msgid="4402572014604490502">"Опште"</string>
+    <string name="tts_general_section_title" msgid="4402572014604490502">"Општа"</string>
     <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Ресетујте висину тона говора"</string>
     <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Ресетујте висину тона којом се текст изговара на подразумевану."</string>
   <string-array name="tts_rate_entries">
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Увек дозволи скенирање Wi‑Fi-ја у ромингу"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилни подаци су увек активни"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Онемогући главно подешавање јачине звука"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Верзија Bluetooth AVRCP-а"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Изаберите верзију Bluetooth AVRCP-а"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодек"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Верификуј апликације преко USB-а"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Проверава да ли су апликације инсталиране преко ADB-а/ADT-а штетне."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Онемогућава главно подешавање јачине звука на Bluetooth уређају у случају проблема са јачином звука на даљинским уређајима, као што су изузетно велика јачина звука или недостатак контроле."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Локални терминал"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Омогући аплик. терминала за приступ локалном командном окружењу"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP провера"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 8dad4bc..e187143 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillåt alltid sökning efter Wi-Fi-roaming"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata alltid aktiverad"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inaktivera Absolute volume"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"AVRCP-version för Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Välj AVRCP-version för Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Ljudkodek för Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Verifiera appar via USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kontrollera om appar som installeras via ADB/ADT kan vara skadliga."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Inaktivera Bluetooth-funktionen Absolute volume om det skulle uppstå problem med volymen på fjärrenheter, t.ex. alldeles för hög volym eller brist på kontroll."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokal terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Aktivera en terminalapp som ger åtkomst till hyllor lokalt"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP-kontroll"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index e38a5c6..c343c0f 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Ruhusu Uchanganuzi wa Matumizi ya Mitandao mingine"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Iendelee kutumia data ya simu"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zima sauti kamili"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Toleo la Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Chagua Toleo la Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodeki ya Sauti ya Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Thibitisha programu kupitia USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kagua programu zilizosakinishwa kupitia ADB/ADT kwa tabia ya kudhuru."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Huzima kipengele cha Bluetooth cha sauti kamili kunapotokea matatizo ya sauti katika vifaa vya mbali kama vile sauti ya juu mno au inaposhindikana kuidhibiti."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Kituo cha karibu"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Washa programu ya mwisho inayotoa ufikiaji mkuu wa karibu"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Inakagua HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 5826d66..5a1efb9 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"எப்போதும் வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"மொபைல் தரவை எப்போதும் இயக்கத்திலேயே வை"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கு"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"புளூடூத் AVRCP பதிப்பு"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"புளூடூத் AVRCP பதிப்பைத் தேர்ந்தெடு"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"புளூடூத் ஆடியோ கோடெக்"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB பயன்பாடுகளை சரிபார்"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"தீங்கு விளைவிக்கும் செயல்பாட்டை அறிய ADB/ADT மூலம் நிறுவப்பட்டப் பயன்பாடுகளைச் சரிபார்."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"மிகவும் அதிகமான ஒலியளவு அல்லது கட்டுப்பாடு இழப்பு போன்ற தொலைநிலைச் சாதனங்களில் ஏற்படும் ஒலி தொடர்பான சிக்கல்கள் இருக்கும் சமயங்களில், புளூடூத் அப்சல்யூட் ஒலியளவு அம்சத்தை முடக்கும்."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"அக முனையம்"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"அக ஷெல் அணுகலை வழங்கும் இறுதிப் பயன்பாட்டை இயக்கு"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP சரிபார்ப்பு"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 1c937ed..c7bb387 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi సంచార స్కాన్‌లను ఎల్లప్పుడూ అనుమతించు"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"మొబైల్ డేటాని ఎల్లప్పుడూ సక్రియంగా ఉంచు"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"సంపూర్ణ వాల్యూమ్‌‍ను నిలిపివేయి"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"బ్లూటూత్ AVRCP సంస్కరణ"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"బ్లూటూత్ AVRCP సంస్కరణను ఎంచుకోండి"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"బ్లూటూత్ ఆడియో కోడెక్"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ద్వారా అనువర్తనాలను ధృవీకరించు"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"హానికరమైన ప్రవర్తన కోసం ADB/ADT ద్వారా ఇన్‌స్టాల్ చేయబడిన అనువర్తనాలను తనిఖీ చేయి."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"రిమోట్ పరికరాల్లో ఆమోదించలేని స్థాయిలో అధిక వాల్యూమ్ ఉండటం లేదా వాల్యూమ్ నియంత్రణ లేకపోవడం వంటి సమస్యలు ఉంటే బ్లూటూత్ సంపూర్ణ వాల్యూమ్ లక్షణాన్ని నిలిపివేస్తుంది."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"స్థానిక టెర్మినల్"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"స్థానిక షెల్ ప్రాప్యతను అందించే టెర్మినల్ అనువర్తనాన్ని ప్రారంభించు"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP తనిఖీ"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 56e4939..a862272 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ใช้การสแกน Wi-Fi ข้ามเครือข่ายเสมอ"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"เปิดใช้อินเทอร์เน็ตมือถือเสมอ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ปิดใช้การควบคุมระดับเสียงของอุปกรณ์อื่น"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"เวอร์ชันของบลูทูธ AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"เลือกเวอร์ชันของบลูทูธ AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ตัวแปลงรหัสเสียงบลูทูธ"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ยืนยันแอปพลิเคชันผ่าน USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ตรวจสอบแอปพลิเคชันที่ติดตั้งผ่าน ADB/ADT เพื่อตรวจดูพฤติกรรมที่เป็นอันตราย"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ปิดใช้คุณลักษณะการควบคุมระดับเสียงของอุปกรณ์อื่นผ่านบลูทูธในกรณีที่มีปัญหาเกี่ยวกับระดับเสียงของอุปกรณ์ระยะไกล เช่น ระดับเสียงที่ดังเกินไปหรือระดับเสียงที่ไม่มีการควบคุม"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"เทอร์มินัลในตัวเครื่อง"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"เปิดใช้งานแอปเทอร์มินัลที่ให้การเข้าถึงเชลล์ในตัวเครื่อง"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"การตรวจสอบ HDCP"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 8dc6f4d..eefeeda 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Palaging payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Palaging aktibo ang mobile data"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"I-disable ang absolute volume"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bersyon ng AVRCP ng Bluetooth"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Pumili ng Bersyon ng AVRCP ng Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"I-verify ang mga app sa USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Tingnan kung may nakakahamak na pagkilos sa apps na na-install sa pamamagitan ng ADB/ADT."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Dini-disable ang absolute volume feature ng Bluetooth kung may mga isyu sa volume ang mga malayong device gaya ng hindi katanggap-tanggap na malakas na volume o kawalan ng kontrol."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Lokal na terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Paganahin ang terminal app na nag-aalok ng lokal na shell access"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Pagsusuring HDCP"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 6fc6cd0..05310df 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Kablosuz Dolaşım Taramalarına daima izin ver"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil veri her zaman etkin"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Mutlak sesi iptal et"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP Sürümü"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP Sürümünü seçin"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Ses Codec\'i"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB\'den yüklenen uygulamaları doğrula"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT üzerinden yüklenen uygulamaları zararlı davranışlara karşı denetle."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Uzak cihazda sesin aşırı yüksek olması veya kontrol edilememesi gibi ses sorunları olması ihtimaline karşı Bluetooh mutlak ses özelliğini iptal eder."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Yerel terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Yerel kabuk erişimi sunan terminal uygulamasını etkinleştir"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP denetimi"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 2a46d09..6f6f9d8 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Завжди шукати мережі Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Не вимикати мобільне передавання даних"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Вимкнути абсолютну гучність"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Версія Bluetooth AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Виберіть версію Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодек для аудіо Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Встановлення через USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Перевіряти безпеку додатків, установлених через ADB/ADT."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Функція абсолютної гучності Bluetooth вимикається, якщо на віддалених пристроях виникають проблеми, як-от надто висока гучність або втрата контролю."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Локальний термінал"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Увімк. програму-термінал, що надає локальний доступ до оболонки"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Перевірка HDCP"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 8c1d8f4..3a0eaa0 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏ہمیشہ Wi‑Fi روم اسکینز کی اجازت دیں"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"موبائل ڈیٹا ہمیشہ فعال رکھیں"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"مطلق والیوم کو غیر فعال کریں"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"‏بلوٹوتھ AVRCP ورژن"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"‏بلوٹوتھ AVRCP ورژن منتخب کریں"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"بلوٹوتھ آڈیو کوڈیک"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"‏USB پر ایپس کی توثیق کریں"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"‏نقصان دہ رویے کے مدنظر ADB/ADT کی معرفت انسٹال شدہ ایپس کی جانچ کریں۔"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ریموٹ آلات کے ساتھ والیوم کے مسائل مثلاً نا قابل قبول حد تک بلند والیوم یا کنٹرول نہ ہونے کی صورت میں بلو ٹوتھ مطلق والیوم والی خصوصیت کو غیر فعال کریں۔"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"مقامی ٹرمینل"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"مقامی شیل رسائی پیش کرنے والی ٹرمینل ایپ فعال کریں"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"‏HDCP چیکنگ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 588ea1a..69407ff 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi tarmoqlarini qidirishga doim ruxsat"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil internet doim yoniq tursin"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Ovoz balangligining mutlaq darajasini o‘chirib qo‘yish"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth AVRCP versiyasi"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Bluetooth AVRCP versiyasini tanlang"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodeki"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB orqali o‘rnatish"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ADB/ADT orqali o‘rnatilgan ilovalar xavfsizligini tekshiring"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Masofadan ulanadigan qurilmalar bilan muammolar yuz berganda, jumladan, juda baland ovoz yoki sozlamalarni boshqarib bo‘lmaydigan holatlarda Bluetooth ovozi balandligining mutlaq darajasini o‘chirib qo‘yadi."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Mahalliy terminal"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Mahalliy terminalga kirishga ruxsat beruvchi terminal ilovani faollashtirish"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP tekshiruvi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 6ffef25..c5810d7 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luôn cho phép quét chuyển vùng Wi‑Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Dữ liệu di động luôn hiện hoạt"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Vô hiệu hóa âm lượng tuyệt đối"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Bluetooth phiên bản AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Chọn Bluetooth phiên bản AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec âm thanh Bluetooth"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Xác minh ứng dụng qua USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Kiểm tra các ứng dụng được cài đặt qua ADB/ADT để xem có hoạt động gây hại hay không."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Vô hiệu hóa tính năng âm lượng tuyệt đối qua Bluetooth trong trường hợp xảy ra sự cố về âm lượng với các thiết bị từ xa, chẳng hạn như âm lượng lớn không thể chấp nhận được hoặc thiếu kiểm soát."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Dòng lệnh cục bộ"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Bật ứng dụng dòng lệnh cung cấp quyền truy cập vỏ cục bộ"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Kiểm tra HDCP"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index f2d2026..f6c20b6 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允许WLAN漫游扫描"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"始终开启移动数据网络"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用绝对音量功能"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"蓝牙 AVRCP 版本"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"选择蓝牙 AVRCP 版本"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"蓝牙音频编解码器"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"通过USB验证应用"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"通过 ADB/ADT 检查安装的应用是否存在有害行为。"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"停用蓝牙绝对音量功能,即可避免在连接到远程设备时出现音量问题(例如音量高得让人无法接受或无法控制音量等)。"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"本地终端"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"启用终端应用,以便在本地访问 Shell"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP 检查"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index db590f7..2881b79 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"永遠允許 Wi-Fi 漫遊掃瞄"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"一律保持啟用流動數據"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用絕對音量功能"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"藍牙 AVRCP 版本"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"選擇藍牙 AVRCP 版本"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"藍牙音訊編解碼器"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"透過 USB 驗證應用程式"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"透過 ADB/ADT 檢查安裝的應用程式有否有害的行為。"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"連線至遠端裝置時,如發生音量過大或無法控制音量等問題,請停用藍牙絕對音量功能。"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"本機終端機"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP 檢查"</string>
@@ -317,7 +321,7 @@
     <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"這是一項實驗性功能,可能會影響效能。"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
-    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能完全充電"</string>
+    <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"<xliff:g id="TIME">%1$s</xliff:g>後就能完全充電"</string>
     <string name="power_remaining_duration_only_short" msgid="5329694252258605547">"尚餘 <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_discharging_duration" msgid="2843747179907396142">"<xliff:g id="LEVEL">%1$s</xliff:g> - 剩餘約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="power_discharging_duration_short" msgid="4192244429001842403">"<xliff:g id="LEVEL">%1$s</xliff:g> - 尚餘 <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index ad9c769..e2ff29f 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允許 Wi-Fi 漫遊掃描"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"行動數據連線一律保持啟用狀態"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"停用絕對音量功能"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"藍牙 AVRCP 版本"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"選取藍牙 AVRCP 版本"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"藍牙音訊轉碼器"</string>
@@ -207,8 +209,10 @@
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"允許開發設定?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"這些設定僅供開發之用,可能導致您的裝置及裝置中的應用程式毀損或運作異常。"</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"透過 USB 驗證應用程式"</string>
-    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"透過 ADB/ADT 檢查安裝的應用程式是否出現有害的行為。"</string>
+    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"檢查透過 ADB/ADT 安裝的應用程式是否具有有害行為。"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"只要停用藍牙絕對音量功能,即可避免在連線到遠端裝置時,發生音量過大或無法控制音量等問題。"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"本機終端機"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"啟用可提供本機命令介面存取權的終端機應用程式"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP 檢查"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 5aabdb0..3e990f9 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -172,6 +172,8 @@
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vumela njalo ukuskena kokuzula kwe-Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8774857027458200434">"Idatha yeselula ihlala isebenza"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Khubaza ivolumu ngokuphelele"</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing (3291686366721786740) -->
+    <skip />
     <string name="bluetooth_select_avrcp_version_string" msgid="3750059931120293633">"Inguqulo ye-Bluetooth ye-AVRCP"</string>
     <string name="bluetooth_select_avrcp_version_dialog_title" msgid="7277329668298705702">"Khetha inguqulo ye-Bluetooth AVRCP"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"I-Bluetooth Audio Codec"</string>
@@ -209,6 +211,8 @@
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"Qiniseka izinhlelo zokusebenza nge-USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"Hlola izinhlelo zokusebenza ezifakiwe nge-ADB/ADT ngokuziphatha okuyingozi."</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"Ikhubaza isici esiphelele sevolumu ye-Bluetooth uma kuba nezinkinga zevolumu ngamadivayisi esilawuli kude ezifana nevolumu ephezulu noma eshoda ngokulawuleka."</string>
+    <!-- no translation found for bluetooth_enable_inband_ringing_summary (2787866074741784975) -->
+    <skip />
     <string name="enable_terminal_title" msgid="95572094356054120">"Itheminali yasendaweni"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"Nika amandla uhlelo lokusebenza letheminali olunikeza ukufinyelela kwasendaweni kwe-shell"</string>
     <string name="hdcp_checking_title" msgid="8605478913544273282">"Ihlola i-HDCP"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
index 5b2541c..2d8defa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/BatteryInfo.java
@@ -25,22 +25,21 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.text.format.Formatter;
-import android.util.Log;
 import android.util.SparseIntArray;
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.settingslib.graph.UsageView;
 
 public class BatteryInfo {
 
-    public String mChargeLabelString;
-    public int mBatteryLevel;
-    public boolean mDischarging = true;
+    public String chargeLabelString;
+    public int batteryLevel;
+    public boolean discharging = true;
     public long remainingTimeUs = 0;
     public String batteryPercentString;
     public String remainingLabel;
     public String statusLabel;
-    private BatteryStats mStats;
     private boolean mCharging;
+    private BatteryStats mStats;
     private long timePeriod;
 
     public interface Callback {
@@ -132,10 +131,11 @@
             BatteryStats stats, long elapsedRealtimeUs, boolean shortString) {
         BatteryInfo info = new BatteryInfo();
         info.mStats = stats;
-        info.mBatteryLevel = Utils.getBatteryLevel(batteryBroadcast);
-        info.batteryPercentString = Utils.formatPercentage(info.mBatteryLevel);
+        info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
+        info.batteryPercentString = Utils.formatPercentage(info.batteryLevel);
         info.mCharging = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
         final Resources resources = context.getResources();
+
         info.statusLabel = Utils.getBatteryStatus(resources, batteryBroadcast);
         if (!info.mCharging) {
             final long drainTime = stats.computeBatteryTimeRemaining(elapsedRealtimeUs);
@@ -147,20 +147,20 @@
                         shortString ? R.string.power_remaining_duration_only_short
                                 : R.string.power_remaining_duration_only,
                         timeString);
-                info.mChargeLabelString = resources.getString(
+                info.chargeLabelString = resources.getString(
                         shortString ? R.string.power_discharging_duration_short
                                 : R.string.power_discharging_duration,
                         info.batteryPercentString, timeString);
             } else {
                 info.remainingLabel = null;
-                info.mChargeLabelString = info.batteryPercentString;
+                info.chargeLabelString = info.batteryPercentString;
             }
         } else {
             final long chargeTime = stats.computeChargeTimeRemaining(elapsedRealtimeUs);
             final int status = batteryBroadcast.getIntExtra(BatteryManager.EXTRA_STATUS,
                     BatteryManager.BATTERY_STATUS_UNKNOWN);
+            info.discharging = false;
             if (chargeTime > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
-                info.mDischarging = false;
                 info.remainingTimeUs = chargeTime;
                 String timeString = Formatter.formatShortElapsedTime(context,
                         chargeTime / 1000);
@@ -168,13 +168,13 @@
                         : R.string.power_charging_duration;
                 info.remainingLabel = resources.getString(
                         R.string.power_remaining_charging_duration_only, timeString);
-                info.mChargeLabelString = resources.getString(resId, info.batteryPercentString,
-                        timeString);
+                info.chargeLabelString = resources.getString(
+                        resId, info.batteryPercentString, timeString);
             } else {
                 final String chargeStatusLabel = resources.getString(
                         R.string.battery_info_status_charging_lower);
                 info.remainingLabel = null;
-                info.mChargeLabelString = resources.getString(
+                info.chargeLabelString = resources.getString(
                         R.string.power_charging, info.batteryPercentString, chargeStatusLabel);
             }
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java
new file mode 100644
index 0000000..972ea34
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityButtonHelper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.accessibility;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
+
+import java.util.List;
+
+/**
+ * A helper class to assist determining the state of the accessibility button that can appear
+ * within the software-rendered navigation area.
+ */
+public class AccessibilityButtonHelper {
+    public static boolean isRequestedByMagnification(Context ctx) {
+        return Settings.Secure.getInt(ctx.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 1;
+    }
+
+    public static boolean isRequestedByAccessibilityService(Context ctx) {
+        final AccessibilityManager accessibilityManager = ctx.getSystemService(
+                AccessibilityManager.class);
+        List<AccessibilityServiceInfo> services =
+                accessibilityManager.getEnabledAccessibilityServiceList(
+                        AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+        if (services != null) {
+            for (int i = 0, size = services.size(); i < size; i++) {
+                if ((services.get(i).flags
+                        & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON)
+                        != 0) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isRequested(Context ctx) {
+        return isRequestedByMagnification(ctx) || isRequestedByAccessibilityService(ctx);
+    }
+
+    public static boolean isDeviceSupported(Resources res) {
+        return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 296b4d6f..c109704 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -29,6 +29,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageStats;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
@@ -45,6 +46,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.format.Formatter;
+import android.util.IconDrawableFactory;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -52,6 +54,7 @@
 import com.android.settingslib.R;
 
 import java.io.File;
+import java.io.IOException;
 import java.text.Collator;
 import java.text.Normalizer;
 import java.text.Normalizer.Form;
@@ -61,6 +64,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Objects;
+import java.util.UUID;
 import java.util.regex.Pattern;
 
 /**
@@ -92,6 +96,7 @@
 
     final Context mContext;
     final PackageManager mPm;
+    final IconDrawableFactory mDrawableFactory;
     final IPackageManager mIpm;
     final UserManager mUm;
     final StorageStatsManager mStats;
@@ -114,7 +119,7 @@
     final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
     List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();
     long mCurId = 1;
-    String mCurComputingSizeUuid;
+    UUID mCurComputingSizeUuid;
     String mCurComputingSizePkg;
     int mCurComputingSizeUserId;
     boolean mSessionsChanged;
@@ -129,6 +134,7 @@
     private ApplicationsState(Application app) {
         mContext = app;
         mPm = mContext.getPackageManager();
+        mDrawableFactory = IconDrawableFactory.newInstance(mContext);
         mIpm = AppGlobals.getPackageManager();
         mUm = mContext.getSystemService(UserManager.class);
         mStats = mContext.getSystemService(StorageStatsManager.class);
@@ -324,7 +330,7 @@
             return;
         }
         synchronized (entry) {
-            entry.ensureIconLocked(mContext, mPm);
+            entry.ensureIconLocked(mContext, mDrawableFactory);
         }
     }
 
@@ -334,15 +340,23 @@
             AppEntry entry = mEntriesMap.get(userId).get(packageName);
             if (entry != null && (entry.info.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
                 mBackgroundHandler.post(() -> {
-                    final StorageStats stats = mStats.queryStatsForPackage(entry.info.volumeUuid,
-                            packageName, UserHandle.of(userId));
-                    final PackageStats legacyStats = new PackageStats(packageName, userId);
-                    legacyStats.codeSize = stats.getCodeBytes();
-                    legacyStats.dataSize = stats.getDataBytes();
-                    legacyStats.cacheSize = stats.getCacheBytes();
                     try {
-                        mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacyStats, true);
-                    } catch (RemoteException ignored) {
+                        final StorageStats stats = mStats.queryStatsForPackage(
+                                entry.info.storageUuid, packageName, UserHandle.of(userId));
+                        final PackageStats legacy = new PackageStats(packageName, userId);
+                        legacy.codeSize = stats.getCodeBytes();
+                        legacy.dataSize = stats.getDataBytes();
+                        legacy.cacheSize = stats.getCacheBytes();
+                        try {
+                            mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacy, true);
+                        } catch (RemoteException ignored) {
+                        }
+                    } catch (NameNotFoundException | IOException e) {
+                        Log.w(TAG, "Failed to query stats: " + e);
+                        try {
+                            mBackgroundHandler.mStatsObserver.onGetStatsCompleted(null, false);
+                        } catch (RemoteException ignored) {
+                        }
                     }
                 });
             }
@@ -932,7 +946,7 @@
                             AppEntry entry = mAppEntries.get(i);
                             if (entry.icon == null || !entry.mounted) {
                                 synchronized (entry) {
-                                    if (entry.ensureIconLocked(mContext, mPm)) {
+                                    if (entry.ensureIconLocked(mContext, mDrawableFactory)) {
                                         if (!mRunning) {
                                             mRunning = true;
                                             Message m = mMainHandler.obtainMessage(
@@ -979,23 +993,32 @@
                                         mMainHandler.sendMessage(m);
                                     }
                                     entry.sizeLoadStart = now;
-                                    mCurComputingSizeUuid = entry.info.volumeUuid;
+                                    mCurComputingSizeUuid = entry.info.storageUuid;
                                     mCurComputingSizePkg = entry.info.packageName;
                                     mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
 
                                     mBackgroundHandler.post(() -> {
-                                        final StorageStats stats = mStats.queryStatsForPackage(
-                                                mCurComputingSizeUuid, mCurComputingSizePkg,
-                                                UserHandle.of(mCurComputingSizeUserId));
-                                        final PackageStats legacyStats = new PackageStats(
-                                                mCurComputingSizePkg, mCurComputingSizeUserId);
-                                        legacyStats.codeSize = stats.getCodeBytes();
-                                        legacyStats.dataSize = stats.getDataBytes();
-                                        legacyStats.cacheSize = stats.getCacheBytes();
                                         try {
-                                            mStatsObserver.onGetStatsCompleted(legacyStats, true);
-                                        } catch (RemoteException ignored) {
+                                            final StorageStats stats = mStats.queryStatsForPackage(
+                                                    mCurComputingSizeUuid, mCurComputingSizePkg,
+                                                    UserHandle.of(mCurComputingSizeUserId));
+                                            final PackageStats legacy = new PackageStats(
+                                                    mCurComputingSizePkg, mCurComputingSizeUserId);
+                                            legacy.codeSize = stats.getCodeBytes();
+                                            legacy.dataSize = stats.getDataBytes();
+                                            legacy.cacheSize = stats.getCacheBytes();
+                                            try {
+                                                mStatsObserver.onGetStatsCompleted(legacy, true);
+                                            } catch (RemoteException ignored) {
+                                            }
+                                        } catch (NameNotFoundException | IOException e) {
+                                            Log.w(TAG, "Failed to query stats: " + e);
+                                            try {
+                                                mStatsObserver.onGetStatsCompleted(null, false);
+                                            } catch (RemoteException ignored) {
+                                            }
                                         }
+
                                     });
                                 }
                                 if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
@@ -1246,10 +1269,10 @@
             }
         }
 
-        boolean ensureIconLocked(Context context, PackageManager pm) {
+        boolean ensureIconLocked(Context context, IconDrawableFactory drawableFactory) {
             if (this.icon == null) {
                 if (this.apkFile.exists()) {
-                    this.icon = getBadgedIcon(pm);
+                    this.icon = drawableFactory.getBadgedIcon(info);
                     return true;
                 } else {
                     this.mounted = false;
@@ -1261,19 +1284,13 @@
                 // its icon.
                 if (this.apkFile.exists()) {
                     this.mounted = true;
-                    this.icon = getBadgedIcon(pm);
+                    this.icon = drawableFactory.getBadgedIcon(info);
                     return true;
                 }
             }
             return false;
         }
 
-        private Drawable getBadgedIcon(PackageManager pm) {
-            // Do badging ourself so that it comes from the user of the app not the current user.
-            return pm.getUserBadgedIcon(pm.loadUnbadgedItemIcon(info, info),
-                    new UserHandle(UserHandle.getUserId(info.uid)));
-        }
-
         public String getVersion(Context context) {
             try {
                 return context.getPackageManager().getPackageInfo(info.packageName, 0).versionName;
@@ -1493,7 +1510,8 @@
 
         @Override
         public boolean filterApp(AppEntry entry) {
-            return (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
+            return !AppUtils.isInstant(entry.info)
+                && (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
         }
     };
 
@@ -1616,20 +1634,21 @@
         }
     };
 
-    public static final AppFilter FILTER_OTHER_APPS = new AppFilter() {
-        @Override
-        public void init() {
-        }
+    public static final AppFilter FILTER_OTHER_APPS =
+            new AppFilter() {
+                @Override
+                public void init() {}
 
-        @Override
-        public boolean filterApp(AppEntry entry) {
-            boolean isCategorized;
-            synchronized(entry) {
-                isCategorized = entry.info.category == ApplicationInfo.CATEGORY_AUDIO ||
-                    entry.info.category == ApplicationInfo.CATEGORY_GAME ||
-                    entry.info.category == ApplicationInfo.CATEGORY_VIDEO;
-            }
-            return !isCategorized;
-        }
-    };
+                @Override
+                public boolean filterApp(AppEntry entry) {
+                    boolean isCategorized;
+                    synchronized (entry) {
+                        isCategorized =
+                                FILTER_AUDIO.filterApp(entry)
+                                        || FILTER_GAMES.filterApp(entry)
+                                        || FILTER_MOVIES.filterApp(entry);
+                    }
+                    return !isCategorized;
+                }
+            };
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
index 2183573..34fdc9d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
@@ -19,9 +19,12 @@
 import android.app.usage.StorageStats;
 import android.app.usage.StorageStatsManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.support.annotation.VisibleForTesting;
 
+import java.io.IOException;
+
 /**
  * StorageStatsSource wraps the StorageStatsManager for testability purposes.
  */
@@ -32,17 +35,21 @@
         mStorageStatsManager = context.getSystemService(StorageStatsManager.class);
     }
 
-    public StorageStatsSource.ExternalStorageStats getExternalStorageStats(String volumeUuid, UserHandle user) {
+    public StorageStatsSource.ExternalStorageStats getExternalStorageStats(String volumeUuid,
+            UserHandle user) throws IOException {
         return new StorageStatsSource.ExternalStorageStats(
                 mStorageStatsManager.queryExternalStatsForUser(volumeUuid, user));
     }
 
-    public StorageStatsSource.AppStorageStats getStatsForUid(String volumeUuid, int uid) {
-        return new StorageStatsSource.AppStorageStatsImpl(mStorageStatsManager.queryStatsForUid(volumeUuid, uid));
+    public StorageStatsSource.AppStorageStats getStatsForUid(String volumeUuid, int uid)
+            throws IOException {
+        return new StorageStatsSource.AppStorageStatsImpl(
+                mStorageStatsManager.queryStatsForUid(volumeUuid, uid));
     }
 
     public StorageStatsSource.AppStorageStats getStatsForPackage(
-            String volumeUuid, String packageName, UserHandle user) {
+            String volumeUuid, String packageName, UserHandle user)
+            throws PackageManager.NameNotFoundException, IOException {
         return new StorageStatsSource.AppStorageStatsImpl(
                 mStorageStatsManager.queryStatsForPackage(volumeUuid, packageName, user));
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index bd37abe..28137ff 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -32,7 +32,7 @@
 import java.util.Collection;
 import java.util.List;
 
-final class PbapClientProfile implements LocalBluetoothProfile {
+public final class PbapClientProfile implements LocalBluetoothProfile {
     private static final String TAG = "PbapClientProfile";
     private static boolean V = false;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
index 88f133c..ccf7a0b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/PrivateStorageInfo.java
@@ -20,11 +20,16 @@
 import android.app.usage.StorageStatsManager;
 import android.content.Context;
 import android.os.storage.VolumeInfo;
+import android.util.Log;
+
+import java.io.IOException;
 
 /**
  * PrivateStorageInfo provides information about the total and free storage on the device.
  */
 public class PrivateStorageInfo {
+    private static final String TAG = "PrivateStorageInfo";
+
     public final long freeBytes;
     public final long totalBytes;
 
@@ -41,8 +46,12 @@
         long privateTotalBytes = 0;
         for (VolumeInfo info : sm.getVolumes()) {
             if (info.getType() == VolumeInfo.TYPE_PRIVATE && info.isMountedReadable()) {
-                privateTotalBytes += sm.getTotalBytes(stats, info);
-                privateFreeBytes += sm.getFreeBytes(stats, info);
+                try {
+                    privateTotalBytes += sm.getTotalBytes(stats, info);
+                    privateFreeBytes += sm.getFreeBytes(stats, info);
+                } catch (IOException e) {
+                    Log.w(TAG, e);
+                }
             }
         }
         return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
@@ -51,6 +60,11 @@
     public static long getTotalSize(VolumeInfo info, long totalInternalStorage) {
         final Context context = AppGlobals.getInitialApplication();
         final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
-        return stats.getTotalBytes(info.getFsUuid());
+        try {
+            return stats.getTotalBytes(info.getFsUuid());
+        } catch (IOException e) {
+            Log.w(TAG, e);
+            return 0;
+        }
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
index 11060e6..b57b6cc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageManagerVolumeProvider.java
@@ -20,6 +20,7 @@
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -49,12 +50,12 @@
     }
 
     @Override
-    public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) {
+    public long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException {
         return stats.getTotalBytes(volume.getFsUuid());
     }
 
     @Override
-    public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) {
+    public long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException {
         return stats.getFreeBytes(volume.getFsUuid());
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 60e10a1..ea28fe6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -32,6 +32,7 @@
 import android.util.SparseArray;
 import android.util.SparseLongArray;
 
+import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import java.util.List;
@@ -154,7 +155,7 @@
         try {
             details.totalSize = mStats.getTotalBytes(mVolume.fsUuid);
             details.availSize = mStats.getFreeBytes(mVolume.fsUuid);
-        } catch (IllegalStateException e) {
+        } catch (IOException e) {
             // The storage volume became null while we were measuring it.
             Log.w(TAG, e);
             return details;
@@ -169,8 +170,14 @@
                 final HashMap<String, Long> mediaMap = new HashMap<>();
                 details.mediaSize.put(user.id, mediaMap);
 
-                final ExternalStorageStats stats = mStats
-                        .queryExternalStatsForUser(mSharedVolume.fsUuid, UserHandle.of(user.id));
+                final ExternalStorageStats stats;
+                try {
+                    stats = mStats.queryExternalStatsForUser(mSharedVolume.fsUuid,
+                            UserHandle.of(user.id));
+                } catch (IOException e) {
+                    Log.w(TAG, e);
+                    continue;
+                }
 
                 addValue(details.usersSize, user.id, stats.getTotalBytes());
 
@@ -190,8 +197,13 @@
 
         if ((mVolume.getType() == VolumeInfo.TYPE_PRIVATE) && mVolume.isMountedReadable()) {
             for (UserInfo user : users) {
-                final StorageStats stats = mStats.queryStatsForUser(mVolume.fsUuid,
-                        UserHandle.of(user.id));
+                final StorageStats stats;
+                try {
+                    stats = mStats.queryStatsForUser(mVolume.fsUuid, UserHandle.of(user.id));
+                } catch (IOException e) {
+                    Log.w(TAG, e);
+                    continue;
+                }
 
                 // Only count code once against current user
                 if (user.id == UserHandle.myUserId()) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
index e5d85d1..4c45413 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageVolumeProvider.java
@@ -19,6 +19,7 @@
 import android.app.usage.StorageStatsManager;
 import android.os.storage.VolumeInfo;
 
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -46,12 +47,12 @@
      *
      * @pre The volume is a private volume and is readable.
      */
-    long getTotalBytes(StorageStatsManager stats, VolumeInfo volume);
+    long getTotalBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException;
 
     /**
      * Returns the free bytes for a given storage volume.
      *
      * @pre The volume is a private volume and is readable.
      */
-    long getFreeBytes(StorageStatsManager stats, VolumeInfo volume);
+    long getFreeBytes(StorageStatsManager stats, VolumeInfo volume) throws IOException;
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
index d6bde81..9d09737 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -40,6 +40,8 @@
             "com.android.settings.category.ia.language";
     public static final String CATEGORY_SYSTEM_DEVELOPMENT =
             "com.android.settings.category.ia.development";
+    public static final String CATEGORY_NOTIFICATIONS =
+            "com.android.settings.category.ia.notifications";
 
     public static final Map<String, String> KEY_COMPAT_MAP;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index 61ca13d..9d6505b 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -40,9 +40,15 @@
     public static final String TAG = BatteryMeterDrawableBase.class.getSimpleName();
 
     protected final Context mContext;
+    protected final Paint mFramePaint;
+    protected final Paint mBatteryPaint;
+    protected final Paint mWarningTextPaint;
+    protected final Paint mTextPaint;
+    protected final Paint mBoltPaint;
+    protected final Paint mPlusPaint;
 
     private int mLevel = -1;
-    private boolean mPluggedIn;
+    private boolean mCharging;
     private boolean mPowerSaveEnabled;
     private boolean mShowPercent;
 
@@ -59,8 +65,6 @@
     private float mButtonHeightFraction;
     private float mSubpixelSmoothingLeft;
     private float mSubpixelSmoothingRight;
-    private final Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint,
-            mPlusPaint;
     private float mTextHeight, mWarningTextHeight;
     private int mIconTint = Color.WHITE;
     private float mOldDarkIntensity = -1f;
@@ -180,16 +184,24 @@
         postInvalidate();
     }
 
-    public void setPluggedIn(boolean val) {
-        mPluggedIn = val;
+    public void setCharging(boolean val) {
+        mCharging = val;
         postInvalidate();
     }
 
+    public boolean getCharging() {
+        return mCharging;
+    }
+
     public void setBatteryLevel(int val) {
         mLevel = val;
         postInvalidate();
     }
 
+    public int getBatteryLevel() {
+        return mLevel;
+    }
+
     public void setPowerSave(boolean val) {
         mPowerSaveEnabled = val;
         postInvalidate();
@@ -314,7 +326,7 @@
         mFrame.bottom -= mSubpixelSmoothingRight;
 
         // set the battery charging color
-        mBatteryPaint.setColor(mPluggedIn ? mChargeColor : getColorForLevel(level));
+        mBatteryPaint.setColor(mCharging ? mChargeColor : getColorForLevel(level));
 
         if (level >= FULL) {
             drawFrac = 1f;
@@ -337,7 +349,7 @@
         mShapePath.lineTo(mButtonFrame.left, mFrame.top);
         mShapePath.lineTo(mButtonFrame.left, mButtonFrame.top);
 
-        if (mPluggedIn) {
+        if (mCharging) {
             // define the bolt shape
             final float bl = mFrame.left + mFrame.width() / 4f;
             final float bt = mFrame.top + mFrame.height() / 6f;
@@ -408,7 +420,7 @@
         boolean pctOpaque = false;
         float pctX = 0, pctY = 0;
         String pctText = null;
-        if (!mPluggedIn && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) {
+        if (!mCharging && !mPowerSaveEnabled && level > mCriticalLevel && mShowPercent) {
             mTextPaint.setColor(getColorForLevel(level));
             mTextPaint.setTextSize(height *
                     (SINGLE_DIGIT_PERCENT ? 0.75f
@@ -436,7 +448,7 @@
         mShapePath.op(mClipPath, Path.Op.INTERSECT);
         c.drawPath(mShapePath, mBatteryPaint);
 
-        if (!mPluggedIn && !mPowerSaveEnabled) {
+        if (!mCharging && !mPowerSaveEnabled) {
             if (level <= mCriticalLevel) {
                 // draw the warning text
                 final float x = mWidth * 0.5f;
@@ -467,4 +479,8 @@
     public int getOpacity() {
         return 0;
     }
+
+    public int getCriticalLevel() {
+        return mCriticalLevel;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
index c6a45bc..e2c05a1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/UsageView.java
@@ -35,15 +35,15 @@
     public UsageView(Context context, AttributeSet attrs) {
         super(context, attrs);
         LayoutInflater.from(context).inflate(R.layout.usage_view, this);
-        mUsageGraph = (UsageGraph) findViewById(R.id.usage_graph);
+        mUsageGraph = findViewById(R.id.usage_graph);
         mLabels = new TextView[] {
-                (TextView) findViewById(R.id.label_bottom),
-                (TextView) findViewById(R.id.label_middle),
-                (TextView) findViewById(R.id.label_top),
+                findViewById(R.id.label_bottom),
+                findViewById(R.id.label_middle),
+                findViewById(R.id.label_top),
         };
         mBottomLabels = new TextView[] {
-                (TextView) findViewById(R.id.label_start),
-                (TextView) findViewById(R.id.label_end),
+                findViewById(R.id.label_start),
+                findViewById(R.id.label_end),
         };
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.UsageView, 0, 0);
         if (a.hasValue(R.styleable.UsageView_sideLabels)) {
@@ -64,15 +64,15 @@
         if (a.hasValue(R.styleable.UsageView_android_gravity)) {
             int gravity = a.getInt(R.styleable.UsageView_android_gravity, 0);
             if (gravity == Gravity.END) {
-                LinearLayout layout = (LinearLayout) findViewById(R.id.graph_label_group);
-                LinearLayout labels = (LinearLayout) findViewById(R.id.label_group);
+                LinearLayout layout = findViewById(R.id.graph_label_group);
+                LinearLayout labels = findViewById(R.id.label_group);
                 // Swap the children order.
                 layout.removeView(labels);
                 layout.addView(labels);
                 // Set gravity.
                 labels.setGravity(Gravity.END);
                 // Swap the bottom space order.
-                LinearLayout bottomLabels = (LinearLayout) findViewById(R.id.bottom_label_group);
+                LinearLayout bottomLabels = findViewById(R.id.bottom_label_group);
                 View bottomSpace = bottomLabels.findViewById(R.id.bottom_label_space);
                 bottomLabels.removeView(bottomSpace);
                 bottomLabels.addView(bottomSpace);
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
index 231fc69..3f826cc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
@@ -27,6 +27,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.IconDrawableFactory;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -48,10 +49,12 @@
 
     private final PackageManager mPackageManager;
     private final Context mContext;
+    private final IconDrawableFactory mDrawableFactory;
 
     public RecentLocationApps(Context context) {
         mContext = context;
         mPackageManager = context.getPackageManager();
+        mDrawableFactory = IconDrawableFactory.newInstance(context);
     }
 
     /**
@@ -146,8 +149,7 @@
             }
 
             final UserHandle userHandle = new UserHandle(userId);
-            Drawable appIcon = mPackageManager.getApplicationIcon(appInfo);
-            Drawable icon = mPackageManager.getUserBadgedIcon(appIcon, userHandle);
+            Drawable icon = mDrawableFactory.getBadgedIcon(appInfo, userId);
             CharSequence appLabel = mPackageManager.getApplicationLabel(appInfo);
             CharSequence badgedAppLabel = mPackageManager.getUserBadgedLabel(appLabel, userHandle);
             if (appLabel.toString().contentEquals(badgedAppLabel)) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 901848a..9e9bc93 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -985,25 +985,32 @@
         return false;
     }
 
+    /** Attempt to update the AccessPoint and return true if an update occurred. */
     public boolean update(WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
-        boolean reorder = false;
+        boolean updated = false;
+        final int oldLevel = getLevel();
         if (info != null && isInfoForThisAccessPoint(config, info)) {
-            reorder = (mInfo == null);
-            mRssi = info.getRssi();
-            mInfo = info;
-            mNetworkInfo = networkInfo;
-            if (mAccessPointListener != null) {
-                mAccessPointListener.onAccessPointChanged(this);
+            updated = (mInfo == null);
+            if (mRssi != info.getRssi()) {
+                mRssi = info.getRssi();
+                updated = true;
             }
+            mInfo = info;
+            // TODO(b/37289220): compare NetworkInfo states and set updated = true if necessary
+            mNetworkInfo = networkInfo;
         } else if (mInfo != null) {
-            reorder = true;
+            updated = true;
             mInfo = null;
             mNetworkInfo = null;
-            if (mAccessPointListener != null) {
-                mAccessPointListener.onAccessPointChanged(this);
+        }
+        if (updated && mAccessPointListener != null) {
+            mAccessPointListener.onAccessPointChanged(this);
+
+            if (oldLevel != getLevel() /* current level */) {
+                mAccessPointListener.onLevelChanged(this);
             }
         }
-        return reorder;
+        return updated;
     }
 
     void update(WifiConfiguration config) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index fc8c42c..314791e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -203,6 +203,7 @@
         mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
         mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
         mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
 
         mNetworkRequest = new NetworkRequest.Builder()
                 .clearCapabilities()
@@ -233,10 +234,19 @@
     }
 
     /**
-     * Forces an update of the wifi networks when not scanning.
+     * Synchronously update the list of access points with the latest information.
      */
     public void forceUpdate() {
+        mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+
+        mLastInfo = mWifiManager.getConnectionInfo();
+        mLastNetworkInfo = mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
         updateAccessPoints();
+
+        // Synchronously copy access points
+        mMainHandler.removeMessages(MainHandler.MSG_ACCESS_POINT_CHANGED);
+        mMainHandler.handleMessage(
+                Message.obtain(mMainHandler, MainHandler.MSG_ACCESS_POINT_CHANGED));
     }
 
     /**
@@ -640,20 +650,24 @@
                     (System.currentTimeMillis() - before) + "ms.");
         }
 
-        boolean reorder = false;
+        boolean updated = false;
+        boolean reorder = false; // Only reorder if connected AP was changed
         for (int i = mInternalAccessPoints.size() - 1; i >= 0; --i) {
             AccessPoint ap = mInternalAccessPoints.get(i);
+            boolean previouslyConnected = ap.isActive();
             if (ap.update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
-                reorder = true;
+                updated = true;
+                if (previouslyConnected != ap.isActive()) reorder = true;
             }
             if (ap.update(mScoreCache, mNetworkScoringUiEnabled)) {
                 reorder = true;
+                updated = true;
             }
         }
-        if (reorder) {
-            Collections.sort(mInternalAccessPoints);
-            mMainHandler.scheduleAPCopyingAndCloseWriteLock();
-        }
+
+        if (reorder) Collections.sort(mInternalAccessPoints);
+
+        if (updated) mMainHandler.scheduleAPCopyingAndCloseWriteLock();
     }
 
     /**
@@ -718,6 +732,8 @@
                 mWorkHandler.obtainMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO, info)
                         .sendToTarget();
                 mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
+            } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
+                mWorkHandler.sendEmptyMessage(WorkHandler.MSG_UPDATE_NETWORK_INFO);
             }
         }
     };
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
index d6ab8d2..fed18fa1 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/applications/ApplicationsStateTest.java
@@ -174,6 +174,13 @@
     }
 
     @Test
+    public void testOtherAppsRejectsLegacyGame() {
+        mEntry.info.flags = ApplicationInfo.FLAG_IS_GAME;
+
+        assertThat(ApplicationsState.FILTER_OTHER_APPS.filterApp(mEntry)).isFalse();
+    }
+
+    @Test
     public void testInstantFilterAcceptsInstantApp() {
         when(mEntry.info.isInstantApp()).thenReturn(true);
         assertThat(ApplicationsState.FILTER_INSTANT.filterApp(mEntry)).isTrue();
@@ -194,6 +201,22 @@
     }
 
     @Test
+    public void testFilterWithDomainUrls() {
+        mEntry.info.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+        // should included updated system apps
+        when(mEntry.info.isInstantApp()).thenReturn(false);
+        assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+                .isTrue();
+        mEntry.info.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+        assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+                .isFalse();
+        mEntry.info.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
+        when(mEntry.info.isInstantApp()).thenReturn(true);
+        assertThat(ApplicationsState.FILTER_WITH_DOMAIN_URLS.filterApp(mEntry))
+                .isFalse();
+    }
+
+    @Test
     public void testDisabledFilterRejectsInstantApp() {
         mEntry.info.enabled = false;
         assertThat(ApplicationsState.FILTER_DISABLED.filterApp(mEntry)).isTrue();
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index 4de2c12..83667ea 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -55,12 +55,12 @@
         final int levels[] = { 0, 1, 5, 10, 25, 50, 75, 90, 95, 99, 100 };
         final boolean bools[] = { false, true };
         for (int l : levels) {
-            for (boolean plugged : bools) {
+            for (boolean charging : bools) {
                 for (boolean saver : bools) {
                     for (boolean percent : bools) {
                         mBatteryDrawable.setBatteryLevel(l);
                         mBatteryDrawable.setPowerSave(saver);
-                        mBatteryDrawable.setPluggedIn(plugged);
+                        mBatteryDrawable.setCharging(charging);
                         mBatteryDrawable.setShowPercent(percent);
                         mBatteryDrawable.draw(canvas);
                     }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
index 85b04c8..820231e 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
@@ -159,14 +159,14 @@
         for (String pkg : defaultImes) {
             final ResolveInfo ri = createResolveInfoForSystemApp(pkg);
             final InputMethodInfo inputMethodInfo = new InputMethodInfo(
-                    ri, false, null, null, 0, true, true, false);
+                    ri, false, null, null, 0, true, true);
             inputMethods.add(inputMethodInfo);
             addInstalledApp(ri);
         }
         for (String pkg : otherImes) {
             final ResolveInfo ri = createResolveInfoForSystemApp(pkg);
             final InputMethodInfo inputMethodInfo = new InputMethodInfo(
-                    ri, false, null, null, 0, false, true, false);
+                    ri, false, null, null, 0, false, true);
             inputMethods.add(inputMethodInfo);
             addInstalledApp(ri);
         }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index b71915f3..b938fe2 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -20,9 +20,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doThrow;
@@ -32,12 +32,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.net.Network;
 import android.net.NetworkBadging;
 import android.net.NetworkInfo;
 import android.net.NetworkKey;
 import android.net.NetworkScoreManager;
-import android.net.ScoredNetwork;
 import android.net.RssiCurve;
+import android.net.ScoredNetwork;
 import android.net.WifiKey;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
@@ -46,10 +47,10 @@
 import android.net.wifi.WifiNetworkScoreCache;
 import android.net.wifi.WifiSsid;
 import android.os.Bundle;
-import android.os.SystemClock;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
@@ -61,8 +62,8 @@
 import org.junit.runner.RunWith;
 
 import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
 import org.mockito.Captor;
+import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
@@ -100,6 +101,16 @@
     private static final byte SCORE_2 = 15;
     private static final int BADGE_2 = NetworkBadging.BADGING_HD;
 
+    private static final int CONNECTED_NETWORK_ID = 123;
+    private static final int CONNECTED_RSSI = -50;
+    private static final WifiInfo CONNECTED_AP_1_INFO = new WifiInfo();
+    static {
+        CONNECTED_AP_1_INFO.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
+        CONNECTED_AP_1_INFO.setBSSID(BSSID_1);
+        CONNECTED_AP_1_INFO.setNetworkId(CONNECTED_NETWORK_ID);
+        CONNECTED_AP_1_INFO.setRssi(CONNECTED_RSSI);
+    }
+
     @Captor ArgumentCaptor<WifiNetworkScoreCache> mScoreCacheCaptor;
     @Mock private ConnectivityManager mockConnectivityManager;
     @Mock private NetworkScoreManager mockNetworkScoreManager;
@@ -312,18 +323,12 @@
 
     private WifiTracker createTrackerWithScanResultsAndAccessPoint1Connected()
             throws InterruptedException {
-        int networkId = 123;
-
-        WifiInfo wifiInfo = new WifiInfo();
-        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
-        wifiInfo.setBSSID(BSSID_1);
-        wifiInfo.setNetworkId(networkId);
-        when(mockWifiManager.getConnectionInfo()).thenReturn(wifiInfo);
+        when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
 
         WifiConfiguration configuration = new WifiConfiguration();
         configuration.SSID = SSID_1;
         configuration.BSSID = BSSID_1;
-        configuration.networkId = networkId;
+        configuration.networkId = CONNECTED_NETWORK_ID;
         when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
 
         NetworkInfo networkInfo = new NetworkInfo(
@@ -445,7 +450,8 @@
     }
 
     @Test
-    public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged() throws InterruptedException {
+    public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged()
+            throws InterruptedException {
         WifiTracker tracker = createMockedWifiTracker();
         startTracking(tracker);
         sendScanResultsAndProcess(tracker);
@@ -463,7 +469,7 @@
 
     @Test
     public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
-        WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
+        WifiTracker tracker =  createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         List<AccessPoint> aps = tracker.getAccessPoints();
         assertTrue(aps.size() == 2);
         assertEquals(aps.get(0).getSsidStr(), SSID_1);
@@ -636,4 +642,53 @@
         tracker.forceUpdate();
         verify(mockWifiManager).getMatchingWifiConfig(any(ScanResult.class));
     }
-}
+
+    @Test
+    public void rssiChangeBroadcastShouldUpdateConnectedAp() throws Exception {
+        WifiTracker tracker =  createTrackerWithScanResultsAndAccessPoint1Connected();
+        assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
+
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = SSID_1;
+        configuration.BSSID = BSSID_1;
+        configuration.networkId = CONNECTED_NETWORK_ID;
+        when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
+
+        int newRssi = CONNECTED_RSSI + 10;
+        WifiInfo info = new WifiInfo(CONNECTED_AP_1_INFO);
+        info.setRssi(newRssi);
+        when(mockWifiManager.getConnectionInfo()).thenReturn(info);
+
+        mAccessPointsChangedLatch = new CountDownLatch(1);
+        tracker.mReceiver.onReceive(mContext, new Intent(WifiManager.RSSI_CHANGED_ACTION));
+        assertTrue(mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
+
+        verify(mockWifiManager, atLeast(2)).getConnectionInfo();
+        assertThat(tracker.getAccessPoints().get(0).getRssi()).isEqualTo(newRssi);
+    }
+
+    @Test
+    public void forceUpdateShouldSynchronouslyFetchLatestInformation() throws Exception {
+        when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
+
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = SSID_1;
+        configuration.BSSID = BSSID_1;
+        configuration.networkId = CONNECTED_NETWORK_ID;
+        when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
+
+        NetworkInfo networkInfo = new NetworkInfo(
+                ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
+        when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(networkInfo);
+
+
+        WifiTracker tracker = createMockedWifiTracker();
+        startTracking(tracker);
+        tracker.forceUpdate();
+
+        verify(mockWifiListener).onAccessPointsChanged();
+        assertThat(tracker.getAccessPoints().size()).isEqualTo(2);
+        assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
index 962c4e7..69efc9e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/BatteryInfoTest.java
@@ -32,6 +32,7 @@
 import org.robolectric.annotation.Config;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.eq;
@@ -44,10 +45,12 @@
     private static final String STATUS_FULL = "Full";
     private static final String STATUS_CHARGING_NO_TIME = "Charging";
     private static final String STATUS_CHARGING_TIME = "Charging - 2h left";
+    private static final int PLUGGED_IN = 1;
     private static final long REMAINING_TIME_NULL = -1;
     private static final long REMAINING_TIME = 2;
     private Intent mDisChargingBatteryBroadcast;
     private Intent mChargingBatteryBroadcast;
+
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private BatteryStats mBatteryStats;
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -95,7 +98,7 @@
         BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
                 mBatteryStats, SystemClock.elapsedRealtime() * 1000, false);
 
-        assertThat(info.mChargeLabelString).isEqualTo(STATUS_CHARGING_TIME);
+        assertThat(info.chargeLabelString).isEqualTo(STATUS_CHARGING_TIME);
     }
 
     @Test
@@ -104,6 +107,14 @@
         BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
                 mBatteryStats, SystemClock.elapsedRealtime() * 1000, false);
 
-        assertThat(info.mChargeLabelString).isEqualTo(STATUS_CHARGING_NO_TIME);
+        assertThat(info.chargeLabelString).isEqualTo(STATUS_CHARGING_NO_TIME);
+    }
+
+    @Test
+    public void testGetBatteryInfo_pluggedIn_dischargingFalse() {
+        BatteryInfo info = BatteryInfo.getBatteryInfo(mContext, mChargingBatteryBroadcast,
+                mBatteryStats, SystemClock.elapsedRealtime() * 1000, true);
+
+        assertThat(info.discharging).isEqualTo(false);
     }
 }
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml
new file mode 100644
index 0000000..8cbd94b
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This contains disable esim buttonas shared by sim_pin/sim_puk screens -->
+<com.android.keyguard.KeyguardEsimArea
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:id="@+id/keyguard_disable_esim"
+    android:visibility="gone"
+    android:text="@string/disable_carrier_button_text"
+    style="?android:attr/buttonBarButtonStyle"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:textSize="@dimen/kg_status_line_font_size"
+    android:textColor="?android:attr/textColorSecondary"
+    android:textAllCaps="@bool/kg_use_all_caps" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index b0a93e6..fd681ca 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -42,9 +42,15 @@
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:orientation="vertical"
+            android:gravity="center"
             android:layout_weight="1"
             android:layoutDirection="ltr"
             >
+        <include layout="@layout/keyguard_esim_area"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_marginTop="@dimen/eca_overlap" />
+
         <RelativeLayout
                 android:id="@+id/row0"
                 android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index cf41bd3..040b429 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -43,9 +43,15 @@
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:orientation="vertical"
+            android:gravity="center"
             android:layout_weight="1"
             android:layoutDirection="ltr"
             >
+        <include layout="@layout/keyguard_esim_area"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_marginTop="@dimen/eca_overlap" />
+
         <RelativeLayout
                 android:id="@+id/row0"
                 android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 2f52227..e45dba6 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -116,6 +116,8 @@
     <!-- KeyguardPinView - accessibility support --><skip />
     <!-- Description of the Delete button in a KeyboardView. [CHAR LIMIT=NONE] -->
     <string name="keyboardview_keycode_delete">Delete</string>
+    <!-- Description of the button used to disable current carrier when the device supported embedded SIM. [CHAR LIMIT=30] -->
+    <string name="disable_carrier_button_text">Disable eSIM</string>
     <!-- Description of the Enter button in a KeyboardView. [CHAR LIMIT=NONE] -->
     <string name="keyboardview_keycode_enter">Enter</string>
 
@@ -132,9 +134,11 @@
     <!-- Instructions for using the pattern unlock screen -->
     <string name="kg_pattern_instructions">Draw your pattern</string>
     <!-- Instructions for using the SIM PIN unlock screen -->
-    <string name="kg_sim_pin_instructions">Enter SIM PIN</string>
+    <string name="kg_sim_pin_instructions">Enter SIM PIN.</string>
     <!-- Instructions for using the SIM PIN unlock screen when there's more than one SIM -->
-    <string name="kg_sim_pin_instructions_multi">Enter SIM PIN for \"<xliff:g id="carrier" example="CARD 1">%1$s</xliff:g>\"</string>
+    <string name="kg_sim_pin_instructions_multi">Enter SIM PIN for \"<xliff:g id="carrier" example="CARD 1">%1$s</xliff:g>\".</string>
+    <!-- Instructions for disabling eSIM carrier to unlock the phone with embedded SIM -->
+    <string name="kg_sim_lock_instructions_esim">Disable eSIM to use device without mobile service.</string>
     <!-- Instructions for using the PIN unlock screen -->
     <string name="kg_pin_instructions">Enter PIN</string>
     <!-- Instructions for using the password unlock screen -->
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_background_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_background_enter_animation.xml
deleted file mode 100644
index 9ab41d0..0000000
--- a/packages/SystemUI/res/anim/tv_pip_onboarding_background_enter_animation.xml
+++ /dev/null
@@ -1,25 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <objectAnimator
-        android:propertyName="alpha"
-        android:valueFrom="0"
-        android:valueTo="0.9"
-        android:interpolator="@android:interpolator/linear"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml
deleted file mode 100644
index 01c263b..0000000
--- a/packages/SystemUI/res/anim/tv_pip_onboarding_button_enter_animation.xml
+++ /dev/null
@@ -1,30 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <objectAnimator
-        android:propertyName="translationY"
-        android:valueFrom="114dp"
-        android:valueTo="0dp"
-        android:interpolator="@android:interpolator/fast_out_slow_in"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-    <objectAnimator
-        android:propertyName="alpha"
-        android:valueTo="1"
-        android:interpolator="@android:interpolator/linear"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml
deleted file mode 100644
index a12b3b6..0000000
--- a/packages/SystemUI/res/anim/tv_pip_onboarding_description_enter_animation.xml
+++ /dev/null
@@ -1,30 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <objectAnimator
-        android:propertyName="translationY"
-        android:valueFrom="84dp"
-        android:valueTo="0dp"
-        android:interpolator="@android:interpolator/fast_out_slow_in"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-    <objectAnimator
-        android:propertyName="alpha"
-        android:valueTo="1"
-        android:interpolator="@android:interpolator/linear"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml
deleted file mode 100644
index ae9677e..0000000
--- a/packages/SystemUI/res/anim/tv_pip_onboarding_image_enter_animation.xml
+++ /dev/null
@@ -1,30 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <objectAnimator
-        android:propertyName="translationY"
-        android:valueFrom="114dp"
-        android:valueTo="0dp"
-        android:interpolator="@android:interpolator/fast_out_slow_in"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-    <objectAnimator
-        android:propertyName="alpha"
-        android:valueTo="1"
-        android:interpolator="@android:interpolator/fast_out_slow_in"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml b/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml
deleted file mode 100644
index 4bde070..0000000
--- a/packages/SystemUI/res/anim/tv_pip_onboarding_title_enter_animation.xml
+++ /dev/null
@@ -1,30 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <objectAnimator
-        android:propertyName="translationY"
-        android:valueFrom="84dp"
-        android:valueTo="0dp"
-        android:interpolator="@android:interpolator/fast_out_slow_in"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-    <objectAnimator
-        android:propertyName="alpha"
-        android:valueTo="1"
-        android:interpolator="@android:interpolator/fast_out_slow_in"
-        android:duration="@integer/tv_pip_onboarding_anim_duration" />
-</set>
diff --git a/packages/SystemUI/res/anim/tv_pip_overlay_fade_in_animation.xml b/packages/SystemUI/res/anim/tv_pip_overlay_fade_in_animation.xml
deleted file mode 100644
index 33bceaa..0000000
--- a/packages/SystemUI/res/anim/tv_pip_overlay_fade_in_animation.xml
+++ /dev/null
@@ -1,21 +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.
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:propertyName="alpha"
-    android:valueTo="1"
-    android:interpolator="@android:interpolator/fast_out_slow_in"
-    android:duration="350" />
diff --git a/packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml b/packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml
deleted file mode 100644
index a12ddff..0000000
--- a/packages/SystemUI/res/anim/tv_pip_overlay_fade_out_animation.xml
+++ /dev/null
@@ -1,21 +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.
--->
-
-<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
-    android:propertyName="alpha"
-    android:valueTo="0"
-    android:interpolator="@android:interpolator/fast_out_slow_in"
-    android:duration="500" />
diff --git a/packages/SystemUI/res/color/segmented_button_text_selector.xml b/packages/SystemUI/res/color/segmented_button_text_selector.xml
index 537cbb8..d4f0181 100644
--- a/packages/SystemUI/res/color/segmented_button_text_selector.xml
+++ b/packages/SystemUI/res/color/segmented_button_text_selector.xml
@@ -18,4 +18,4 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_selected="true" android:color="?android:attr/textColorPrimary"/>
     <item android:alpha="0.58" android:color="?android:attr/colorForeground"/>
-</selector>
\ No newline at end of file
+</selector>
diff --git a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
index 6737c80..32f1ed7 100644
--- a/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
index d9e33eb..33826a6 100644
--- a/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
index 64daf20..c1157f4 100644
--- a/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_0.png b/packages/SystemUI/res/drawable-xhdpi/remote_0.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_1.png b/packages/SystemUI/res/drawable-xhdpi/remote_1.png
deleted file mode 100644
index 252ff5e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_10.png b/packages/SystemUI/res/drawable-xhdpi/remote_10.png
deleted file mode 100644
index 5e52b37..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_10.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_100.png b/packages/SystemUI/res/drawable-xhdpi/remote_100.png
deleted file mode 100644
index f604808..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_100.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_101.png b/packages/SystemUI/res/drawable-xhdpi/remote_101.png
deleted file mode 100644
index 0272e45..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_101.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_102.png b/packages/SystemUI/res/drawable-xhdpi/remote_102.png
deleted file mode 100644
index aaa35c0..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_102.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_103.png b/packages/SystemUI/res/drawable-xhdpi/remote_103.png
deleted file mode 100644
index 20f95a5..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_103.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_104.png b/packages/SystemUI/res/drawable-xhdpi/remote_104.png
deleted file mode 100644
index 052f23e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_104.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_105.png b/packages/SystemUI/res/drawable-xhdpi/remote_105.png
deleted file mode 100644
index c5c8256..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_105.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_106.png b/packages/SystemUI/res/drawable-xhdpi/remote_106.png
deleted file mode 100644
index 4e804fe..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_106.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_107.png b/packages/SystemUI/res/drawable-xhdpi/remote_107.png
deleted file mode 100644
index 76669cc..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_107.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_108.png b/packages/SystemUI/res/drawable-xhdpi/remote_108.png
deleted file mode 100644
index c1b2f3b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_108.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_109.png b/packages/SystemUI/res/drawable-xhdpi/remote_109.png
deleted file mode 100644
index 79e1d7b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_109.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_11.png b/packages/SystemUI/res/drawable-xhdpi/remote_11.png
deleted file mode 100644
index cfec6cb..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_11.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_110.png b/packages/SystemUI/res/drawable-xhdpi/remote_110.png
deleted file mode 100644
index d902297..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_110.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_111.png b/packages/SystemUI/res/drawable-xhdpi/remote_111.png
deleted file mode 100644
index e48ed0b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_111.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_112.png b/packages/SystemUI/res/drawable-xhdpi/remote_112.png
deleted file mode 100644
index 90dd1a2..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_112.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_113.png b/packages/SystemUI/res/drawable-xhdpi/remote_113.png
deleted file mode 100644
index 8fb4ad2..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_113.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_114.png b/packages/SystemUI/res/drawable-xhdpi/remote_114.png
deleted file mode 100644
index 76873fb..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_114.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_115.png b/packages/SystemUI/res/drawable-xhdpi/remote_115.png
deleted file mode 100644
index e923d4c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_115.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_116.png b/packages/SystemUI/res/drawable-xhdpi/remote_116.png
deleted file mode 100644
index 41d5124..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_116.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_117.png b/packages/SystemUI/res/drawable-xhdpi/remote_117.png
deleted file mode 100644
index eacde64..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_117.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_118.png b/packages/SystemUI/res/drawable-xhdpi/remote_118.png
deleted file mode 100644
index 5dc1fb0..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_118.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_119.png b/packages/SystemUI/res/drawable-xhdpi/remote_119.png
deleted file mode 100644
index a16f037..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_119.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_12.png b/packages/SystemUI/res/drawable-xhdpi/remote_12.png
deleted file mode 100644
index 28bb387..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_12.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_120.png b/packages/SystemUI/res/drawable-xhdpi/remote_120.png
deleted file mode 100644
index fe3ef41..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_120.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_121.png b/packages/SystemUI/res/drawable-xhdpi/remote_121.png
deleted file mode 100644
index ef2b892..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_121.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_122.png b/packages/SystemUI/res/drawable-xhdpi/remote_122.png
deleted file mode 100644
index 5342976..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_122.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_123.png b/packages/SystemUI/res/drawable-xhdpi/remote_123.png
deleted file mode 100644
index bb8a53a..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_123.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_124.png b/packages/SystemUI/res/drawable-xhdpi/remote_124.png
deleted file mode 100644
index b68337e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_124.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_125.png b/packages/SystemUI/res/drawable-xhdpi/remote_125.png
deleted file mode 100644
index 81fa3a7..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_125.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_126.png b/packages/SystemUI/res/drawable-xhdpi/remote_126.png
deleted file mode 100644
index 2339d74..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_126.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_127.png b/packages/SystemUI/res/drawable-xhdpi/remote_127.png
deleted file mode 100644
index 90d1e0b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_127.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_128.png b/packages/SystemUI/res/drawable-xhdpi/remote_128.png
deleted file mode 100644
index 6de4eb8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_128.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_129.png b/packages/SystemUI/res/drawable-xhdpi/remote_129.png
deleted file mode 100644
index 9086074..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_129.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_13.png b/packages/SystemUI/res/drawable-xhdpi/remote_13.png
deleted file mode 100644
index a1e212d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_13.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_130.png b/packages/SystemUI/res/drawable-xhdpi/remote_130.png
deleted file mode 100644
index 2bc9698..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_130.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_131.png b/packages/SystemUI/res/drawable-xhdpi/remote_131.png
deleted file mode 100644
index d18d2c6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_131.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_132.png b/packages/SystemUI/res/drawable-xhdpi/remote_132.png
deleted file mode 100644
index 10a00cd..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_132.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_133.png b/packages/SystemUI/res/drawable-xhdpi/remote_133.png
deleted file mode 100644
index 6f495b4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_133.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_134.png b/packages/SystemUI/res/drawable-xhdpi/remote_134.png
deleted file mode 100644
index 703f2c6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_134.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_135.png b/packages/SystemUI/res/drawable-xhdpi/remote_135.png
deleted file mode 100644
index f4105b0..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_135.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_136.png b/packages/SystemUI/res/drawable-xhdpi/remote_136.png
deleted file mode 100644
index 0c3a5bc..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_136.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_137.png b/packages/SystemUI/res/drawable-xhdpi/remote_137.png
deleted file mode 100644
index cbebc05..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_137.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_138.png b/packages/SystemUI/res/drawable-xhdpi/remote_138.png
deleted file mode 100644
index 6dfefb0..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_138.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_139.png b/packages/SystemUI/res/drawable-xhdpi/remote_139.png
deleted file mode 100644
index 1acfdd6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_139.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_14.png b/packages/SystemUI/res/drawable-xhdpi/remote_14.png
deleted file mode 100644
index a503cdf..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_14.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_140.png b/packages/SystemUI/res/drawable-xhdpi/remote_140.png
deleted file mode 100644
index 70d27c1..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_140.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_141.png b/packages/SystemUI/res/drawable-xhdpi/remote_141.png
deleted file mode 100644
index d523a0c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_141.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_142.png b/packages/SystemUI/res/drawable-xhdpi/remote_142.png
deleted file mode 100644
index ed6a65d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_142.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_143.png b/packages/SystemUI/res/drawable-xhdpi/remote_143.png
deleted file mode 100644
index 9b048e6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_143.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_144.png b/packages/SystemUI/res/drawable-xhdpi/remote_144.png
deleted file mode 100644
index 9e2337d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_144.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_145.png b/packages/SystemUI/res/drawable-xhdpi/remote_145.png
deleted file mode 100644
index 3f30629..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_145.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_146.png b/packages/SystemUI/res/drawable-xhdpi/remote_146.png
deleted file mode 100644
index 1288039..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_146.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_147.png b/packages/SystemUI/res/drawable-xhdpi/remote_147.png
deleted file mode 100644
index d060539..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_147.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_148.png b/packages/SystemUI/res/drawable-xhdpi/remote_148.png
deleted file mode 100644
index 5be839d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_148.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_149.png b/packages/SystemUI/res/drawable-xhdpi/remote_149.png
deleted file mode 100644
index 39d31ba..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_149.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_15.png b/packages/SystemUI/res/drawable-xhdpi/remote_15.png
deleted file mode 100644
index 5695595..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_15.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_150.png b/packages/SystemUI/res/drawable-xhdpi/remote_150.png
deleted file mode 100644
index ec2667c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_150.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_151.png b/packages/SystemUI/res/drawable-xhdpi/remote_151.png
deleted file mode 100644
index ec2667c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_151.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_152.png b/packages/SystemUI/res/drawable-xhdpi/remote_152.png
deleted file mode 100644
index a5d58c8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_152.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_153.png b/packages/SystemUI/res/drawable-xhdpi/remote_153.png
deleted file mode 100644
index a5d58c8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_153.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_154.png b/packages/SystemUI/res/drawable-xhdpi/remote_154.png
deleted file mode 100644
index a5d58c8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_154.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_155.png b/packages/SystemUI/res/drawable-xhdpi/remote_155.png
deleted file mode 100644
index 793d411..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_155.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_156.png b/packages/SystemUI/res/drawable-xhdpi/remote_156.png
deleted file mode 100644
index 793d411..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_156.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_157.png b/packages/SystemUI/res/drawable-xhdpi/remote_157.png
deleted file mode 100644
index f9d6cdc..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_157.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_158.png b/packages/SystemUI/res/drawable-xhdpi/remote_158.png
deleted file mode 100644
index da8d5d7..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_158.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_159.png b/packages/SystemUI/res/drawable-xhdpi/remote_159.png
deleted file mode 100644
index 1e0b097..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_159.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_16.png b/packages/SystemUI/res/drawable-xhdpi/remote_16.png
deleted file mode 100644
index 4ae106c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_16.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_160.png b/packages/SystemUI/res/drawable-xhdpi/remote_160.png
deleted file mode 100644
index 8aa68ad..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_160.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_161.png b/packages/SystemUI/res/drawable-xhdpi/remote_161.png
deleted file mode 100644
index e49fdd9..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_161.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_162.png b/packages/SystemUI/res/drawable-xhdpi/remote_162.png
deleted file mode 100644
index 69257a0..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_162.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_163.png b/packages/SystemUI/res/drawable-xhdpi/remote_163.png
deleted file mode 100644
index 8f0c3d5..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_163.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_164.png b/packages/SystemUI/res/drawable-xhdpi/remote_164.png
deleted file mode 100644
index a4c3229..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_164.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_165.png b/packages/SystemUI/res/drawable-xhdpi/remote_165.png
deleted file mode 100644
index 46fae23..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_165.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_166.png b/packages/SystemUI/res/drawable-xhdpi/remote_166.png
deleted file mode 100644
index 40d5a9b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_166.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_167.png b/packages/SystemUI/res/drawable-xhdpi/remote_167.png
deleted file mode 100644
index 6bd0380..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_167.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_168.png b/packages/SystemUI/res/drawable-xhdpi/remote_168.png
deleted file mode 100644
index 03904bf..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_168.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_169.png b/packages/SystemUI/res/drawable-xhdpi/remote_169.png
deleted file mode 100644
index 564a161..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_169.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_17.png b/packages/SystemUI/res/drawable-xhdpi/remote_17.png
deleted file mode 100644
index 0703e1a..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_17.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_170.png b/packages/SystemUI/res/drawable-xhdpi/remote_170.png
deleted file mode 100644
index 0411f94..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_170.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_171.png b/packages/SystemUI/res/drawable-xhdpi/remote_171.png
deleted file mode 100644
index ec141e9..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_171.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_172.png b/packages/SystemUI/res/drawable-xhdpi/remote_172.png
deleted file mode 100644
index cb9ecaf..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_172.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_173.png b/packages/SystemUI/res/drawable-xhdpi/remote_173.png
deleted file mode 100644
index 484ee51..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_173.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_174.png b/packages/SystemUI/res/drawable-xhdpi/remote_174.png
deleted file mode 100644
index 85a3135..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_174.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_175.png b/packages/SystemUI/res/drawable-xhdpi/remote_175.png
deleted file mode 100644
index edd6507..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_175.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_176.png b/packages/SystemUI/res/drawable-xhdpi/remote_176.png
deleted file mode 100644
index d95a68b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_176.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_177.png b/packages/SystemUI/res/drawable-xhdpi/remote_177.png
deleted file mode 100644
index 305641f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_177.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_178.png b/packages/SystemUI/res/drawable-xhdpi/remote_178.png
deleted file mode 100644
index 59de0e5..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_178.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_179.png b/packages/SystemUI/res/drawable-xhdpi/remote_179.png
deleted file mode 100644
index 414e548..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_179.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_18.png b/packages/SystemUI/res/drawable-xhdpi/remote_18.png
deleted file mode 100644
index 74df1e4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_18.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_180.png b/packages/SystemUI/res/drawable-xhdpi/remote_180.png
deleted file mode 100644
index b5d925c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_180.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_181.png b/packages/SystemUI/res/drawable-xhdpi/remote_181.png
deleted file mode 100644
index e8a7127..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_181.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_182.png b/packages/SystemUI/res/drawable-xhdpi/remote_182.png
deleted file mode 100644
index 29c7037..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_182.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_183.png b/packages/SystemUI/res/drawable-xhdpi/remote_183.png
deleted file mode 100644
index 9491d94..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_183.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_184.png b/packages/SystemUI/res/drawable-xhdpi/remote_184.png
deleted file mode 100644
index 4aa0e32..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_184.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_185.png b/packages/SystemUI/res/drawable-xhdpi/remote_185.png
deleted file mode 100644
index 2a0dde8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_185.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_186.png b/packages/SystemUI/res/drawable-xhdpi/remote_186.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_186.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_187.png b/packages/SystemUI/res/drawable-xhdpi/remote_187.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_187.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_188.png b/packages/SystemUI/res/drawable-xhdpi/remote_188.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_188.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_189.png b/packages/SystemUI/res/drawable-xhdpi/remote_189.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_189.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_19.png b/packages/SystemUI/res/drawable-xhdpi/remote_19.png
deleted file mode 100644
index 222ea31..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_19.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_190.png b/packages/SystemUI/res/drawable-xhdpi/remote_190.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_190.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_191.png b/packages/SystemUI/res/drawable-xhdpi/remote_191.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_191.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_192.png b/packages/SystemUI/res/drawable-xhdpi/remote_192.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_192.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_193.png b/packages/SystemUI/res/drawable-xhdpi/remote_193.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_193.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_194.png b/packages/SystemUI/res/drawable-xhdpi/remote_194.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_194.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_195.png b/packages/SystemUI/res/drawable-xhdpi/remote_195.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_195.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_196.png b/packages/SystemUI/res/drawable-xhdpi/remote_196.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_196.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_197.png b/packages/SystemUI/res/drawable-xhdpi/remote_197.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_197.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_198.png b/packages/SystemUI/res/drawable-xhdpi/remote_198.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_198.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_199.png b/packages/SystemUI/res/drawable-xhdpi/remote_199.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_199.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_2.png b/packages/SystemUI/res/drawable-xhdpi/remote_2.png
deleted file mode 100644
index fb3f7ef..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_20.png b/packages/SystemUI/res/drawable-xhdpi/remote_20.png
deleted file mode 100644
index 646587c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_20.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_200.png b/packages/SystemUI/res/drawable-xhdpi/remote_200.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_200.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_201.png b/packages/SystemUI/res/drawable-xhdpi/remote_201.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_201.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_202.png b/packages/SystemUI/res/drawable-xhdpi/remote_202.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_202.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_203.png b/packages/SystemUI/res/drawable-xhdpi/remote_203.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_203.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_204.png b/packages/SystemUI/res/drawable-xhdpi/remote_204.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_204.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_205.png b/packages/SystemUI/res/drawable-xhdpi/remote_205.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_205.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_206.png b/packages/SystemUI/res/drawable-xhdpi/remote_206.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_206.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_207.png b/packages/SystemUI/res/drawable-xhdpi/remote_207.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_207.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_208.png b/packages/SystemUI/res/drawable-xhdpi/remote_208.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_208.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_209.png b/packages/SystemUI/res/drawable-xhdpi/remote_209.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_209.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_21.png b/packages/SystemUI/res/drawable-xhdpi/remote_21.png
deleted file mode 100644
index 5858ba92..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_21.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_210.png b/packages/SystemUI/res/drawable-xhdpi/remote_210.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_210.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_211.png b/packages/SystemUI/res/drawable-xhdpi/remote_211.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_211.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_212.png b/packages/SystemUI/res/drawable-xhdpi/remote_212.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_212.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_213.png b/packages/SystemUI/res/drawable-xhdpi/remote_213.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_213.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_214.png b/packages/SystemUI/res/drawable-xhdpi/remote_214.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_214.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_215.png b/packages/SystemUI/res/drawable-xhdpi/remote_215.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_215.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_216.png b/packages/SystemUI/res/drawable-xhdpi/remote_216.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_216.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_217.png b/packages/SystemUI/res/drawable-xhdpi/remote_217.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_217.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_218.png b/packages/SystemUI/res/drawable-xhdpi/remote_218.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_218.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_219.png b/packages/SystemUI/res/drawable-xhdpi/remote_219.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_219.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_22.png b/packages/SystemUI/res/drawable-xhdpi/remote_22.png
deleted file mode 100644
index 1974802..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_22.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_220.png b/packages/SystemUI/res/drawable-xhdpi/remote_220.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_220.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_221.png b/packages/SystemUI/res/drawable-xhdpi/remote_221.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_221.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_222.png b/packages/SystemUI/res/drawable-xhdpi/remote_222.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_222.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_223.png b/packages/SystemUI/res/drawable-xhdpi/remote_223.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_223.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_224.png b/packages/SystemUI/res/drawable-xhdpi/remote_224.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_224.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_225.png b/packages/SystemUI/res/drawable-xhdpi/remote_225.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_225.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_226.png b/packages/SystemUI/res/drawable-xhdpi/remote_226.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_226.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_227.png b/packages/SystemUI/res/drawable-xhdpi/remote_227.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_227.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_228.png b/packages/SystemUI/res/drawable-xhdpi/remote_228.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_228.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_229.png b/packages/SystemUI/res/drawable-xhdpi/remote_229.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_229.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_23.png b/packages/SystemUI/res/drawable-xhdpi/remote_23.png
deleted file mode 100644
index 96b7c35..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_23.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_230.png b/packages/SystemUI/res/drawable-xhdpi/remote_230.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_230.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_231.png b/packages/SystemUI/res/drawable-xhdpi/remote_231.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_231.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_232.png b/packages/SystemUI/res/drawable-xhdpi/remote_232.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_232.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_233.png b/packages/SystemUI/res/drawable-xhdpi/remote_233.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_233.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_234.png b/packages/SystemUI/res/drawable-xhdpi/remote_234.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_234.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_235.png b/packages/SystemUI/res/drawable-xhdpi/remote_235.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_235.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_236.png b/packages/SystemUI/res/drawable-xhdpi/remote_236.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_236.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_237.png b/packages/SystemUI/res/drawable-xhdpi/remote_237.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_237.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_238.png b/packages/SystemUI/res/drawable-xhdpi/remote_238.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_238.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_239.png b/packages/SystemUI/res/drawable-xhdpi/remote_239.png
deleted file mode 100644
index 5bda52e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_239.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_24.png b/packages/SystemUI/res/drawable-xhdpi/remote_24.png
deleted file mode 100644
index 0437200..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_24.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_25.png b/packages/SystemUI/res/drawable-xhdpi/remote_25.png
deleted file mode 100644
index 60b0f15..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_25.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_26.png b/packages/SystemUI/res/drawable-xhdpi/remote_26.png
deleted file mode 100644
index c34ed97..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_26.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_27.png b/packages/SystemUI/res/drawable-xhdpi/remote_27.png
deleted file mode 100644
index 1a83664..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_27.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_28.png b/packages/SystemUI/res/drawable-xhdpi/remote_28.png
deleted file mode 100644
index a3685ad..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_28.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_29.png b/packages/SystemUI/res/drawable-xhdpi/remote_29.png
deleted file mode 100644
index f7135eb..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_29.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_3.png b/packages/SystemUI/res/drawable-xhdpi/remote_3.png
deleted file mode 100644
index 937da65..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_3.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_30.png b/packages/SystemUI/res/drawable-xhdpi/remote_30.png
deleted file mode 100644
index 718cf52..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_30.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_31.png b/packages/SystemUI/res/drawable-xhdpi/remote_31.png
deleted file mode 100644
index c0b55df..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_31.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_32.png b/packages/SystemUI/res/drawable-xhdpi/remote_32.png
deleted file mode 100644
index 7a1ce9f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_32.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_33.png b/packages/SystemUI/res/drawable-xhdpi/remote_33.png
deleted file mode 100644
index 5428bcf..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_33.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_34.png b/packages/SystemUI/res/drawable-xhdpi/remote_34.png
deleted file mode 100644
index 264efe8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_34.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_35.png b/packages/SystemUI/res/drawable-xhdpi/remote_35.png
deleted file mode 100644
index a5c450f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_35.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_36.png b/packages/SystemUI/res/drawable-xhdpi/remote_36.png
deleted file mode 100644
index 3e469e4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_36.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_37.png b/packages/SystemUI/res/drawable-xhdpi/remote_37.png
deleted file mode 100644
index 124ebe4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_37.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_38.png b/packages/SystemUI/res/drawable-xhdpi/remote_38.png
deleted file mode 100644
index b2b4844..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_38.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_39.png b/packages/SystemUI/res/drawable-xhdpi/remote_39.png
deleted file mode 100644
index a6d1733..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_39.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_4.png b/packages/SystemUI/res/drawable-xhdpi/remote_4.png
deleted file mode 100644
index c282f40..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_4.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_40.png b/packages/SystemUI/res/drawable-xhdpi/remote_40.png
deleted file mode 100644
index 4cd615c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_40.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_41.png b/packages/SystemUI/res/drawable-xhdpi/remote_41.png
deleted file mode 100644
index c746ae0..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_41.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_42.png b/packages/SystemUI/res/drawable-xhdpi/remote_42.png
deleted file mode 100644
index a93f198..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_42.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_43.png b/packages/SystemUI/res/drawable-xhdpi/remote_43.png
deleted file mode 100644
index 966e563..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_43.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_44.png b/packages/SystemUI/res/drawable-xhdpi/remote_44.png
deleted file mode 100644
index beb7031..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_44.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_45.png b/packages/SystemUI/res/drawable-xhdpi/remote_45.png
deleted file mode 100644
index 718e167..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_45.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_46.png b/packages/SystemUI/res/drawable-xhdpi/remote_46.png
deleted file mode 100644
index aa54ddb..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_46.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_47.png b/packages/SystemUI/res/drawable-xhdpi/remote_47.png
deleted file mode 100644
index 1d11270..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_47.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_48.png b/packages/SystemUI/res/drawable-xhdpi/remote_48.png
deleted file mode 100644
index ab31163..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_48.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_49.png b/packages/SystemUI/res/drawable-xhdpi/remote_49.png
deleted file mode 100644
index 219b7f6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_49.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_5.png b/packages/SystemUI/res/drawable-xhdpi/remote_5.png
deleted file mode 100644
index 15f69e1..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_5.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_50.png b/packages/SystemUI/res/drawable-xhdpi/remote_50.png
deleted file mode 100644
index 8a9725f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_50.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_51.png b/packages/SystemUI/res/drawable-xhdpi/remote_51.png
deleted file mode 100644
index bc839cf..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_51.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_52.png b/packages/SystemUI/res/drawable-xhdpi/remote_52.png
deleted file mode 100644
index 7bab6e5..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_52.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_53.png b/packages/SystemUI/res/drawable-xhdpi/remote_53.png
deleted file mode 100644
index 34ab855..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_53.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_54.png b/packages/SystemUI/res/drawable-xhdpi/remote_54.png
deleted file mode 100644
index 5bd9f59..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_54.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_55.png b/packages/SystemUI/res/drawable-xhdpi/remote_55.png
deleted file mode 100644
index 1ff17f4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_55.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_56.png b/packages/SystemUI/res/drawable-xhdpi/remote_56.png
deleted file mode 100644
index d57e067..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_56.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_57.png b/packages/SystemUI/res/drawable-xhdpi/remote_57.png
deleted file mode 100644
index a1bdae1..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_57.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_58.png b/packages/SystemUI/res/drawable-xhdpi/remote_58.png
deleted file mode 100644
index c8bc6a4..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_58.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_59.png b/packages/SystemUI/res/drawable-xhdpi/remote_59.png
deleted file mode 100644
index 526a24e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_59.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_6.png b/packages/SystemUI/res/drawable-xhdpi/remote_6.png
deleted file mode 100644
index 2b6732f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_6.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_60.png b/packages/SystemUI/res/drawable-xhdpi/remote_60.png
deleted file mode 100644
index 080619e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_60.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_61.png b/packages/SystemUI/res/drawable-xhdpi/remote_61.png
deleted file mode 100644
index 5932a8c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_61.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_62.png b/packages/SystemUI/res/drawable-xhdpi/remote_62.png
deleted file mode 100644
index d1233dd..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_62.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_63.png b/packages/SystemUI/res/drawable-xhdpi/remote_63.png
deleted file mode 100644
index 4f230c7..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_63.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_64.png b/packages/SystemUI/res/drawable-xhdpi/remote_64.png
deleted file mode 100644
index 6b89fcb..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_64.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_65.png b/packages/SystemUI/res/drawable-xhdpi/remote_65.png
deleted file mode 100644
index 87597b1..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_65.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_66.png b/packages/SystemUI/res/drawable-xhdpi/remote_66.png
deleted file mode 100644
index 0ee8c1e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_66.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_67.png b/packages/SystemUI/res/drawable-xhdpi/remote_67.png
deleted file mode 100644
index 9aca8fdd..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_67.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_68.png b/packages/SystemUI/res/drawable-xhdpi/remote_68.png
deleted file mode 100644
index 5f263ae..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_68.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_69.png b/packages/SystemUI/res/drawable-xhdpi/remote_69.png
deleted file mode 100644
index 1a22b61..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_69.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_7.png b/packages/SystemUI/res/drawable-xhdpi/remote_7.png
deleted file mode 100644
index 9d9d699..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_7.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_70.png b/packages/SystemUI/res/drawable-xhdpi/remote_70.png
deleted file mode 100644
index 0372c50..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_70.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_71.png b/packages/SystemUI/res/drawable-xhdpi/remote_71.png
deleted file mode 100644
index 854e3e2..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_71.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_72.png b/packages/SystemUI/res/drawable-xhdpi/remote_72.png
deleted file mode 100644
index 6919624..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_72.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_73.png b/packages/SystemUI/res/drawable-xhdpi/remote_73.png
deleted file mode 100644
index d8e9ae1..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_73.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_74.png b/packages/SystemUI/res/drawable-xhdpi/remote_74.png
deleted file mode 100644
index 24e5b6a..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_74.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_75.png b/packages/SystemUI/res/drawable-xhdpi/remote_75.png
deleted file mode 100644
index 369a3a9..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_75.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_76.png b/packages/SystemUI/res/drawable-xhdpi/remote_76.png
deleted file mode 100644
index 96824c6..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_76.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_77.png b/packages/SystemUI/res/drawable-xhdpi/remote_77.png
deleted file mode 100644
index dd60cca..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_77.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_78.png b/packages/SystemUI/res/drawable-xhdpi/remote_78.png
deleted file mode 100644
index aa3460b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_78.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_79.png b/packages/SystemUI/res/drawable-xhdpi/remote_79.png
deleted file mode 100644
index 9a60e3c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_79.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_8.png b/packages/SystemUI/res/drawable-xhdpi/remote_8.png
deleted file mode 100644
index b73c7ef..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_8.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_80.png b/packages/SystemUI/res/drawable-xhdpi/remote_80.png
deleted file mode 100644
index cbf883c..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_80.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_81.png b/packages/SystemUI/res/drawable-xhdpi/remote_81.png
deleted file mode 100644
index 11a6add..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_81.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_82.png b/packages/SystemUI/res/drawable-xhdpi/remote_82.png
deleted file mode 100644
index e05105d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_82.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_83.png b/packages/SystemUI/res/drawable-xhdpi/remote_83.png
deleted file mode 100644
index 57813aa..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_83.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_84.png b/packages/SystemUI/res/drawable-xhdpi/remote_84.png
deleted file mode 100644
index 0f6f0fe..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_84.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_85.png b/packages/SystemUI/res/drawable-xhdpi/remote_85.png
deleted file mode 100644
index ada83ec..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_85.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_86.png b/packages/SystemUI/res/drawable-xhdpi/remote_86.png
deleted file mode 100644
index 442dd51..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_86.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_87.png b/packages/SystemUI/res/drawable-xhdpi/remote_87.png
deleted file mode 100644
index bdb4962..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_87.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_88.png b/packages/SystemUI/res/drawable-xhdpi/remote_88.png
deleted file mode 100644
index b318002..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_88.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_89.png b/packages/SystemUI/res/drawable-xhdpi/remote_89.png
deleted file mode 100644
index c4ed874..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_89.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_9.png b/packages/SystemUI/res/drawable-xhdpi/remote_9.png
deleted file mode 100644
index ce5041f..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_90.png b/packages/SystemUI/res/drawable-xhdpi/remote_90.png
deleted file mode 100644
index 6a662f9..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_90.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_91.png b/packages/SystemUI/res/drawable-xhdpi/remote_91.png
deleted file mode 100644
index 21be887..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_91.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_92.png b/packages/SystemUI/res/drawable-xhdpi/remote_92.png
deleted file mode 100644
index 1bc5361..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_92.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_93.png b/packages/SystemUI/res/drawable-xhdpi/remote_93.png
deleted file mode 100644
index 76495ac..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_93.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_94.png b/packages/SystemUI/res/drawable-xhdpi/remote_94.png
deleted file mode 100644
index 081c84b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_94.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_95.png b/packages/SystemUI/res/drawable-xhdpi/remote_95.png
deleted file mode 100644
index e9c27a8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_95.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_96.png b/packages/SystemUI/res/drawable-xhdpi/remote_96.png
deleted file mode 100644
index 1369603..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_96.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_97.png b/packages/SystemUI/res/drawable-xhdpi/remote_97.png
deleted file mode 100644
index fbd1458..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_97.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_98.png b/packages/SystemUI/res/drawable-xhdpi/remote_98.png
deleted file mode 100644
index ccdd7a7..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_98.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/remote_99.png b/packages/SystemUI/res/drawable-xhdpi/remote_99.png
deleted file mode 100644
index f3cb4db..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/remote_99.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
index 49e0499..8d58a7e 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
index 0e6ca16..6c04d1a 100644
--- a/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
+++ b/packages/SystemUI/res/drawable-xxxhdpi/pip_dismiss_scrim.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_data_off.xml b/packages/SystemUI/res/drawable/ic_data_off.xml
new file mode 100644
index 0000000..b97ddae
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_data_off.xml
@@ -0,0 +1,27 @@
+<!--
+    Copyright (C) 2017 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M21.6,21.6L10.8,10.9L2.1,2.1L0.8,3.4l3.3,3.3C3.1,8.2 2.5,10.0 2.5,12.0c0.0,5.2 4.3,9.5 9.5,9.5c2.0,0.0 3.8,-0.6 5.3,-1.6l3.0,3.0L21.6,21.6zM9.6,12.2l0.7,0.7L9.6,12.9L9.6,12.2zM13.9,18.6c-0.2,0.2 -0.5,0.2 -0.6,0.0l-2.4,-3.7l1.5,0.0l2.4,2.4L13.9,18.6z"
+        android:fillColor="#ffffff"/>
+    <path
+        android:pathData="M12.0,2.5c-2.0,0.0 -3.8,0.6 -5.3,1.6l2.5,2.5L10.0,5.4c0.2,-0.2 0.5,-0.2 0.6,0.0L13.0,9.1l-1.4,0.0l2.0,2.0l0.6,0.0l0.0,0.6l5.6,5.6c1.0,-1.5 1.6,-3.3 1.6,-5.3C21.5,6.8 17.2,2.5 12.0,2.5z"
+        android:fillColor="#ffffff"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_data_on.xml
similarity index 60%
rename from packages/SystemUI/res/drawable/ic_qs_signal_4.xml
rename to packages/SystemUI/res/drawable/ic_data_on.xml
index 012e95e..a65dc79 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
+++ b/packages/SystemUI/res/drawable/ic_data_on.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2017 The Android Open Source Project
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,15 +14,13 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
+        android:width="24.0dp"
+        android:height="24.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
+        android:pathData="M12.0,12.0m-9.5,0.0a9.5,9.5 0.0,1.0 1.0,19.0 0.0a9.5,9.5 0.0,1.0 1.0,-19.0 0.0
+        M10.6,5.4c-0.2,-0.2 -0.5,-0.2 -0.6,0.0L7.6,9.1l2.0,0.0l0.0,3.8L11.0,12.900001L11.0,9.1l2.0,0.0L10.6,5.4z
+        M13.3,18.6c0.2,0.2 0.5,0.2 0.6,0.0l2.4,-3.7l-2.0,0.0l0.0,-3.8l-1.4,0.0l0.0,3.8l-2.0,0.0L13.3,18.6z"
+        android:fillColor="#ffffff"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_data_unavailable.xml b/packages/SystemUI/res/drawable/ic_data_unavailable.xml
new file mode 100644
index 0000000..27a7697
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_data_unavailable.xml
@@ -0,0 +1,32 @@
+<!--
+    Copyright (C) 2017 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+        M12.0,12.0m-9.5,0.0a9.5,9.5 0.0,1.0 1.0,19.0 0.0a9.5,9.5 0.0,1.0 1.0,-19.0 0.0
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M12.0,2.5c-5.246705,0.0 -9.5,4.253295 -9.5,9.5 0.0,5.246705 4.253295,9.5 9.5,9.5 2.771732,0.0 5.263364,-1.200342 7.0,-3.09375l0.0,-0.21875 0.0,-7.5 0.0,-1.0 1.0,0.0 1.1875,0.0C20.148497,5.5674677 16.442669,2.5 12.0,2.5zm9.1875,7.1875c-14.125,9.541667 -7.0625,4.770833 0.0,0.0z
+        M10.6,5.4C10.4,5.2 10.1,5.2 10.0,5.4L7.6,9.1l2.0,0.0l0.0,3.8L11.0,12.900001L11.0,9.1l2.0,0.0L10.6,5.4z
+        M13.3,18.6c0.2,0.2 0.5,0.2 0.6,0.0l2.4,-3.7l-2.0,0.0l0.0,-3.8l-1.4,0.0l0.0,3.8l-2.0,0.0l2.4,3.7z
+        M21.7,24.0c-0.5,0.0 -0.8,-0.1 -1.1,-0.4c-0.3,-0.3 -0.4,-0.6 -0.4,-1.0c0.0,-0.4 0.1,-0.8 0.4,-1.0c0.3,-0.3 0.7,-0.4 1.1,-0.4s0.8,0.1 1.1,0.4c0.3,0.3 0.4,0.6 0.4,1.0c0.0,0.4 -0.1,0.7 -0.4,1.0
+        C22.6,23.8 22.2,24 21.7,24z
+        M20.4,19.7l0.0,-8.5L23.0,11.2l0.0,8.5L20.4,19.7z
+        "
+        android:fillType="evenOdd"
+        android:fillColor="#231F20"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_dnd.xml b/packages/SystemUI/res/drawable/ic_dnd.xml
index 17ecf21..e658e68 100644
--- a/packages/SystemUI/res/drawable/ic_dnd.xml
+++ b/packages/SystemUI/res/drawable/ic_dnd.xml
@@ -17,7 +17,8 @@
     android:height="24dp"
     android:viewportHeight="48.0"
     android:viewportWidth="48.0"
-    android:width="24dp" >
+    android:width="24dp"
+    android:tint="?android:attr/colorControlNormal">
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml b/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml
index 4875974..0515b35 100644
--- a/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml
+++ b/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml
@@ -17,7 +17,8 @@
     android:height="24dp"
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
-    android:width="24dp" >
+    android:width="24dp"
+    android:tint="?android:attr/colorControlNormal">
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_info_outline.xml b/packages/SystemUI/res/drawable/ic_info_outline.xml
new file mode 100644
index 0000000..a4a3e9a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_info_outline.xml
@@ -0,0 +1,25 @@
+<!--
+  Copyright (C) 2016 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
index 5aeceba..169cc71 100644
--- a/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_enable.xml
@@ -16,7 +16,6 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="root"
-    android:alpha="0.3"
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
diff --git a/packages/SystemUI/res/drawable/ic_pause_white_24dp.xml b/packages/SystemUI/res/drawable/ic_pause_white.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_pause_white_24dp.xml
rename to packages/SystemUI/res/drawable/ic_pause_white.xml
diff --git a/packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml b/packages/SystemUI/res/drawable/ic_play_arrow_white.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_play_arrow_white_24dp.xml
rename to packages/SystemUI/res/drawable/ic_play_arrow_white.xml
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
deleted file mode 100644
index e055de7..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
-    Copyright (C) 2016 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
deleted file mode 100644
index 8a48817..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
-    Copyright (C) 2016 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
deleted file mode 100644
index 39cc94c..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
-    Copyright (C) 2016 The Android Open Source Project
-
-    Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillAlpha="0.3"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z"
-        android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
deleted file mode 100644
index 96e2fd4..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
+++ /dev/null
@@ -1,36 +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="32dp"
-        android:height="32dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:name="dot1"
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M9.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/>
-    <path
-        android:name="dot2"
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M14.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/>
-    <path
-        android:name="dot3"
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M19.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/>
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M2.0,22.0l6.0,0.0 0.0,-4.0 14.0,0.0 0.0,-16.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml
deleted file mode 100644
index 2186aa8..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change_animation.xml
+++ /dev/null
@@ -1,27 +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.
--->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_qs_signal_carrier_network_change" >
-    <target
-        android:name="dot1"
-        android:animation="@anim/ic_qs_signal_blink_1"/>
-    <target
-        android:name="dot2"
-        android:animation="@anim/ic_qs_signal_blink_2"/>
-    <target
-        android:name="dot3"
-        android:animation="@anim/ic_qs_signal_blink_3"/>
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
deleted file mode 100644
index 326373d..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
deleted file mode 100644
index 8baa4eb..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
deleted file mode 100644
index bf19a71..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M14.000000,10.000000l-12.000000,12.000000 12.000000,0.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
deleted file mode 100644
index 01839e85..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#4DFFFFFF"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M16.700001,7.300000l-14.700001,14.700000 14.700001,0.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
deleted file mode 100644
index 48151ad..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
index 236fdac0..5e7cd974 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
@@ -17,7 +17,8 @@
         android:width="6.0dp"
         android:height="32dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/textColorSecondary">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M6.000000,15.700000l-3.000000,5.599999 -3.000000,-5.599999z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
index c510972..0dca1db 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
@@ -17,7 +17,8 @@
         android:width="6.0dp"
         android:height="32dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/textColorSecondary">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M0.000000,13.700000l3.000000,-5.700000 3.000000,5.700000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml b/packages/SystemUI/res/drawable/ic_skip_next_white.xml
similarity index 64%
copy from packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
copy to packages/SystemUI/res/drawable/ic_skip_next_white.xml
index e267d25..040c7e6 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
+++ b/packages/SystemUI/res/drawable/ic_skip_next_white.xml
@@ -1,5 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,12 +15,14 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
     <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-</vector>
+        android:fillColor="#FFFFFF"
+        android:pathData="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml b/packages/SystemUI/res/drawable/ic_skip_previous_white.xml
similarity index 64%
rename from packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
rename to packages/SystemUI/res/drawable/ic_skip_previous_white.xml
index e267d25..b9b94b7 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0_fully.xml
+++ b/packages/SystemUI/res/drawable/ic_skip_previous_white.xml
@@ -1,5 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,12 +15,14 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
     <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-</vector>
+        android:fillColor="#FFFFFF"
+        android:pathData="M6 6h2v12H6zm3.5 6l8.5 6V6z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/segmented_buttons_background.xml b/packages/SystemUI/res/drawable/segmented_buttons_background.xml
index b243dc7c..755c917 100644
--- a/packages/SystemUI/res/drawable/segmented_buttons_background.xml
+++ b/packages/SystemUI/res/drawable/segmented_buttons_background.xml
@@ -17,6 +17,6 @@
 
       <corners android:radius="@dimen/borderless_button_radius" />
 
-      <solid android:color="@color/segmented_buttons_background" />
+      <solid android:color="?android:attr/colorPrimaryDark" />
 
-</shape>
\ No newline at end of file
+</shape>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
index d7463a4..be9a7e2 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_1x.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="8.5dp"
-        android:height="17dp"
-        android:viewportWidth="12.0"
-        android:viewportHeight="24.0">
+    android:width="17dp"
+    android:height="17dp"
+    android:viewportWidth="12.0"
+    android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
index 6309b6d..fd7a658 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_3g.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="9.208dp"
+        android:width="17dp"
         android:height="17dp"
         android:viewportWidth="13.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="13.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
index 4067ae5..02c4ab6 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="8.5dp"
+        android:width="17dp"
         android:height="17dp"
         android:viewportWidth="12.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
index 3cdd3e1..daf4061 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="17.0dp"
+        android:width="25.5dp"
         android:height="17.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportWidth="18.0"
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
index acaa9b1..cd0cc65 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_e.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="3.541dp"
+        android:width="7.083dp"
         android:height="17dp"
         android:viewportWidth="5.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
index 7985237..92ed49c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_g.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="4.958dp"
+        android:width="9.154dp"
         android:height="17dp"
         android:viewportWidth="7.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="13">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
index fda8761..ca61b6f 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_h.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="4.25dp"
+        android:width="9.5dp"
         android:height="17dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
index c08ff20..add96b4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="9.208dp"
+        android:width="18.417dp"
         android:height="17dp"
-        android:viewportWidth="13.0"
-        android:viewportHeight="24.0">
+        android:viewportWidth="13"
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
index db18fad..8811d2f 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="17.0dp"
+        android:width="25.0dp"
         android:height="17.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
+        android:viewportWidth="18.0"
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_roaming.xml b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
index 4baa472..363e231 100644
--- a/packages/SystemUI/res/drawable/stat_sys_roaming.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="8.5dp"
+        android:width="4.25dp"
         android:height="17dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="12.0">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.800000,7.900000l-1.000000,0.000000L1.800000,11.000000L0.200000,11.000000L0.200000,2.500000l2.700000,0.000000c0.900000,0.000000 1.500000,0.200000 2.000000,0.700000s0.700000,1.100000 0.700000,1.900000c0.000000,0.600000 -0.100000,1.100000 -0.300000,1.500000S4.800000,7.200000 4.400000,7.400000l1.500000,3.500000L5.900000,11.000000L4.100000,11.000000L2.800000,7.900000zM1.800000,6.500000l1.100000,0.000000c0.400000,0.000000 0.600000,-0.100000 0.800000,-0.400000S4.000000,5.600000 4.000000,5.200000c0.000000,-0.400000 -0.100000,-0.800000 -0.300000,-1.000000S3.300000,3.800000 2.900000,3.800000L1.800000,3.800000L1.800000,6.500000z"/>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
deleted file mode 100644
index 8bc872a..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
+++ /dev/null
@@ -1,28 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
deleted file mode 100644
index 8fa7630..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
+++ /dev/null
@@ -1,31 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
-        android:fillColor="?attr/fillColor"/>
-    <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
deleted file mode 100644
index 60822f4..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
deleted file mode 100644
index 2a660a3..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
+++ /dev/null
@@ -1,31 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
-        android:fillColor="?attr/fillColor"/>
-    <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml
deleted file mode 100644
index 5e68eed..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2_fully.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M14.000000,10.000000l-12.000000,12.000000 12.000000,0.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
deleted file mode 100644
index 9e0a433..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
+++ /dev/null
@@ -1,31 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
-    <path
-        android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z"
-        android:fillColor="?attr/fillColor"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml
deleted file mode 100644
index 599b34a..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3_fully.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M16.700001,7.300000l-14.700001,14.700000 14.700001,0.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
deleted file mode 100644
index 01f6703..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
+++ /dev/null
@@ -1,28 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17.0dp"
-        android:height="17.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
-        android:fillColor="?attr/fillColor"/>
-    <path
-        android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
-        android:fillColor="?attr/fillColor"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml
deleted file mode 100644
index b66d89a..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4_fully.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="17dp"
-        android:height="17dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml
deleted file mode 100644
index f69ffe4..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change.xml
+++ /dev/null
@@ -1,36 +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="17dp"
-        android:height="17dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:name="dot1"
-        android:fillColor="?attr/fillColor"
-        android:pathData="M9.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/>
-    <path
-        android:name="dot2"
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M14.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/>
-    <path
-        android:name="dot3"
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M19.0,19.0l3.0,0.0l0.0,3.0l-3.0,0.0z"/>
-    <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M2.0,22.0l6.0,0.0 0.0,-4.0 14.0,0.0 0.0,-16.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml b/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml
deleted file mode 100644
index 275f037..0000000
--- a/packages/SystemUI/res/drawable/stat_sys_signal_carrier_network_change_animation.xml
+++ /dev/null
@@ -1,27 +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.
--->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/stat_sys_signal_carrier_network_change" >
-    <target
-        android:name="dot1"
-        android:animation="@anim/ic_signal_blink_1"/>
-    <target
-        android:name="dot2"
-        android:animation="@anim/ic_signal_blink_2"/>
-    <target
-        android:name="dot3"
-        android:animation="@anim/ic_signal_blink_3"/>
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_disconnected.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_disconnected.xml
new file mode 100644
index 0000000..f4e8af4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_disconnected.xml
@@ -0,0 +1,42 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="18.41dp"
+        android:height="17dp"
+        android:viewportWidth="26.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="?attr/backgroundColor"
+        android:pathData="M21.0,8.5
+        c0.85,0.0 1.6,0.23 2.3,0.62l2.24,-2.79
+        C25.1,5.96 20.26,2.0 13.0,2.0
+        S0.9,5.9 0.42,6.32
+        l12.57,15.6 4.21,-5.17
+        c-0.76,-0.87 -1.22,-2.0 -1.22,-3.25
+        c0.0,-2.76 2.24,-5.0 5.0,-5.0z"
+        android:fillAlpha=".3"/>
+    <path
+        android:fillColor="?attr/backgroundColor"
+        android:pathData="M21.0,10.0
+        c-1.93,0.0 -3.5,1.57 -3.5,3.5l1.75,0.0
+        c0.0,-0.9 0.78,-1.75 1.75,-1.75s1.7,0.78 1.75,1.75
+        c0.0,0.48 -0.2,0.92 -0.51,1.24l-1.09,1.1
+        c-0.6,0.63 -1.02,1.51 -1.02,2.47l0.0,0.44l1.75,0.0
+        c0.0,-1.3 0.39,-1.84 1.03,-2.47l0.78,-0.8
+        c0.5,-0.5 0.82,-1.2 0.82,-1.97
+        C24.5,11.57 22.93,10.0 21.0,10.0z
+        m-0.95,11.95l1.9,0.0l0.0,-1.9l-1.9,0.0l0.0,1.9z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
index 5169de4..c1856fa 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_null.xml
@@ -20,5 +20,8 @@
         android:viewportHeight="24.0">
     <path
         android:fillColor="?attr/backgroundColor"
-        android:pathData="M13.000000,2.000000C7.700000,2.000000 3.700000,3.900000 0.400000,6.400000L13.000000,22.000000L25.600000,6.500000C22.299999,4.000000 18.299999,2.000000 13.000000,2.000000zM13.000000,18.600000L3.300000,7.000000l0.000000,0.000000l0.000000,0.000000C6.000000,5.300000 8.700000,4.000000 13.000000,4.000000s7.000000,1.400000 9.700000,3.000000l0.000000,0.000000l0.000000,0.000000L13.000000,18.600000z"/>
+        android:pathData="M17.500000,16.500000L5.800000,3.400000c0.000000,0.000000 0.000000,0.000000 0.000000,0.000000l-2.700000,-3.000000L1.600000,1.800000l2.200000,2.500000c-2.000000,1.000000 -3.200000,2.000000 -3.400000,2.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l3.200000,-3.900000l2.400000,2.700000l1.500000,-1.400000L17.500000,16.500000L17.500000,16.500000z"/>
+    <path
+        android:fillColor="?attr/backgroundColor"
+        android:pathData="M25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000c-1.900000,0.000000 -3.600000,0.300000 -5.200000,0.700000L18.700001,15.000000L25.600000,6.500000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml b/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml
deleted file mode 100644
index d46108a..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_onboarding_remote.xml
+++ /dev/null
@@ -1,259 +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.
--->
-<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
-    android:oneshot="false">
-
-    <item android:drawable="@drawable/remote_0" android:duration="13" />
-    <item android:drawable="@drawable/remote_1" android:duration="13" />
-    <item android:drawable="@drawable/remote_2" android:duration="13" />
-    <item android:drawable="@drawable/remote_3" android:duration="13" />
-    <item android:drawable="@drawable/remote_4" android:duration="13" />
-    <item android:drawable="@drawable/remote_5" android:duration="13" />
-    <item android:drawable="@drawable/remote_6" android:duration="13" />
-    <item android:drawable="@drawable/remote_7" android:duration="13" />
-    <item android:drawable="@drawable/remote_8" android:duration="13" />
-    <item android:drawable="@drawable/remote_9" android:duration="13" />
-    <item android:drawable="@drawable/remote_10" android:duration="13" />
-    <item android:drawable="@drawable/remote_11" android:duration="13" />
-    <item android:drawable="@drawable/remote_12" android:duration="13" />
-    <item android:drawable="@drawable/remote_13" android:duration="13" />
-    <item android:drawable="@drawable/remote_14" android:duration="13" />
-    <item android:drawable="@drawable/remote_15" android:duration="13" />
-    <item android:drawable="@drawable/remote_16" android:duration="13" />
-    <item android:drawable="@drawable/remote_17" android:duration="13" />
-    <item android:drawable="@drawable/remote_18" android:duration="13" />
-    <item android:drawable="@drawable/remote_19" android:duration="13" />
-    <item android:drawable="@drawable/remote_20" android:duration="13" />
-    <item android:drawable="@drawable/remote_21" android:duration="13" />
-    <item android:drawable="@drawable/remote_22" android:duration="13" />
-    <item android:drawable="@drawable/remote_23" android:duration="13" />
-    <item android:drawable="@drawable/remote_24" android:duration="13" />
-    <item android:drawable="@drawable/remote_25" android:duration="13" />
-    <item android:drawable="@drawable/remote_26" android:duration="13" />
-    <item android:drawable="@drawable/remote_27" android:duration="13" />
-    <item android:drawable="@drawable/remote_28" android:duration="13" />
-    <item android:drawable="@drawable/remote_29" android:duration="13" />
-    <item android:drawable="@drawable/remote_30" android:duration="13" />
-    <item android:drawable="@drawable/remote_31" android:duration="13" />
-    <item android:drawable="@drawable/remote_32" android:duration="13" />
-    <item android:drawable="@drawable/remote_33" android:duration="13" />
-    <item android:drawable="@drawable/remote_34" android:duration="13" />
-    <item android:drawable="@drawable/remote_35" android:duration="13" />
-    <item android:drawable="@drawable/remote_36" android:duration="13" />
-    <item android:drawable="@drawable/remote_37" android:duration="13" />
-    <item android:drawable="@drawable/remote_38" android:duration="13" />
-    <item android:drawable="@drawable/remote_39" android:duration="13" />
-    <item android:drawable="@drawable/remote_40" android:duration="13" />
-    <item android:drawable="@drawable/remote_41" android:duration="13" />
-    <item android:drawable="@drawable/remote_42" android:duration="13" />
-    <item android:drawable="@drawable/remote_43" android:duration="13" />
-    <item android:drawable="@drawable/remote_44" android:duration="13" />
-    <item android:drawable="@drawable/remote_45" android:duration="13" />
-    <item android:drawable="@drawable/remote_46" android:duration="13" />
-    <item android:drawable="@drawable/remote_47" android:duration="13" />
-    <item android:drawable="@drawable/remote_48" android:duration="13" />
-    <item android:drawable="@drawable/remote_49" android:duration="13" />
-    <item android:drawable="@drawable/remote_50" android:duration="13" />
-    <item android:drawable="@drawable/remote_51" android:duration="13" />
-    <item android:drawable="@drawable/remote_52" android:duration="13" />
-    <item android:drawable="@drawable/remote_53" android:duration="13" />
-    <item android:drawable="@drawable/remote_54" android:duration="13" />
-    <item android:drawable="@drawable/remote_55" android:duration="13" />
-    <item android:drawable="@drawable/remote_56" android:duration="13" />
-    <item android:drawable="@drawable/remote_57" android:duration="13" />
-    <item android:drawable="@drawable/remote_58" android:duration="13" />
-    <item android:drawable="@drawable/remote_59" android:duration="13" />
-    <item android:drawable="@drawable/remote_60" android:duration="13" />
-    <item android:drawable="@drawable/remote_61" android:duration="13" />
-    <item android:drawable="@drawable/remote_62" android:duration="13" />
-    <item android:drawable="@drawable/remote_63" android:duration="13" />
-    <item android:drawable="@drawable/remote_64" android:duration="13" />
-    <item android:drawable="@drawable/remote_65" android:duration="13" />
-    <item android:drawable="@drawable/remote_66" android:duration="13" />
-    <item android:drawable="@drawable/remote_67" android:duration="13" />
-    <item android:drawable="@drawable/remote_68" android:duration="13" />
-    <item android:drawable="@drawable/remote_69" android:duration="13" />
-    <item android:drawable="@drawable/remote_70" android:duration="13" />
-    <item android:drawable="@drawable/remote_71" android:duration="13" />
-    <item android:drawable="@drawable/remote_72" android:duration="13" />
-    <item android:drawable="@drawable/remote_73" android:duration="13" />
-    <item android:drawable="@drawable/remote_74" android:duration="13" />
-    <item android:drawable="@drawable/remote_75" android:duration="13" />
-    <item android:drawable="@drawable/remote_76" android:duration="13" />
-    <item android:drawable="@drawable/remote_77" android:duration="13" />
-    <item android:drawable="@drawable/remote_78" android:duration="13" />
-    <item android:drawable="@drawable/remote_79" android:duration="13" />
-    <item android:drawable="@drawable/remote_80" android:duration="13" />
-    <item android:drawable="@drawable/remote_81" android:duration="13" />
-    <item android:drawable="@drawable/remote_82" android:duration="13" />
-    <item android:drawable="@drawable/remote_83" android:duration="13" />
-    <item android:drawable="@drawable/remote_84" android:duration="13" />
-    <item android:drawable="@drawable/remote_85" android:duration="13" />
-    <item android:drawable="@drawable/remote_86" android:duration="13" />
-    <item android:drawable="@drawable/remote_87" android:duration="13" />
-    <item android:drawable="@drawable/remote_88" android:duration="13" />
-    <item android:drawable="@drawable/remote_89" android:duration="13" />
-    <item android:drawable="@drawable/remote_90" android:duration="13" />
-    <item android:drawable="@drawable/remote_91" android:duration="13" />
-    <item android:drawable="@drawable/remote_92" android:duration="13" />
-    <item android:drawable="@drawable/remote_93" android:duration="13" />
-    <item android:drawable="@drawable/remote_94" android:duration="13" />
-    <item android:drawable="@drawable/remote_95" android:duration="13" />
-    <item android:drawable="@drawable/remote_96" android:duration="13" />
-    <item android:drawable="@drawable/remote_97" android:duration="13" />
-    <item android:drawable="@drawable/remote_98" android:duration="13" />
-    <item android:drawable="@drawable/remote_99" android:duration="13" />
-    <item android:drawable="@drawable/remote_100" android:duration="13" />
-    <item android:drawable="@drawable/remote_101" android:duration="13" />
-    <item android:drawable="@drawable/remote_102" android:duration="13" />
-    <item android:drawable="@drawable/remote_103" android:duration="13" />
-    <item android:drawable="@drawable/remote_104" android:duration="13" />
-    <item android:drawable="@drawable/remote_105" android:duration="13" />
-    <item android:drawable="@drawable/remote_106" android:duration="13" />
-    <item android:drawable="@drawable/remote_107" android:duration="13" />
-    <item android:drawable="@drawable/remote_108" android:duration="13" />
-    <item android:drawable="@drawable/remote_109" android:duration="13" />
-    <item android:drawable="@drawable/remote_110" android:duration="13" />
-    <item android:drawable="@drawable/remote_111" android:duration="13" />
-    <item android:drawable="@drawable/remote_112" android:duration="13" />
-    <item android:drawable="@drawable/remote_113" android:duration="13" />
-    <item android:drawable="@drawable/remote_114" android:duration="13" />
-    <item android:drawable="@drawable/remote_115" android:duration="13" />
-    <item android:drawable="@drawable/remote_116" android:duration="13" />
-    <item android:drawable="@drawable/remote_117" android:duration="13" />
-    <item android:drawable="@drawable/remote_118" android:duration="13" />
-    <item android:drawable="@drawable/remote_119" android:duration="13" />
-    <item android:drawable="@drawable/remote_120" android:duration="13" />
-    <item android:drawable="@drawable/remote_121" android:duration="13" />
-    <item android:drawable="@drawable/remote_122" android:duration="13" />
-    <item android:drawable="@drawable/remote_123" android:duration="13" />
-    <item android:drawable="@drawable/remote_124" android:duration="13" />
-    <item android:drawable="@drawable/remote_125" android:duration="13" />
-    <item android:drawable="@drawable/remote_126" android:duration="13" />
-    <item android:drawable="@drawable/remote_127" android:duration="13" />
-    <item android:drawable="@drawable/remote_128" android:duration="13" />
-    <item android:drawable="@drawable/remote_129" android:duration="13" />
-    <item android:drawable="@drawable/remote_130" android:duration="13" />
-    <item android:drawable="@drawable/remote_131" android:duration="13" />
-    <item android:drawable="@drawable/remote_132" android:duration="13" />
-    <item android:drawable="@drawable/remote_133" android:duration="13" />
-    <item android:drawable="@drawable/remote_134" android:duration="13" />
-    <item android:drawable="@drawable/remote_135" android:duration="13" />
-    <item android:drawable="@drawable/remote_136" android:duration="13" />
-    <item android:drawable="@drawable/remote_137" android:duration="13" />
-    <item android:drawable="@drawable/remote_138" android:duration="13" />
-    <item android:drawable="@drawable/remote_139" android:duration="13" />
-    <item android:drawable="@drawable/remote_140" android:duration="13" />
-    <item android:drawable="@drawable/remote_141" android:duration="13" />
-    <item android:drawable="@drawable/remote_142" android:duration="13" />
-    <item android:drawable="@drawable/remote_143" android:duration="13" />
-    <item android:drawable="@drawable/remote_144" android:duration="13" />
-    <item android:drawable="@drawable/remote_145" android:duration="13" />
-    <item android:drawable="@drawable/remote_146" android:duration="13" />
-    <item android:drawable="@drawable/remote_147" android:duration="13" />
-    <item android:drawable="@drawable/remote_148" android:duration="13" />
-    <item android:drawable="@drawable/remote_149" android:duration="13" />
-    <item android:drawable="@drawable/remote_150" android:duration="13" />
-    <item android:drawable="@drawable/remote_151" android:duration="13" />
-    <item android:drawable="@drawable/remote_152" android:duration="13" />
-    <item android:drawable="@drawable/remote_153" android:duration="13" />
-    <item android:drawable="@drawable/remote_154" android:duration="13" />
-    <item android:drawable="@drawable/remote_155" android:duration="13" />
-    <item android:drawable="@drawable/remote_156" android:duration="13" />
-    <item android:drawable="@drawable/remote_157" android:duration="13" />
-    <item android:drawable="@drawable/remote_158" android:duration="13" />
-    <item android:drawable="@drawable/remote_159" android:duration="13" />
-    <item android:drawable="@drawable/remote_160" android:duration="13" />
-    <item android:drawable="@drawable/remote_161" android:duration="13" />
-    <item android:drawable="@drawable/remote_162" android:duration="13" />
-    <item android:drawable="@drawable/remote_163" android:duration="13" />
-    <item android:drawable="@drawable/remote_164" android:duration="13" />
-    <item android:drawable="@drawable/remote_165" android:duration="13" />
-    <item android:drawable="@drawable/remote_166" android:duration="13" />
-    <item android:drawable="@drawable/remote_167" android:duration="13" />
-    <item android:drawable="@drawable/remote_168" android:duration="13" />
-    <item android:drawable="@drawable/remote_169" android:duration="13" />
-    <item android:drawable="@drawable/remote_170" android:duration="13" />
-    <item android:drawable="@drawable/remote_171" android:duration="13" />
-    <item android:drawable="@drawable/remote_172" android:duration="13" />
-    <item android:drawable="@drawable/remote_173" android:duration="13" />
-    <item android:drawable="@drawable/remote_174" android:duration="13" />
-    <item android:drawable="@drawable/remote_175" android:duration="13" />
-    <item android:drawable="@drawable/remote_176" android:duration="13" />
-    <item android:drawable="@drawable/remote_177" android:duration="13" />
-    <item android:drawable="@drawable/remote_178" android:duration="13" />
-    <item android:drawable="@drawable/remote_179" android:duration="13" />
-    <item android:drawable="@drawable/remote_180" android:duration="13" />
-    <item android:drawable="@drawable/remote_181" android:duration="13" />
-    <item android:drawable="@drawable/remote_182" android:duration="13" />
-    <item android:drawable="@drawable/remote_183" android:duration="13" />
-    <item android:drawable="@drawable/remote_184" android:duration="13" />
-    <item android:drawable="@drawable/remote_185" android:duration="13" />
-    <item android:drawable="@drawable/remote_186" android:duration="13" />
-    <item android:drawable="@drawable/remote_187" android:duration="13" />
-    <item android:drawable="@drawable/remote_188" android:duration="13" />
-    <item android:drawable="@drawable/remote_189" android:duration="13" />
-    <item android:drawable="@drawable/remote_190" android:duration="13" />
-    <item android:drawable="@drawable/remote_191" android:duration="13" />
-    <item android:drawable="@drawable/remote_192" android:duration="13" />
-    <item android:drawable="@drawable/remote_193" android:duration="13" />
-    <item android:drawable="@drawable/remote_194" android:duration="13" />
-    <item android:drawable="@drawable/remote_195" android:duration="13" />
-    <item android:drawable="@drawable/remote_196" android:duration="13" />
-    <item android:drawable="@drawable/remote_197" android:duration="13" />
-    <item android:drawable="@drawable/remote_198" android:duration="13" />
-    <item android:drawable="@drawable/remote_199" android:duration="13" />
-    <item android:drawable="@drawable/remote_200" android:duration="13" />
-    <item android:drawable="@drawable/remote_201" android:duration="13" />
-    <item android:drawable="@drawable/remote_202" android:duration="13" />
-    <item android:drawable="@drawable/remote_203" android:duration="13" />
-    <item android:drawable="@drawable/remote_204" android:duration="13" />
-    <item android:drawable="@drawable/remote_205" android:duration="13" />
-    <item android:drawable="@drawable/remote_206" android:duration="13" />
-    <item android:drawable="@drawable/remote_207" android:duration="13" />
-    <item android:drawable="@drawable/remote_208" android:duration="13" />
-    <item android:drawable="@drawable/remote_209" android:duration="13" />
-    <item android:drawable="@drawable/remote_210" android:duration="13" />
-    <item android:drawable="@drawable/remote_211" android:duration="13" />
-    <item android:drawable="@drawable/remote_212" android:duration="13" />
-    <item android:drawable="@drawable/remote_213" android:duration="13" />
-    <item android:drawable="@drawable/remote_214" android:duration="13" />
-    <item android:drawable="@drawable/remote_215" android:duration="13" />
-    <item android:drawable="@drawable/remote_216" android:duration="13" />
-    <item android:drawable="@drawable/remote_217" android:duration="13" />
-    <item android:drawable="@drawable/remote_218" android:duration="13" />
-    <item android:drawable="@drawable/remote_219" android:duration="13" />
-    <item android:drawable="@drawable/remote_220" android:duration="13" />
-    <item android:drawable="@drawable/remote_221" android:duration="13" />
-    <item android:drawable="@drawable/remote_222" android:duration="13" />
-    <item android:drawable="@drawable/remote_223" android:duration="13" />
-    <item android:drawable="@drawable/remote_224" android:duration="13" />
-    <item android:drawable="@drawable/remote_225" android:duration="13" />
-    <item android:drawable="@drawable/remote_226" android:duration="13" />
-    <item android:drawable="@drawable/remote_227" android:duration="13" />
-    <item android:drawable="@drawable/remote_228" android:duration="13" />
-    <item android:drawable="@drawable/remote_229" android:duration="13" />
-    <item android:drawable="@drawable/remote_230" android:duration="13" />
-    <item android:drawable="@drawable/remote_231" android:duration="13" />
-    <item android:drawable="@drawable/remote_232" android:duration="13" />
-    <item android:drawable="@drawable/remote_233" android:duration="13" />
-    <item android:drawable="@drawable/remote_234" android:duration="13" />
-    <item android:drawable="@drawable/remote_235" android:duration="13" />
-    <item android:drawable="@drawable/remote_236" android:duration="13" />
-    <item android:drawable="@drawable/remote_237" android:duration="13" />
-    <item android:drawable="@drawable/remote_238" android:duration="13" />
-    <item android:drawable="@drawable/remote_239" android:duration="13" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
deleted file mode 100644
index 2b58fc5..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_overlay_background.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!--
-     Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-
-    <stroke android:width="1dp" android:color="#33FFFFFF" />
-</shape>
diff --git a/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml b/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml
deleted file mode 100644
index e247dec..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_overlay_text_background.xml
+++ /dev/null
@@ -1,23 +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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-
-    <gradient
-        android:startColor="#B2000000"
-        android:endColor="#00000000"
-        android:angle="90"/>
-</shape>
diff --git a/packages/SystemUI/res/drawable/tv_pip_recents_overlay_scrim.xml b/packages/SystemUI/res/drawable/tv_pip_recents_overlay_scrim.xml
deleted file mode 100644
index 57bee75..0000000
--- a/packages/SystemUI/res/drawable/tv_pip_recents_overlay_scrim.xml
+++ /dev/null
@@ -1,23 +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.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-
-    <gradient
-        android:startColor="#80000000"
-        android:endColor="#00000000"
-        android:angle="90"/>
-</shape>
diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index 33effba..6d4365c 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -63,20 +63,21 @@
             systemui:hasOverlappingRendering="false"
             />
         <ImageView
-            android:id="@+id/mobile_type"
+            android:id="@+id/mobile_roaming"
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
+            android:src="@drawable/stat_sys_roaming"
+            android:contentDescription="@string/accessibility_data_connection_roaming"
+            android:visibility="gone"
             />
         <ImageView
-            android:id="@+id/mobile_roaming"
+            android:id="@+id/mobile_type"
             android:layout_width="wrap_content"
             android:layout_height="17dp"
-            android:paddingStart="22dp"
+            android:paddingStart="19dp"
             android:paddingTop="1.5dp"
             android:paddingBottom="3dp"
             android:scaleType="fitCenter"
-            android:src="@drawable/stat_sys_roaming"
-            android:contentDescription="@string/accessibility_data_connection_roaming"
             android:visibility="gone" />
     </FrameLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index ff22ffb..0c9858d 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -114,6 +114,7 @@
             android:layout_height="wrap_content"
             android:layout_gravity="end|center_vertical"
             android:layout_weight="1"
+            android:contentDescription="@string/notification_channel_switch_accessibility"
             android:background="@null" />
     </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout/notification_snooze.xml b/packages/SystemUI/res/layout/notification_snooze.xml
index 5bd64de..b70f24b 100644
--- a/packages/SystemUI/res/layout/notification_snooze.xml
+++ b/packages/SystemUI/res/layout/notification_snooze.xml
@@ -19,47 +19,56 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="@dimen/snooze_snackbar_min_height"
-    android:id="@+id/notification_snooze"
-    android:clickable="true"
-    android:gravity="center_vertical"
-    android:orientation="horizontal"
-    android:paddingStart="24dp"
-    android:paddingEnd="24dp"
-    android:background="@color/snooze_snackbar_bg">
-    
-    <TextView
-        android:id="@+id/snooze_option_default"
-        style="@style/TextAppearance.SnoozeSnackBar"
-        android:layout_width="wrap_content"
-       	android:layout_height="match_parent"
-       	android:gravity="center_vertical"
-      	android:drawableTint="@android:color/white"
-       	android:drawableEnd="@drawable/notification_expand_more"/>
-    
-    <android.widget.Space
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_weight="1"
-        />
-    
-    <TextView
-        android:id="@+id/undo"
-        style="@style/TextAppearance.SnoozeSnackBar.Button"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_marginEnd="8dp"
-        android:layout_marginStart="8dp"
-        android:background="@drawable/btn_borderless_rect"
-        android:layout_gravity="end"
-        android:text="@string/snooze_undo" />
-    
+    android:orientation="vertical"
+    android:background="@color/notification_guts_bg_color"
+    android:theme="@*android:style/Theme.DeviceDefault.Light">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:id="@+id/notification_snooze"
+        android:layout_height="@dimen/snooze_snackbar_min_height">
+
+        <TextView
+            android:id="@+id/snooze_option_default"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            android:layout_centerVertical="true"
+            android:paddingStart="16dp"
+            android:textColor="#DD000000"
+            android:paddingEnd="4dp"/>
+
+        <ImageView
+            android:id="@+id/expand_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_toEndOf="@+id/snooze_option_default"
+            android:layout_centerVertical="true"
+            android:paddingTop="1dp"
+            android:tint="#9E9E9E" />
+
+        <TextView
+            android:id="@+id/undo"
+            style="@style/TextAppearance.NotificationInfo.Button"
+            android:layout_width="wrap_content"
+            android:layout_height="36dp"
+            android:layout_marginEnd="8dp"
+            android:layout_alignParentEnd="true"
+            android:layout_centerVertical="true"
+            android:text="@string/snooze_undo" />
+    </RelativeLayout>
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="match_parent"
+        android:layout_height="0.5dp"
+        android:background="#9E9E9E" />
+
     <LinearLayout
         android:id="@+id/snooze_options"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingTop="8dp"
         android:paddingBottom="8dp"
-        android:orientation="vertical"/>
-    
+        android:orientation="vertical" />
+
 </com.android.systemui.statusbar.NotificationSnooze>
diff --git a/packages/SystemUI/res/layout/notification_snooze_option.xml b/packages/SystemUI/res/layout/notification_snooze_option.xml
new file mode 100644
index 0000000..aaf45f3
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_snooze_option.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 2017, The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<TextView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:layout_marginStart="@*android:dimen/notification_content_margin_start"
+        android:layout_marginEnd="@*android:dimen/notification_content_margin_end"
+        android:gravity="center_vertical"
+        android:textSize="14sp"
+        android:textColor="#DD000000"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_dismiss_view.xml b/packages/SystemUI/res/layout/pip_dismiss_view.xml
index 34228d9..058f59fa 100644
--- a/packages/SystemUI/res/layout/pip_dismiss_view.xml
+++ b/packages/SystemUI/res/layout/pip_dismiss_view.xml
@@ -27,6 +27,10 @@
         android:layout_gravity="bottom|center_horizontal"
         android:text="@string/pip_phone_dismiss_hint"
         android:textColor="#FFFFFFFF"
-        android:textSize="14sp" />
+        android:textSize="14sp"
+        android:shadowColor="@android:color/black"
+        android:shadowDx="-2"
+        android:shadowDy="2"
+        android:shadowRadius="0.01" />
 
 </FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_footer.xml b/packages/SystemUI/res/layout/quick_settings_footer.xml
index 8667a5a..bb1b288 100644
--- a/packages/SystemUI/res/layout/quick_settings_footer.xml
+++ b/packages/SystemUI/res/layout/quick_settings_footer.xml
@@ -14,41 +14,31 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:clickable="true"
     android:paddingBottom="@dimen/qs_tile_padding_top"
-    android:paddingTop="@dimen/qs_tile_padding_top" >
+    android:paddingTop="@dimen/qs_tile_padding_top"
+    android:paddingStart="@dimen/qs_footer_padding_start"
+    android:paddingEnd="@dimen/qs_footer_padding_end"
+    android:gravity="center_vertical"
+    android:background="?android:attr/colorPrimaryDark" >
 
     <TextView
         android:id="@+id/footer_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_centerHorizontal="true"
-        android:textSize="@dimen/qs_tile_text_size" />
+        android:gravity="start"
+        android:layout_weight="1"
+        android:textAppearance="@style/TextAppearance.QS.TileLabel"
+        android:textColor="?android:attr/textColorSecondary"/>
 
     <ImageView
         android:id="@+id/footer_icon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_marginEnd="8dp"
-        android:layout_toStartOf="@id/footer_text"
+        android:layout_width="@dimen/qs_footer_icon_size"
+        android:layout_height="@dimen/qs_footer_icon_size"
         android:contentDescription="@null"
-        android:src="@drawable/ic_qs_vpn"
-        android:visibility="invisible" />
+        android:src="@drawable/ic_info_outline" />
 
-    <!-- Only shown if both images are visible -->
-    <ImageView
-        android:id="@+id/footer_icon2"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerVertical="true"
-        android:layout_marginEnd="8dp"
-        android:layout_toStartOf="@id/footer_icon"
-        android:contentDescription="@null"
-        android:src="@drawable/ic_qs_network_logging"
-        android:visibility="invisible" />
-
-</RelativeLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index da7e4d7..5766dc1 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -52,9 +52,54 @@
             android:alpha="0.0"
             />
     </FrameLayout>
+    <ViewStub
+        android:id="@+id/connected_device_signals_stub"
+        android:layout="@layout/connected_device_signal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+    <LinearLayout
+        android:id="@+id/mobile_signal_group"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        >
+    </LinearLayout>
+    <View
+        android:id="@+id/wifi_signal_spacer"
+        android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
+        android:layout_height="4dp"
+        android:visibility="gone"
+        />
+    <FrameLayout
+        android:id="@+id/no_sims_combo"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:contentDescription="@string/accessibility_no_sims">
+        <com.android.systemui.statusbar.AlphaOptimizedImageView
+            android:theme="@style/DualToneLightTheme"
+            android:id="@+id/no_sims"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:src="@drawable/stat_sys_no_sims"
+            />
+        <com.android.systemui.statusbar.AlphaOptimizedImageView
+            android:theme="@style/DualToneDarkTheme"
+            android:id="@+id/no_sims_dark"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:src="@drawable/stat_sys_no_sims"
+            android:alpha="0.0"
+            />
+    </FrameLayout>
+    <View
+        android:id="@+id/wifi_airplane_spacer"
+        android:layout_width="@dimen/status_bar_airplane_spacer_width"
+        android:layout_height="4dp"
+        android:visibility="gone"
+        />
     <FrameLayout
         android:layout_height="17dp"
-        android:layout_width="wrap_content">
+        android:layout_width="wrap_content"
+        android:paddingStart="2dp">
         <ImageView
             android:id="@+id/wifi_in"
             android:layout_height="wrap_content"
@@ -96,50 +141,6 @@
             android:layout_width="wrap_content"
             />
     </FrameLayout>
-    <View
-        android:id="@+id/wifi_signal_spacer"
-        android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
-        android:layout_height="4dp"
-        android:visibility="gone"
-        />
-    <ViewStub
-        android:id="@+id/connected_device_signals_stub"
-        android:layout="@layout/connected_device_signal"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-    <LinearLayout
-        android:id="@+id/mobile_signal_group"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        >
-    </LinearLayout>
-    <FrameLayout
-        android:id="@+id/no_sims_combo"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:contentDescription="@string/accessibility_no_sims">
-        <com.android.systemui.statusbar.AlphaOptimizedImageView
-            android:theme="@style/DualToneLightTheme"
-            android:id="@+id/no_sims"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:src="@drawable/stat_sys_no_sims"
-            />
-        <com.android.systemui.statusbar.AlphaOptimizedImageView
-            android:theme="@style/DualToneDarkTheme"
-            android:id="@+id/no_sims_dark"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:src="@drawable/stat_sys_no_sims"
-            android:alpha="0.0"
-            />
-    </FrameLayout>
-    <View
-        android:id="@+id/wifi_airplane_spacer"
-        android:layout_width="@dimen/status_bar_airplane_spacer_width"
-        android:layout_height="4dp"
-        android:visibility="gone"
-        />
     <ImageView
         android:id="@+id/airplane"
         android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml
index c6bcd32..61ac6f69 100644
--- a/packages/SystemUI/res/layout/tv_pip_controls.xml
+++ b/packages/SystemUI/res/layout/tv_pip_controls.xml
@@ -40,7 +40,7 @@
         android:layout_width="100dp"
         android:layout_height="wrap_content"
         android:layout_marginStart="-50dp"
-        android:src="@drawable/ic_pause_white_24dp"
+        android:src="@drawable/ic_pause_white"
         android:text="@string/pip_pause"
         android:visibility="gone" />
 </merge>
diff --git a/packages/SystemUI/res/layout/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
deleted file mode 100644
index fe80b94..0000000
--- a/packages/SystemUI/res/layout/tv_pip_onboarding.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?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.
-*/
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/pip_onboarding"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-    <View
-        android:id="@+id/background"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="#000000"
-        android:alpha="0" />
-
-    <ImageView
-        android:id="@+id/remote"
-        android:layout_width="72dp"
-        android:layout_height="273dp"
-        android:layout_marginTop="136dp"
-        android:layout_marginStart="304dp"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentStart="true"
-        android:adjustViewBounds="true"
-        android:src="@drawable/remote"
-        android:alpha="0" />
-    <ImageView
-        android:id="@+id/remote_button"
-        android:layout_width="50dp"
-        android:layout_height="50dp"
-        android:layout_marginTop="256dp"
-        android:layout_marginStart="315dp"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentStart="true"
-        android:scaleType="fitXY"
-        android:src="@drawable/tv_pip_onboarding_remote"
-        android:alpha="0" />
-    <TextView
-        android:id="@+id/title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="188dp"
-        android:layout_marginStart="406dp"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentStart="true"
-        android:fontFamily="sans-serif"
-        android:textSize="24sp"
-        android:textColor="#EEEEEE"
-        android:text="@string/pip_onboarding_title"
-        android:alpha="0" />
-    <TextView
-        android:id="@+id/description"
-        android:layout_width="200dp"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="4dp"
-        android:layout_marginStart="408dp"
-        android:layout_below="@id/title"
-        android:layout_alignParentStart="true"
-        android:fontFamily="sans-serif"
-        android:textSize="14sp"
-        android:textColor="#EEEEEE"
-        android:lineSpacingMultiplier="1.46286"
-        android:text="@string/pip_onboarding_description"
-        android:alpha="0" />
-    <Button
-        android:id="@+id/button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="16dp"
-        android:layout_marginStart="408dp"
-        android:layout_below="@id/description"
-        android:layout_alignParentStart="true"
-        android:gravity="center"
-        android:paddingTop="10dp"
-        android:paddingBottom="10dp"
-        android:paddingStart="24dp"
-        android:paddingEnd="24dp"
-        android:fontFamily="sans-serif-condensed"
-        android:textSize="16sp"
-        android:textColor="#FFFFFF"
-        android:textAllCaps="true"
-        android:text="@string/pip_onboarding_button"
-        android:alpha="0"
-        android:background="#009688"
-        android:elevation="4dp" />
-</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml
deleted file mode 100644
index 608680c..0000000
--- a/packages/SystemUI/res/layout/tv_pip_overlay.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?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.
-*/
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@drawable/tv_pip_overlay_background">
-
-    <TextView
-        android:id="@+id/guide_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:paddingTop="6dp"
-        android:paddingBottom="6dp"
-        android:paddingStart="10dp"
-        android:paddingEnd="10dp"
-        android:textSize="14sp"
-        android:textColor="#EEEEEE"
-        android:fontFamily="sans-serif"
-        android:background="@drawable/tv_pip_overlay_text_background"
-        android:lineSpacingMultiplier="1.465"
-        android:gravity="center"
-        android:maxLines="2"
-        android:text="@string/pip_hold_home" />
-</RelativeLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 4f15506..5859838 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Battery laai tans, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> persent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Stelselinstellings"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Kennisgewings"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Sien alle kennisgewings"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Verwyder kennisgewing"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS geaktiveer."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS soek ligging."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is af"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is af"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Moenie steur nie is af"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\'n Outomatiese reël (<xliff:g id="ID_1">%s</xliff:g>) het Moenie steur nie aangeskakel. Hou huidige instellings?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\'n Program (<xliff:g id="ID_1">%s</xliff:g>) het Moenie steur nie aangeskakel. Hou huidige instellings?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\'n Outomatiese reël of \'n program het Moenie steur nie aangeskakel. Hou huidige instellings?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Tot <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Hou"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Vervang"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index a812fbd..97b8317 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ባትሪ ኃይል በመሙላት ላይ፣ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> በመቶ።"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"የስርዓት ቅንብሮች"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"ማሳወቂያዎች"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"ሁሉንም ማሳወቂያዎች ይመልከቱ"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጽዳ"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ነቅቷል።"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS በማግኘት ላይ።"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ጠፍቷል"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ብሉቱዝ ጠፍቷል"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"አትረብሽ ጠፍቷል"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"አትረብሽ በአንድ ራስ-ሰር ደንብ (<xliff:g id="ID_1">%s</xliff:g>) በርቷል። የአሁኖቹ ቅንብሮች ይቀመጡ?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"አትረብሽ በአንድ መተግበሪያ (<xliff:g id="ID_1">%s</xliff:g>) በርቷል። የአሁኖቹ ቅንብሮች ይቀመጡ?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"አትረብሽ በአንድ ራስ-ሰር ደንብ ወይም መተግበሪያ በርቷል። የአሁኖቹ ቅንብሮች ይቀመጡ?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"እስከ <xliff:g id="ID_1">%s</xliff:g> ድረስ"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"አቆይ"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"ተካ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 357f4db..f646dfa 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -168,8 +168,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"جارٍ شحن البطارية، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> بالمائة."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"إعدادات النظام."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"الإشعارات."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"الاطلاع على جميع الإشعارات"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"محو الإشعار."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"‏تم تمكين GPS."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"‏الحصول على GPS."</string>
@@ -759,9 +758,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"‏تم إيقاف شبكة Wi-Fi"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"تم إيقاف البلوتوث."</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"تم إيقاف وضع \"الرجاء عدم الإزعاج\""</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"تم تشغيل وضع \"الرجاء عدم الإزعاج\" بواسطة قاعدة تلقائية (<xliff:g id="ID_1">%s</xliff:g>). هل تريد الإبقاء على الإعدادات الحالية؟"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"تم تشغيل وضع \"الرجاء عدم الإزعاج\" بواسطة تطبيق (<xliff:g id="ID_1">%s</xliff:g>). هل تريد الإبقاء على الإعدادات الحالية؟"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"تم تشغيل وضع \"الرجاء عدم الإزعاج\" بواسطة قاعدة تلقائية أو تطبيق. هل تريد الإبقاء على الإعدادات الحالية؟"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"حتى <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"الإبقاء على الإعدادات"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"استبدال"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 5d485d5..3223aa7 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Batareya doldurulur, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> faiz."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Sistem parametrləri"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Bildirişlər."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Bütün bildirişlərə baxın"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Bildirişi təmizlə."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktivdir."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS əldə edilir."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi deaktivdir"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth deaktivdir"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Narahat Etməyin\" deaktivdir"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"Narahat etməyin\" rejimi (<xliff:g id="ID_1">%s</xliff:g>) avtomatik qaydası tərəfindən aktiv edildi. Cari ayarlar saxlanılsın?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"Narahat etməyin\" (<xliff:g id="ID_1">%s</xliff:g>) tətbiqi tərəfindən aktiv edildi. Cari ayarlar saxlanılsın?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"Narahat etməyin\" rejimi avtomatik qayda və ya tətbiq tərəfindən aktiv edildi. Cari ayarlar saxlanılsın?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> vaxtına qədər"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Saxlayın"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Əvəz edin"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 7fe9534..1a1883c 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -165,8 +165,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Baterija se puni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procenata."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Sistemska podešavanja."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Obaveštenja."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Pogledajte sva obaveštenja"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Obriši obaveštenje."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS je omogućen."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Učitavanje GPS-a."</string>
@@ -747,9 +746,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Režim Ne uznemiravaj je isključen"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Automatsko pravilo (<xliff:g id="ID_1">%s</xliff:g>) je uključilo režim Ne uznemiravaj. Želite li da zadržite aktuelna podešavanja?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Aplikacija (<xliff:g id="ID_1">%s</xliff:g>) je uključila režim Ne uznemiravaj. Želite li da zadržite aktuelna podešavanja?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Automatsko pravilo ili aplikacija su uključili režim Ne uznemiravaj. Želite li da zadržite aktuelna podešavanja?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Zameni"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index cacf21b..59aa605 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -168,8 +168,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Зарадка акумулятара, працэнтаў: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Сістэмныя налады."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Апавяшчэнні."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Паказаць усе апавяшчэнні"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Выдаліць апавяшчэнне."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS уключаны."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Атрыманне GPS."</string>
@@ -753,9 +752,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi выключаны"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth выключаны"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Рэжым \"Не турбаваць\" выключаны"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Рэжым \"Не турбаваць\" быў уключаны аўтаматычным правілам (<xliff:g id="ID_1">%s</xliff:g>). Пакінуць бягучыя налады?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Рэжым \"Не турбаваць\" быў уключаны праграмай (<xliff:g id="ID_1">%s</xliff:g>). Пакінуць бягучыя налады?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Рэжым \"Не турбаваць\" быў уключаны аўтаматычным правілам ці праграмай. Пакінуць бягучыя налады?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Да <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Пакінуць"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Замяніць"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 226b565..a9bcf11b 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Батерията се зарежда – <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> процента."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Системни настройки."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Известия."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Вижте всички известия"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Изчистване на известието."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS е активиран."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS се придобива."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Функцията за Wi‑Fi е изключена"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Функцията за Bluetooth е изключена"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Режимът „Не безпокойте“ е изключен"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Режимът „Не безпокойте“ бе включен от автоматично правило (<xliff:g id="ID_1">%s</xliff:g>). Искате ли да запазите текущите настройки?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Режимът „Не безпокойте“ бе включен от приложение (<xliff:g id="ID_1">%s</xliff:g>). Искате ли да запазите текущите настройки?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Режимът „Не безпокойте“ бе включен от автоматично правило или от приложение. Искате ли да запазите текущите настройки?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Запазване"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Замяна"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 056ab31..c0f6f51 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -743,9 +743,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"ওয়াই ফাই বন্ধ আছে"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ব্লুটুথ বন্ধ আছে"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"বিরক্ত করবেন না বিকল্পটি বন্ধ আছে"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"বিরক্ত করবেন না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম (<xliff:g id="ID_1">%s</xliff:g>) এর দ্বারা চালু করা হয়েছে। বর্তমান সেটিংস রাখতে চান?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"বিরক্ত করবেন না বিকল্পটি একটি অ্যাপ (<xliff:g id="ID_1">%s</xliff:g>) এর দ্বারা চালু করা হয়েছে। বর্তমান সেটিংস রাখতে চান?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"বিরক্ত করবেন না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম বা অ্যাপের দ্বারা চালু করা হয়েছে। বর্তমান সেটিংস রাখতে চান?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> পর্যন্ত"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"রাখুন"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"বদলে দিন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 4f15073..2ea22ec 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -165,8 +165,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Punjenje baterije, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procenata."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Postavke sistema."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Obavještenja."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Vidite sva obavještenja"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Ukloniti obavještenje."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS omogućen."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Uspostavljanje GPS veze."</string>
@@ -749,9 +748,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi veza je isključena"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Opcija Ne ometaj je isključena"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Automatsko pravilo (<xliff:g id="ID_1">%s</xliff:g>) uključilo je opciju Ne ometaj. Želite li zadržati trenutne postavke?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Aplikacija (<xliff:g id="ID_1">%s</xliff:g>) uključila je opciju Ne ometaj. Želite li zadržati trenutne postavke?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Automatsko pravilo ili aplikacija uključili su opciju Ne ometaj. Želite li zadržati trenutne postavke?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Zamijeni"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index d95c991..1b211d2 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"La bateria s\'està carregant, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>%%."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Configuració del sistema."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificacions."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Mostra totes les notificacions"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Esborra la notificació."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activat."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"S\'està adquirint el GPS."</string>
@@ -467,7 +466,7 @@
     <string name="monitoring_description_app_work" msgid="4612997849787922906">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional. El perfil està connectat a <xliff:g id="APPLICATION">%2$s</xliff:g>, que pot supervisar la teva activitat a la xarxa de treball, com ara els correus electrònics, les aplicacions i els llocs web.\n\nPer obtenir més informació, contacta amb l\'administrador."</string>
     <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional. El perfil està connectat a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pot supervisar la teva activitat a la xarxa de treball, com ara els correus electrònics, les aplicacions i els llocs web.\n\nTambé estàs connectat a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pot supervisar la teva activitat personal a la xarxa."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositiu continuarà bloquejat fins que no el desbloquegis manualment."</string>
-    <string name="hidden_notifications_title" msgid="7139628534207443290">"Obtén notificacions més ràpidament"</string>
+    <string name="hidden_notifications_title" msgid="7139628534207443290">"Rep notificacions més ràpidament"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"Mostra-les abans de desbloquejar"</string>
     <string name="hidden_notifications_cancel" msgid="3690709735122344913">"No"</string>
     <string name="hidden_notifications_setup" msgid="41079514801976810">"Configura"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"La Wi-Fi està desactivada"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"El Bluetooth està desactivat"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"El mode No molestis està desactivat"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Una regla automàtica (<xliff:g id="ID_1">%s</xliff:g>) ha activat el mode No molestis. Vols conservar la configuració actual?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Una aplicació (<xliff:g id="ID_1">%s</xliff:g>) ha activat el mode No molestis. Vols conservar la configuració actual?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Una regla automàtica o una aplicació han activat el mode No molestis. Vols conservar la configuració actual?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Fins a les <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Conserva"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Substitueix"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 6da1021..68cb7e8 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -168,8 +168,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Systémová nastavení."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Oznámení."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Zobrazit všechna oznámení"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Vymazat oznámení."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS je povoleno."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Zaměřování GPS."</string>
@@ -753,9 +752,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je vypnuta"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je vypnuto"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Režim Nerušit je vypnut"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Režim Nerušit byl zapnut automatickým pravidlem (<xliff:g id="ID_1">%s</xliff:g>). Ponechat aktuální nastavení?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Režim Nerušit byl zapnut aplikací (<xliff:g id="ID_1">%s</xliff:g>). Ponechat aktuální nastavení?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Režim Nerušit byl zapnut automatickým pravidlem nebo aplikací. Ponechat aktuální nastavení?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Zachovat"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Nahradit"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 330265b..e304b54 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Batteriet oplades. <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Systemindstillinger."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Underretninger."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Se alle underretninger"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Ryd underretning."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktiveret."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS samler data."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er slået fra"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth er slået fra"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Forstyr ikke er slået fra"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Forstyr ikke blev aktiveret af en automatisk regel (<xliff:g id="ID_1">%s</xliff:g>). Vil du beholde de nuværende indstillinger?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Forstyr ikke blev aktiveret af en app (<xliff:g id="ID_1">%s</xliff:g>). Vil du beholde de nuværende indstillinger?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Forstyr ikke blev aktiveret af en automatisk regel eller en app. Vil du beholde de nuværende indstillinger?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Indtil <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Behold"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Erstat"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 434ce6d..9780181 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Systemeinstellungen"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Benachrichtigungen"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Alle Benachrichtigungen ansehen"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Benachrichtigung löschen"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktiviert"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-Signal abrufen"</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"WLAN ist deaktiviert"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ist deaktiviert"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Nicht stören\" ist deaktiviert"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"Nicht stören\" wurde von einer automatischen Regel aktiviert (<xliff:g id="ID_1">%s</xliff:g>). Aktuelle Einstellungen beibehalten?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"Nicht stören\" wurde von einer App aktiviert (<xliff:g id="ID_1">%s</xliff:g>). Aktuelle Einstellungen beibehalten?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"Nicht stören\" wurde von einer automatischen Regel oder einer App aktiviert. Aktuelle Einstellungen beibehalten?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Bis <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Beibehalten"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Ersetzen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ef14db1..710c455 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Φόρτιση μπαταρίας, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> τοις εκατό."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Ρυθμίσεις συστήματος."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Ειδοποιήσεις."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Δείτε όλες τις ειδοποιήσεις"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Διαγραφή ειδοποίησης."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"Το GPS ενεργοποιήθηκε."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Προσδιορισμός GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Το Wi-Fi είναι ανενεργό"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Το Bluetooth είναι ανενεργό"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Η λειτουργία \"Μην ενοχλείτε\" είναι ανενεργή"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε από έναν αυτόματο κανόνα (<xliff:g id="ID_1">%s</xliff:g>). Διατήρηση τρεχουσών ρυθμίσεων;"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε από μια εφαρμογή (<xliff:g id="ID_1">%s</xliff:g>). Διατήρηση τρεχουσών ρυθμίσεων;"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Η λειτουργία \"Μην ενοχλείτε\" ενεργοποιήθηκε από έναν αυτόματο κανόνα ή μια εφαρμογή. Διατήρηση τρεχουσών ρυθμίσεων;"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Έως τις <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Διατήρηση"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Αντικατάσταση"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 5bbd610..723be15 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"System settings"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"See all notifications"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Clear notification."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS enabled."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS acquiring."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Do Not Disturb was turned on by an automatic rule (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Do Not Disturb was turned on by an app (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Do Not Disturb was turned on by an automatic rule or app. Keep current settings?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 5bbd610..723be15 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"System settings"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"See all notifications"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Clear notification."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS enabled."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS acquiring."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Do Not Disturb was turned on by an automatic rule (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Do Not Disturb was turned on by an app (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Do Not Disturb was turned on by an automatic rule or app. Keep current settings?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 5bbd610..723be15 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"System settings"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"See all notifications"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Clear notification."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS enabled."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS acquiring."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is off"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Do Not Disturb is off"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Do Not Disturb was turned on by an automatic rule (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Do Not Disturb was turned on by an app (<xliff:g id="ID_1">%s</xliff:g>). Keep current settings?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Do Not Disturb was turned on by an automatic rule or app. Keep current settings?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Until <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Keep"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Replace"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index fc786ec..16e2549 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Configuración del sistema"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificaciones"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas las notificaciones"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Eliminar notificación"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS habilitado"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Adquisición de GPS"</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desactivado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"No interrumpir desactivado"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Una regla automática activó No interrumpir (<xliff:g id="ID_1">%s</xliff:g>). ¿Deseas mantener la configuración actual?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Una app (<xliff:g id="ID_1">%s</xliff:g>) activó No interrumpir. ¿Deseas mantener la configuración actual?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Una app o regla automática activó No interrumpir. ¿Deseas mantener la configuración actual?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Hasta la(s) <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Mantener"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Reemplazar"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 677f8ef..2c21bae 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Ajustes del sistema"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificaciones"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas las notificaciones"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Borrar notificación"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS habilitado"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Obteniendo ubicación..."</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desactivado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"No molestar está desactivado"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Una regla automática (<xliff:g id="ID_1">%s</xliff:g>) ha activado No molestar. ¿Quieres conservar esta configuración?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Una aplicación (<xliff:g id="ID_1">%s</xliff:g>) ha activado No molestar. ¿Quieres conservar esta configuración?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Una aplicación o una regla automática han activado No molestar. ¿Quieres conservar esta configuración?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Hasta <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Conservar"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Reemplazar"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 055d39f..fbe6dfc 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Süsteemiseaded"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Märguanded"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Kõikide märguannete kuvamine"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Märguande eemaldamine."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS on lubatud."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-signaali otsimine."</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"WiFi on välja lülitatud"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth on välja lülitatud"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Funktsioon Mitte segada on välja lülitatud"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Automaatne reegel lülitas funktsiooni Mitte segada sisse (<xliff:g id="ID_1">%s</xliff:g>). Kas jätta praegused seaded aktiivseks?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Rakendus lülitas funktsiooni Mitte segada sisse (<xliff:g id="ID_1">%s</xliff:g>). Kas jätta praegused seaded aktiivseks?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Automaatne reegel või rakendus lülitas funktsiooni Mitte segada sisse. Kas jätta praegused seaded aktiivseks?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Kuni ajani <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Säilita"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Asenda"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 02c8617..c802e8a 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Sistemaren ezarpenak."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Jakinarazpenak."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ikusi jakinarazpen guztiak"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Garbitu jakinarazpena."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktibatuta."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS seinalea lortzen."</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi konexioa desaktibatuta dago"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth konexioa desaktibatuta dago"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Ez molestatu\" modua desaktibatuta dago"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"Ez molestatu\" modua aktibatu du arau automatiko batek (<xliff:g id="ID_1">%s</xliff:g>). Uneko ezarpenak mantendu nahi dituzu?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"Ez molestatu\" modua aktibatu du aplikazio batek (<xliff:g id="ID_1">%s</xliff:g>). Uneko ezarpenak mantendu nahi dituzu?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"Ez molestatu\" modua aktibatu du arau automatiko edo aplikazio batek. Uneko ezarpenak mantendu nahi dituzu?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> arte"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Utzi bere horretan"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Ordeztu"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 0408f71..9c35ddc 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"در حال شارژ باتری، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> درصد"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"تنظیمات سیستم."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"اعلان‌ها."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"دیدن همه اعلان‌ها"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"پاک کردن اعلان"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"‏GPS فعال شد."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"‏دستیابی به GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi خاموش است"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"بلوتوث خاموش است"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"«مزاحم نشوید» خاموش است"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"قانون خودکاری (<xliff:g id="ID_1">%s</xliff:g>) حالت «مزاحم نشوید» را روشن کرده است. تنظیمات کنونی حفظ شود؟"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"برنامه‌ای (<xliff:g id="ID_1">%s</xliff:g>) حالت «مزاحم نشوید» را روشن کرده است. تنظیمات کنونی حفظ شود؟"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"قانون خودکار یا برنامه‌ای حالت «مزاحم نشوید» را روشن کرده است. تنظیمات کنونی حفظ شود؟"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"تا <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"حفظ شود"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"جایگزین کردن"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 35e5e5a..a949b8b 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Akku latautuu: <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> prosenttia"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Järjestelmän asetukset"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Ilmoitukset"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Näytä kaikki ilmoitukset"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Tyhjennä ilmoitus"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS käytössä."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Haetaan GPS-signaalia."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi on pois käytöstä"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ei ole käytössä"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Älä häiritse ‑tila on pois käytöstä"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Automaattinen sääntö otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>). Pidetäänkö nykyiset asetukset?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Sovellus otti käyttöön Älä häiritse ‑tilan (<xliff:g id="ID_1">%s</xliff:g>). Pidetäänkö nykyiset asetukset?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Automaattinen sääntö tai sovellus otti käyttöön Älä häiritse ‑tilan. Pidetäänkö nykyiset asetukset?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> asti"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Säilytä"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Korvaa"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 4331edf..ffbd493 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Paramètres système"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Afficher toutes les notifications"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Supprimer la notification"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activé"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Acquisition de données GPS"</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Le Wi-Fi est désactivé"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Le Bluetooth est désactivé"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Le mode Ne pas déranger est désactivé"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Le mode Ne pas déranger a été activé par une règle automatique (<xliff:g id="ID_1">%s</xliff:g>). Garder les paramètres actuels?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Le mode Ne pas déranger a été activé par une application (<xliff:g id="ID_1">%s</xliff:g>). Garder les paramètres actuels?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Le mode Ne pas déranger a été activé par une règle automatique ou une application. Garder les paramètres actuels?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Jusqu\'à <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Garder"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Remplacer"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 661d2d8..d7f7115 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Paramètres système"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Afficher toutes les notifications"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Supprimer la notification"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activé"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Acquisition de données GPS"</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi désactivé"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth désactivé"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Mode \"Ne pas déranger\" désactivé"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Le mode \"Ne pas déranger\" a été activé par une règle automatique (<xliff:g id="ID_1">%s</xliff:g>). Conserver les paramètres actuels ?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Le mode \"Ne pas déranger\" a été activé par une application (<xliff:g id="ID_1">%s</xliff:g>). Conserver les paramètres actuels ?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Le mode \"Ne pas déranger\" a été activé par une règle automatique ou une application. Conserver les paramètres actuels ?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Jusqu\'à <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Conserver"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Remplacer"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index b5790c0..ec65726 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Configuración do sistema"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificacións"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas as notificacións"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Eliminar notificación."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activado"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Obtendo GPS."</string>
@@ -744,10 +743,13 @@
     <string name="mobile_data" msgid="7094582042819250762">"Datos móbiles"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"A wifi está desactivada"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"O Bluetooth está desactivado"</string>
-    <string name="dnd_is_off" msgid="6167780215212497572">"Non molestar está desactivado"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Unha norma automática (<xliff:g id="ID_1">%s</xliff:g>) activou Non molestar. Queres manter a configuración actual?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Unha aplicación (<xliff:g id="ID_1">%s</xliff:g>) activou Non molestar. Queres manter a configuración actual?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Unha aplicación ou norma automática activou Non molestar. Queres manter a configuración actual?"</string>
+    <string name="dnd_is_off" msgid="6167780215212497572">"O modo Non molestar está desactivado"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Ata: <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Substituír"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 53d1e1c..3c3681d 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -743,9 +743,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi બંધ છે"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth બંધ છે"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"ખલેલ પાડશો નહીં બંધ છે"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"ખલેલ પાડશો નહીં એક સ્વચાલિત નિયમ દ્વારા ચાલુ કરાયું હતું (<xliff:g id="ID_1">%s</xliff:g>). વર્તમાન સેટિંગ્સ રાખીએ?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"ખલેલ પાડશો નહીં એક ઍપ્લિકેશન દ્વારા ચાલુ કરાયું હતું. (<xliff:g id="ID_1">%s</xliff:g>). વર્તમાન સેટિંગ્સ રાખીએ?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"ખલેલ પાડશો નહીં એક સ્વચાલિત નિયમ અથવા ઍપ્લિકેશન દ્વારા ચાલુ કરાયું હતું. વર્તમાન સેટિંગ્સ રાખીએ?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> સુધી"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"રાખો"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"બદલો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 15a9621..e4c1071 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"बैटरी चार्ज हो रही है, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"सिस्टम सेटिंग."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचनाएं."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"सभी नोटिफ़िकेशन देखें"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"नोटिफिकेशन साफ़ करें"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त करना."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"वाई-फ़ाई बंद है"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटूथ बंद है"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"परेशान न करें बंद है"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"एक ऑटोमैटिक नियम (<xliff:g id="ID_1">%s</xliff:g>) ने परेशान न करें को चालू कर दिया था. क्या अभी वाली सेटिंग बनाए रखें?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"एक ऐप्लिकेशन (<xliff:g id="ID_1">%s</xliff:g>) ने परेशान न करें को चालू कर दिया था. क्या अभी वाली सेटिंग बनाए रखें?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"एक ऑटोमैटिक नियम या ऐप्लिकेशन ने परेशान न करें को चालू कर दिया था. क्या अभी वाली सेटिंग बनाए रखें?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> तक"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"रखें"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"बदलें"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f354132..9e138ae 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -165,8 +165,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Baterija se puni, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> posto."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Postavke sustava."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Obavijesti."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Pogledajte sve obavijesti"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Brisanje obavijesti"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS je omogućen."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Dohvaćanje GPS-a."</string>
@@ -747,9 +746,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je isključen"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Način Ne uznemiravaj isključen"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Način Ne uznemiravaj uključen je automatskim pravilom (<xliff:g id="ID_1">%s</xliff:g>). Želite li zadržati trenutačne postavke?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Način Ne uznemiravaj uključila je aplikacija (<xliff:g id="ID_1">%s</xliff:g>). Želite li zadržati trenutačne postavke?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Način Ne uznemiravaj uključen je automatskim pravilom ili ga je uključila aplikacija. Želite li zadržati trenutačne postavke?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Zadrži"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Zamijeni"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d2e37e9..a34da65 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Akkumulátor töltése folyamatban, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> százalék."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Rendszerbeállítások"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Értesítések"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Összes értesítés megtekintése"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Értesítés törlése"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS engedélyezve."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS lekérése."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"A Wi-Fi ki van kapcsolva"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"A Bluetooth ki van kapcsolva"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"A „Ne zavarjanak” mód ki van kapcsolva"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Az egyik automatikus szabály (<xliff:g id="ID_1">%s</xliff:g>) bekapcsolta a „Ne zavarjanak” módot. Megtartja a jelenlegi beállításokat?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Az egyik alkalmazás (<xliff:g id="ID_1">%s</xliff:g>) bekapcsolta a „Ne zavarjanak” módot. Megtartja a jelenlegi beállításokat?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Az egyik alkalmazás vagy automatikus szabály bekapcsolta a „Ne zavarjanak” módot. Megtartja a jelenlegi beállításokat?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Eddig: <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Megtartás"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Csere"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 8d6d823..6635e61 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Մարտկոցը լիցքավորվում է: Լիցքը <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> տոկոս է:"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Համակարգի կարգավորումներ:"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Ծանուցումներ:"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Տեսնել բոլոր ծանուցումները"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Մաքրել ծանուցումը:"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS-ը միացված է:"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-ի ստացում:"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi-ն անջատված է"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth-ն անջատված է"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Չանհանգստացնելու ռեժիմն անջատված է"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Չանհանգստացնելու ռեժիմն անջատվել է ավտոմատ կանոնի կողմից (<xliff:g id="ID_1">%s</xliff:g>)։ Պահպանե՞լ ընթացիկ կարգավորումները։"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Չանհանգստացնելու ռեժիմն անջատվել է հավելվածի կողմից (<xliff:g id="ID_1">%s</xliff:g>)։ Պահպանե՞լ ընթացիկ կարգավորումները։"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Չանհանգստացնելու ռեժիմն անջատվել է ավտոմատ կանոնի կամ հավելվածի կողմից։ Պահպանե՞լ ընթացիկ կարգավորումները։"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Մինչև <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Պահել"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Փոխարինել"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 4d2080c..6c079440 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Mengisi daya baterai, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> persen."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Setelan sistem."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifikasi."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Lihat semua notifikasi"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Menghapus pemberitahuan."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS diaktifkan."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Memperoleh GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi nonaktif"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth nonaktif"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Fitur Jangan Ganggu nonaktif"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Fitur Jangan Ganggu diaktifkan oleh aturan otomatis (<xliff:g id="ID_1">%s</xliff:g>). Simpan setelan saat ini?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Fitur Jangan Ganggu diaktifkan oleh aplikasi (<xliff:g id="ID_1">%s</xliff:g>). Simpan setelan saat ini?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Fitur Jangan Ganggu diaktifkan oleh aplikasi atau aturan otomatis. Simpan setelan saat ini?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Hingga <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Simpan"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Ganti"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index f00d666..57e031d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Rafhlaða í hleðslu, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> prósent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Kerfisstillingar."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Tilkynningar."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Sjá allar tilkynningar"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Hreinsa tilkynningu."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS virkt."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Tenging við GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Slökkt á Wi-Fi"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Slökkt á Bluetooth"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Slökkt á „Ónáðið ekki“"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Sjálfvirk regla (<xliff:g id="ID_1">%s</xliff:g>) kveikti á „Ónáðið ekki“. Halda núverandi stillingum?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Forrit (<xliff:g id="ID_1">%s</xliff:g>) kveikti á „Ónáðið ekki“. Halda núverandi stillingum?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Sjálfvirk regla eða forrit slökkti á „Ónáðið ekki“. Halda núverandi stillingum?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Þar til <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Halda"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Skipta út"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0719397..1aab341 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Impostazioni di sistema."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifiche."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Visualizza tutte le notifiche"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Cancella notifica."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS abilitato."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Acquisizione GPS."</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi disattivato"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth non attivo"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Funzione Non disturbare disattivata"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"La funzione Non disturbare è stata attivata da una regola automatica (<xliff:g id="ID_1">%s</xliff:g>). Mantenere le impostazioni attuali?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"La funzione Non disturbare è stata attivata da un\'app (<xliff:g id="ID_1">%s</xliff:g>). Mantenere le impostazioni attuali?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"La funzione Non disturbare è stata attivata da una regola automatica o da un\'app. Mantenere le impostazioni attuali?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Fino alle ore <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Mantieni"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Sostituisci"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index b5a1e67..ab821b6 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -166,8 +166,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"טעינת סוללה, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> אחוז."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"הגדרות מערכת"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"התראות"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"הצגת כל ההודעות"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"נקה התראה"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"‏GPS מופעל."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"‏השגת GPS."</string>
@@ -751,9 +750,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi כבוי"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"‏Bluetooth כבוי"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"מצב \'נא לא להפריע\' כבוי"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"מצב \'נא לא להפריע\' הופעל על ידי כלל אוטומטי (<xliff:g id="ID_1">%s</xliff:g>). האם לשמור את ההגדרות הקיימות?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"מצב \'נא לא להפריע\' הופעל על ידי האפליקציה (<xliff:g id="ID_1">%s</xliff:g>). האם לשמור את ההגדרות הקיימות?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"מצב \'נא לא להפריע\' הופעל על ידי כלל אוטומטי או אפליקציה. האם לשמור את ההגדרות הקיימות?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"עד <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"שמור"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"החלף"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 06f761a..9454d54 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"システム設定。"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"通知をすべて表示"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"通知を消去。"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPSが有効です。"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS取得中です。"</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi は OFF です"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth は OFF です"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"マナーモードは OFF です"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"マナーモードが自動ルール(<xliff:g id="ID_1">%s</xliff:g>)によって ON になりました。現在の設定を維持しますか?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"マナーモードがアプリ(<xliff:g id="ID_1">%s</xliff:g>)によって ON になりました。現在の設定を維持しますか?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"マナーモードが自動ルールまたはアプリによって ON になりました。現在の設定を維持しますか?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"終了時間: <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"設定を維持"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"設定を変更"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 94884da..5281011 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ბატარეა იტენება, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> პროცენტი."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"სისტემის პარამეტრები."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"შეტყობინებები"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"ყველა შეტყობინების ნახვა"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"შეტყობინებების გასუფთავება."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS გააქტიურდა."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-ის დადგენა."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi გამორთულია"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth გამორთულია"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"„არ შემაწუხოთ“ რეჟიმი გამორთულია"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"„არ შემაწუხოთ“ ჩართულია ავტომატური წესის მიხედვით (<xliff:g id="ID_1">%s</xliff:g>). გსურთ მიმდინარე პარამეტრების შენარჩუნება?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"„არ შემაწუხოთ“ ჩართულია აპის მიერ (<xliff:g id="ID_1">%s</xliff:g>). გსურთ მიმდინარე პარამეტრების შენარჩუნება?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"„არ შემაწუხოთ“ ჩართულია ავტომატური წესის მიხედვით ან აპის მიერ. გსურთ მიმდინარე პარამეტრების შენარჩუნება?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g>-მდე"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"შენარჩუნება"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"ჩანაცვლება"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 5a05e01..0ae02cc 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Батарея зарядталуда, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> пайыз."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Жүйе параметрлері."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Хабарлар."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Барлық хабарландыруды қарау"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Хабарларды өшіру."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS қосылған."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS қыземтін шығару."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өшірулі"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth өшірулі"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Мазаламау\" режимі өшірулі"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"Мазаламау\" режимі (<xliff:g id="ID_1">%s</xliff:g>) автоматты ережесі арқылы қосылды. Ағымдағы параметрлер қалсын ба?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"Мазаламау\" режимі (<xliff:g id="ID_1">%s</xliff:g>) қолданбасы арқылы қосылды. Ағымдағы параметрлер қалсын ба?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"Мазаламау\" режимі автоматты ереже немесе қолданба арқылы қосылды. Ағымдағы параметрлер қалсын ба?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> дейін"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Қалсын"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Ауыстыру"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index a259301..6545d3a 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"កំពុងសាកថ្ម <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ភាគរយ"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"ការ​កំណត់​ប្រព័ន្ធ​។"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"ការ​ជូន​ដំណឹង។"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"មើល​ការជូនដំណឹង​ទាំងអស់"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"សម្អាត​ការ​ជូន​ដំណឹង។"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"បាន​បើក GPS ។"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ទទួល​​ GPS ។"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi បាន​បិទ"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ប៊្លូធូស​បាន​បិទ"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"មុខងារ​កុំរំខាន​បាន​បិទ"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"មុខងារ​កុំរំខាន​ត្រូវបានបើក​ដោយ​ច្បាប់​ស្វ័យប្រវត្តិ (<xliff:g id="ID_1">%s</xliff:g>)។ រក្សា​ការកំណត់​បច្ចុប្បន្ន​នៅ​ដដែល?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"មុខងារ​កុំរំខាន​ត្រូវបាន​បើក​ដោយ​កម្មវិធី (<xliff:g id="ID_1">%s</xliff:g>)។ រក្សា​ការកំណត់​បច្ចុប្បន្ន​នៅ​ដដែល?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"មុខងារ​កុំរំខាន​ត្រូវបាន​បើក​ដោយ​ច្បាប់​ស្វ័យប្រវត្តិ ឬ​កម្មវិធី។ រក្សា​ការកំណត់​បច្ចុប្បន្ន​នៅ​ដដែល?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"រហូត​ដល់ <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"រក្សានៅ​ដដែល"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"ជំនួស"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index df7935a..fd3233e 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ಬ್ಯಾಟರಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ಪ್ರತಿಶತ."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"ಸಿಸ್ಟಂ ಸೆಟ್ಟಿಂಗ್‌ಗಳು."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"ಅಧಿಸೂಚನೆಗಳು."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನೋಡಿ"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"ಅಧಿಸೂಚನೆ ತೆರವುಗೊಳಿಸು."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ಸಕ್ರಿಯವಾಗಿದೆ."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ಸ್ವಾಧೀನ."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"ವೈ-ಫೈ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ಬ್ಲೂಟೂತ್‌ ಆಫ್ ಆಗಿದೆ"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆಫ್ ಆಗಿದೆ"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"(<xliff:g id="ID_1">%s</xliff:g>) ಸ್ವಯಂಚಾಲಿತ ನಿಯಮದ ಮೂಲಕ ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್ ಆಗಿದೆ. ಪ್ರಸ್ತುತ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಹಾಗೆಯೇ ಇರಿಸುವುದೇ?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"(<xliff:g id="ID_1">%s</xliff:g>) ಅಪ್ಲಿಕೇಶನ್‌ ಮೂಲಕ ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್ ಆಗಿದೆ. ಪ್ರಸ್ತುತ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಹಾಗೆಯೇ ಇರಿಸುವುದೇ?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"ಸ್ವಯಂಚಾಲಿತ ನಿಯಮ ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್‌ ಮೂಲಕ ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಆನ್ ಆಗಿದೆ. ಪ್ರಸ್ತುತ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಹಾಗೆಯೇ ಇರಿಸುವುದೇ?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> ತನಕ"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"ಇರಿಸಿ"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"ಬದಲಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 4286235..649dd1a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"시스템 설정"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"알림"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"모든 알림 보기"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"알림 지우기"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS가 사용 설정되었습니다."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS를 가져오는 중입니다."</string>
@@ -275,7 +274,7 @@
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"블루투스"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"블루투스(<xliff:g id="NUMBER">%d</xliff:g>개의 기기)"</string>
     <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"블루투스 사용 안함"</string>
-    <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"페어링된 기기가 없습니다."</string>
+    <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"페어링된 기기가 없습니다"</string>
     <string name="quick_settings_brightness_label" msgid="6968372297018755815">"밝기"</string>
     <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"자동 회전"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"화면 자동 회전"</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi가 사용 중지됨"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"블루투스가 사용 중지됨"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"알림 일시중지가 사용 중지됨"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"알림 일시중지가 자동 규칙(<xliff:g id="ID_1">%s</xliff:g>)에 의해 사용 설정되었습니다. 현재 설정을 유지하시겠습니까?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"알림 일시중지가 앱(<xliff:g id="ID_1">%s</xliff:g>)에 의해 사용 설정되었습니다. 현재 설정을 유지하시겠습니까?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"알림 일시중지가 자동 규칙 또는 앱에 의해 사용 설정되었습니다. 현재 설정을 유지하시겠습니까?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g>까지"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"유지"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"바꾸기"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 105e2aa..53b46f9 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Батарея кубатталууда, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> пайыз."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Система тууралоолору."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Эскертмелер."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Бардык эскертмелерди көрүү"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Эскертмелерди тазалоо."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS жандырылган."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS байланышууда."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өчүк"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth өчүк"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"Тынчымды алба\" режими өчүк"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Автоматтык эреже \"Тынчымды алба\" режимин күйгүздү (<xliff:g id="ID_1">%s</xliff:g>). Учурдагы жөндөөлөр сакталсынбы?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Колдонмо \"Тынчымды алба\" режимин күйгүздү (<xliff:g id="ID_1">%s</xliff:g>). Учурдагы жөндөөлөр сакталсынбы?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Автоматтык эреже же колдонмо \"Тынчымды алба\" режимин күйгүздү. Учурдагы жөндөөлөр сакталсынбы?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> чейин"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Ушундай калтыруу"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Алмаштыруу"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 87ef293..72fc0c6 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ກຳລັງສາກແບັດເຕີຣີ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ເປີເຊັນ."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"ການຕັ້ງຄ່າລະບົບ."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"ການແຈ້ງເຕືອນ."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"ເບິ່ງການແຈ້ງເຕືອນທັງໝົດ"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"ລຶບລ້າງການແຈ້ງເຕືອນ."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ເປີດແລ້ວ."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ກຳລັງຊອກຫາ GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ປິດຢູ່"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ປິດຢູ່"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"ຫ້າມລົບກວນ ປິດຢູ່"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"ໂໝດຫ້າມລົບກວນຖືກເປີດໃຊ້ໂດຍກົດອັດຕະໂນມັດ (<xliff:g id="ID_1">%s</xliff:g>). ເກັບການຕັ້ງຄ່າປັດຈຸບັນໄວ້ບໍ?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"ໂໝດຫ້າມລົບກວນຖືກເປີດໃຊ້ໂດຍແອັບໜຶ່ງ (<xliff:g id="ID_1">%s</xliff:g>). ເກັບການຕັ້ງຄ່າປັດຈຸບັນໄວ້ບໍ?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"ໂໝດຫ້າມລົບກວນຖືກເປີດໃຊ້ໂດຍກົດອັດຕະໂນມັດ ຫຼື ແອັບໃດໜຶ່ງ. ເກັບການຕັ້ງຄ່າປັດຈຸບັນໄວ້ບໍ?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"ຈົນຮອດ <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"ເກັບໄວ້"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"ແທນທີ່"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 4743c98..51d738c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -166,8 +166,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Įkraunamas akumuliatorius, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> proc."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Sistemos nustatymai"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Pranešimai."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Žr. visus pranešimus"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Išvalyti pranešimą."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS įgalintas."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Gaunama GPS."</string>
@@ -751,9 +750,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"„Wi-Fi“ išjungtas"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"„Bluetooth“ išjungtas"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Netrukdymo režimas išjungtas"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Netrukdymo režimas įjungtas naudojant automatinę taisyklę (<xliff:g id="ID_1">%s</xliff:g>). Palikti dabartinius nustatymus?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Netrukdymo režimą įjungė programa (<xliff:g id="ID_1">%s</xliff:g>). Palikti dabartinius nustatymus?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Netrukdymo režimas įjungtas naudojant automatinę taisyklę arba programą. Palikti dabartinius nustatymus?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Iki <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Palikti"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Pakeisti"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 3e68272..b32ac24 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -165,8 +165,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Notiek akumulatora uzlāde, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procenti."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Sistēmas iestatījumi"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Paziņojumi"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Skatīt visus paziņojumus"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Notīrīt paziņojumu"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ir iespējots."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS iegūšana."</string>
@@ -747,9 +746,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ir izslēgts"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ir izslēgts"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Režīms “Netraucēt” ir izslēgts"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Režīmu “Netraucēt” ieslēdza automātiska kārtula (<xliff:g id="ID_1">%s</xliff:g>). Vai paturēt pašreizējos iestatījumus?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Režīmu “Netraucēt” ieslēdza lietotne (<xliff:g id="ID_1">%s</xliff:g>). Vai paturēt pašreizējos iestatījumus?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Režīmu “Netraucēt” ieslēdza automātiska kārtula vai lietotne. Vai paturēt pašreizējos iestatījumus?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Līdz: <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Paturēt"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Aizstāt"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 931a14c..1ecb7cf 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Полнење на батеријата, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> проценти."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Поставки на систем."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Известувања"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Видете ги сите известувања"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Избриши известување."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS е овозможен."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Се добива GPS..."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi е исклучено"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth е исклучен"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"„Не вознемирувај“ е исклучено"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Автоматското правило ја вклучи „Не вознемирувај“ (<xliff:g id="ID_1">%s</xliff:g>). Да се задржат тековните поставки?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Апликацијата (<xliff:g id="ID_1">%s</xliff:g>) ја вклучи „Не вознемирувај“. Да се задржат тековните поставки?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Некое автоматско правило или апликација ја вклучи „Не вознемирувај“. Да се задржат тековните поставки?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Задржи"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Замени"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 3484cbd..6032246 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ബാറ്ററി ചാർജുചെയ്യുന്നു, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ശതമാനം."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"സിസ്‌റ്റം ക്രമീകരണങ്ങൾ."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"അറിയിപ്പുകൾ."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"എല്ലാ അറിയിപ്പുകളും കാണുക"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"വിവരം മായ്‌ക്കുക."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS പ്രവർത്തനക്ഷമമായി."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS നേടുന്നു."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"വൈഫൈ ഓഫാണ്"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth ഓഫാണ്"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\'ശല്യപ്പെടുത്തരുത്\' ഓഫാണ്"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"സ്വയമേവയുള്ള ഒരു നയം (<xliff:g id="ID_1">%s</xliff:g>) \'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കിയിരിക്കുന്നു. നിലവിലെ ക്രമീകരണം നിലനിർത്തണോ?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"ഒരു ആപ്പ് (<xliff:g id="ID_1">%s</xliff:g>) \'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കിയിരിക്കുന്നു. നിലവിലെ ക്രമീകരണം നിലനിർത്തണോ?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"സ്വയമേവയുള്ള ഒരു നയമോ ആപ്പോ \'ശല്യപ്പെടുത്തരുത്\' ഓണാക്കിയിരിക്കുന്നു. നിലവിലെ ക്രമീകരണം നിലനിർത്തണോ?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> വരെ"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"സൂക്ഷിക്കുക"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"മാറ്റിസ്ഥാപിക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 3947464..d33849d 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -162,8 +162,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Тэжээлийг цэнэглэж байна, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> хувь."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Системийн тохиргоо."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Мэдэгдэл."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Бүх мэдэгдлийг харах"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Мэдэгдлийг цэвэрлэх."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS идэвхтэй."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS хайж байна."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi унтраалттай байна"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth унтраалттай байна"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Бүү саад бол горим унтраалттай байна"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Бүү саад бол горимыг автомат дүрэм (<xliff:g id="ID_1">%s</xliff:g>) асаасан. Одоогийн тохиргоог хадгалах уу?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Апп-д (<xliff:g id="ID_1">%s</xliff:g>) Бүү саад бол горимыг асаасан. Одоогийн тохиргоог хадгалах уу?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Бүү саад бол горимыг автомат дүрэм эсвэл апп асаасан. Одоогийн тохиргоог хадгалах уу?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> хүртэл"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Хадгалах"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Солих"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 75b3b15..692753d2 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -743,9 +743,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"वाय-फाय बंद आहे"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ब्लूटुथ बंद आहे"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"व्यत्यय आणू नका बंद आहे"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"व्यत्यय आणू नका एक स्वयंचलित <xliff:g id="ID_1">%s</xliff:g> नियमाने चालू केले. वर्तमान सेटिंग्ज ठेवायच्‍या?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"व्यत्यय आणू नका (<xliff:g id="ID_1">%s</xliff:g>) अॅपने चालू केले. वर्तमान सेटिंग्ज ठेवायच्‍या?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"व्यत्यय आणू नका एका स्वयंचलित नियमाने किंवा अॅपने चालू केले. वर्तमान सेटिंग्ज ठेवायच्‍या?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> पर्यंत"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"ठेवा"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"पुनर्स्थित करा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index a911581..89070f7 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Bateri mengecas, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> peratus."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Tetapan sistem."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Pemberitahuan."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Lihat semua pemberitahuan"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Padamkan pemberitahuan."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS didayakan."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS sedang mendapatkan."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi dimatikan"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth dimatikan"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Jangan Ganggu dimatikan"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Jangan Ganggu telah dihidupkan oleh peraturan automatik (<xliff:g id="ID_1">%s</xliff:g>). Simpan tetapan semasa?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Jangan Ganggu dihidupkan oleh apl (<xliff:g id="ID_1">%s</xliff:g>). Simpan tetapan semasa?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Jangan Ganggu telah dihidupkan oleh peraturan automatik atau apl. Simpan tetapan semasa?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Hingga <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Simpan"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Gantikan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index b61d77ed..c7fb3d3 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ဘက်ထရီအားသွင်းနေသည်၊ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ရာခိုင်နှုန်း။"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"စနစ်အပြင်အဆင်များ"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"အကြောင်းကြားချက်များ။"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"သတိပေးချက်များအားလုံးကို ကြည့်ရန်"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"သတိပေးချက်အား ဖယ်ရှားခြင်း။"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPSသုံးစွဲနိုင်သည်"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ဖမ်းယူနေသည်။"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ကို ပိတ်ထားသည်"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ဘလူးတုသ်ကို ပိတ်ထားသည်"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"မနှောင့်ယှက်ရ\" ကို ပိတ်ထားသည်"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"အလိုလျောက်စည်းမျဉ်း (<xliff:g id="ID_1">%s</xliff:g>) က \"မနှောင့်ယှက်ရ\" ကို ဖွင့့့်််လိုက်ပါသည်။ လက်ရှိဆက်တင်များကို သိမ်းလိုပါသလား။"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"အက်ပ် (<xliff:g id="ID_1">%s</xliff:g>) က \"မနှောင့်ယှက်ရ\" ကို ဖွင့်လိုက်ပါသည်။ လက်ရှိဆက်တင်များကို သိမ်းလိုပါသလား။"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"အလိုလျောက်စည်းမျဉ်း သို့မဟုတ် အက်ပ်တစ်ခုက \"မနှောင့်ယှက်ရ\" ကို ဖွင့့့်််လိုက်ပါသည်။ လက်ရှိဆက်တင်များကို သိမ်းလိုပါသလား။"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> အထိ"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"သိမ်းထားရန်"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"အစားထိုးရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index f7f8e9d..5bf6d52 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Batteriet lades – <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> prosent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Systeminnstillinger."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Varsler."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Se alle varslene"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Fjern varsling"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS er aktivert."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Henting av GPS-signal."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er av"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth er av"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Ikke forstyrr er av"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Ikke forstyrr ble slått på av en automatisk regel (<xliff:g id="ID_1">%s</xliff:g>). Vil du beholde de nåværende innstillingene?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Ikke forstyrr ble slått på av en app (<xliff:g id="ID_1">%s</xliff:g>). Vil du beholde de nåværende innstillingene?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Ikke forstyrr ble slått på av en automatisk regel eller en app. Vil du beholde de nåværende innstillingene?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Til <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Behold"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Erstatt"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 80d4928..815293e2 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ब्याट्री चार्ज हुँदैछ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> प्रतिशत।"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"प्रणाली सेटिङहरू"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचनाहरू।"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"सबै सूचनाहरू हेर्नुहोस्"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"सूचना खाली गर्नुहोस्।"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम गरिएको"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त हुँदैछ।"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi‑Fi निष्क्रिय छ"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ब्लुटुथ निष्क्रिय छ"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"बाधा नपुर्‍याउनुहोस् नामक विकल्प निष्क्रिय छ"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"कुनै स्वचालित नियमले बाधा नपुर्‍याउनुहोस्‌ नामक विकल्पलाई सक्रिय गऱ्यो(<xliff:g id="ID_1">%s</xliff:g>)। हालका सेटिङहरू राख्ने हो?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"कुनै अनुप्रयोगले बाधा नपुर्‍याउनुहोस्‌ नामक विकल्पलाई सक्रिय गऱ्यो (<xliff:g id="ID_1">%s</xliff:g>)। हालका सेटिङहरू राख्ने हो?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"कुनै स्वचालित नियम वा अनुप्रयोगले बाधा नपुर्‍याउनुहोस्‌ नामक विकल्पलाई सक्रिय गऱ्यो। हालका सेटिङहरू राख्ने हो?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> सम्म"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"राख्नुहोस्"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"प्रतिस्थापन गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 1160bc3..1ad45bd 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Accu wordt opgeladen, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Systeeminstellingen."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Meldingen."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Alle meldingen bekijken"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Melding wissen"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"gps ingeschakeld."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Verbinding maken met gps."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wifi is uitgeschakeld"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth is uitgeschakeld"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\'Niet storen\' is uitgeschakeld"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\'Niet storen\' is ingeschakeld door een automatische regel (<xliff:g id="ID_1">%s</xliff:g>). Huidige instellingen behouden?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\'Niet storen\' is ingeschakeld door een app (<xliff:g id="ID_1">%s</xliff:g>). Huidige instellingen behouden?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\'Niet storen\' is ingeschakeld voor een automatische regel of app. Huidige instellingen behouden?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Tot <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Behouden"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Vervangen"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index fc99a06..183b22c 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"ਬੈਟਰੀ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> ਪ੍ਰਤੀਸ਼ਤ।"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"ਸਿਸਟਮ ਸੈਟਿੰਗਾਂ।"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"ਸੂਚਨਾਵਾਂ।"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖੋ"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"ਸੂਚਨਾ ਹਟਾਓ।"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ਸਮਰਥਿਤ।"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ਪ੍ਰਾਪਤ ਕਰ ਰਿਹਾ ਹੈ।"</string>
@@ -561,7 +560,7 @@
     </plurals>
     <string name="notification_all_categories" msgid="5407190218055113282">"ਸਭ ਸ਼੍ਰੇਣੀਆਂ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="3743278649182392015">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਰੋ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
     <string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ਬੰਦ ਹੈ"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ਬਲੂਟੁੱਥ ਬੰਦ ਹੈ"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\'ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਬੰਦ ਹੈ"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"ਸਵੈਚਲਿਤ ਨਿਯਮ ਦੁਆਰਾ \'ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਚਾਲੂ ਕੀਤਾ ਗਿਆ ਸੀ (<xliff:g id="ID_1">%s</xliff:g>)। ਵਰਤਮਾਨ ਸੈਟਿੰਗਾਂ ਰੱਖੀਏ?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"ਐਪ ਵੱਲੋਂ \'ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਚਾਲੂ ਕੀਤਾ ਗਿਆ ਸੀ (<xliff:g id="ID_1">%s</xliff:g>)। ਵਰਤਮਾਨ ਸੈਟਿੰਗਾਂ ਰੱਖੀਏ?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"ਸਵੈਚਲਿਤ ਨਿਯਮ ਜਾਂ ਐਪ ਵੱਲੋਂ \'ਮੈਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਚਾਲੂ ਕੀਤਾ ਗਿਆ। ਵਰਤਮਾਨ ਸੈਟਿੰਗਾਂ ਰੱਖੀਏ?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> ਤੱਕ"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"ਰੱਖੋ"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"ਬਦਲੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index a8a9a3f..8b9ee0b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -166,8 +166,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Ładuję baterię, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Ustawienia systemu."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Powiadomienia."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Zobacz wszystkie powiadomienia"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Usuń powiadomienie."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS włączony."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Pobieranie danych GPS."</string>
@@ -751,9 +750,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi jest wyłączone"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth jest wyłączony"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Tryb Nie przeszkadzać jest wyłączony"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Tryb Nie przeszkadzać został włączony przez regułę automatyczną (<xliff:g id="ID_1">%s</xliff:g>). Zachować obecne ustawienia?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Tryb Nie przeszkadzać został włączony przez aplikację (<xliff:g id="ID_1">%s</xliff:g>). Zachować obecne ustawienia?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Tryb Nie przeszkadzać został włączony przez regułę automatyczną lub aplikację. Zachować obecne ustawienia?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Do: <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Zachowaj"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Zastąp"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 6be8858..45e2fda 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Configurações do sistema"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificações."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas as notificações"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Limpar notificação."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ativado."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Aquisição de GPS."</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"O recurso Não perturbe está desativado"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"O recurso Não perturbe foi ativado por uma regra automática (<xliff:g id="ID_1">%s</xliff:g>). Manter as configurações atuais?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"O recurso Não perturbe foi ativado por um app (<xliff:g id="ID_1">%s</xliff:g>). Manter as configurações atuais?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"O recurso Não perturbe foi ativado por uma regra automática ou app. Manter as configurações atuais?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Até <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index e0bf506..741b3d6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"A bateria está a carregar, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> por cento."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Definições do sistema"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificações."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas as notificações"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Limpar notificações"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ativado."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Adquirir GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desativado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Não incomodar desativado"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Não incomodar foi ativado por uma regra automática (<xliff:g id="ID_1">%s</xliff:g>). Pretende manter as definições atuais?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Não incomodar foi ativado por uma aplicação (<xliff:g id="ID_1">%s</xliff:g>). Pretende manter as definições atuais?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Não incomodar foi ativado por uma regra automática ou uma aplicação. Pretende manter as definições atuais?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Até à(s) <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 6be8858..45e2fda 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Configurações do sistema"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificações."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Ver todas as notificações"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Limpar notificação."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ativado."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Aquisição de GPS."</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth desativado"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"O recurso Não perturbe está desativado"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"O recurso Não perturbe foi ativado por uma regra automática (<xliff:g id="ID_1">%s</xliff:g>). Manter as configurações atuais?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"O recurso Não perturbe foi ativado por um app (<xliff:g id="ID_1">%s</xliff:g>). Manter as configurações atuais?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"O recurso Não perturbe foi ativado por uma regra automática ou app. Manter as configurações atuais?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Até <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Manter"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Substituir"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 8ad2b102..e7dffee 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -167,8 +167,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Setări de sistem."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificări."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Vedeți toate notificările"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Ștergeți notificarea."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activat."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Se obține GPS."</string>
@@ -749,9 +748,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Conexiunea Wi-Fi este dezactivată"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Funcția Bluetooth este dezactivată"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Funcția Nu deranja este dezactivată"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Funcția Nu deranja a fost activată de o regulă automată (<xliff:g id="ID_1">%s</xliff:g>). Păstrați setările actuale?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Funcția Nu deranja a fost activată de o aplicație (<xliff:g id="ID_1">%s</xliff:g>). Păstrați setările actuale?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Funcția Nu deranja a fost activată de o regulă automată sau de o aplicație. Păstrați setările actuale?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Până la <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Păstrați"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Înlocuiți"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index cd8053d..75310a3 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -168,8 +168,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Настройки"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Уведомления"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Показать все уведомления"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Удалить уведомление"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"Система GPS включена."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Установление связи с GPS."</string>
@@ -753,9 +752,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Модуль Wi-Fi отключен"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Модуль Bluetooth отключен"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Режим \"Не беспокоить\" отключен"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Режим \"Не беспокоить\" был включен специальным правилом (<xliff:g id="ID_1">%s</xliff:g>). Сохранить текущие настройки?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Режим \"Не беспокоить\" был включен приложением (<xliff:g id="ID_1">%s</xliff:g>). Сохранить текущие настройки?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Режим \"Не беспокоить\" был включен специальным правилом или приложением. Сохранить текущие настройки?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Сохранить"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Заменить"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 52f49bf9..c71d5a2 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"බැටරිය ආරෝපණය කරමින්, සියයට <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"පද්ධති සැකසීම්."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"දැනුම්දීම්."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"සියලු දැනුම්දීම් බලන්න"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"දැනුම්දීම හිස් කරන්න."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS සබල කර ඇත."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ලබා ගනිමින්."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ක්‍රියා විරහිතයි"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"බ්ලූටූත් ක්‍රියා විරහිතයි"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"බාධා නොකරන්න ක්‍රියා විරහිතයි"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"බාධා නොකරන්න ස්වයංක්‍රීය රීතියකින් ක්‍රියාත්මක කෙරිණි (<xliff:g id="ID_1">%s</xliff:g>). වත්මන් සැකසීම් තබා ගන්නවා ද?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"බාධා නොකරන්න යෙදුමකින් ක්‍රියාත්මක කෙරිණි (<xliff:g id="ID_1">%s</xliff:g>). වත්මන් සැකසීම් තබා ගන්නවා ද?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"බාධා නොකරන්න ස්වයංක්‍රීය රීතියකින් හෝ යෙදුමකින් ක්‍රියාත්මක කෙරිණි. වත්මන් සැකසීම් තබා ගන්නවා ද?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> දක්වා"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"තබන්න"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"ප්‍රතිස්ථාපනය"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index de8ad54..59dce6f 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -168,8 +168,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Nastavenia systému."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Upozornenia."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Zobraziť všetky upozornenia"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Vymazať upozornenie."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS je povolené."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Prebieha zameriavanie GPS."</string>
@@ -753,9 +752,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Pripojenie Wi-Fi je vypnuté"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Rozhranie Bluetooth je vypnuté"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Nastavenie Nerušiť je vypnuté"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Nastavenie Nerušiť bolo zapnuté automatickým pravidlom (<xliff:g id="ID_1">%s</xliff:g>). Chcete ponechať aktuálne nastavenia?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Nastavenie Nerušiť bolo zapnuté aplikáciou (<xliff:g id="ID_1">%s</xliff:g>). Chcete ponechať aktuálne nastavenia?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Nastavenie Nerušiť bolo zapnuté automatickým pravidlom alebo aplikáciou. Chcete ponechať aktuálne nastavenia?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Ponechať"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Nahradiť"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 55699fa..53ae44e 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -168,8 +168,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Sistemske nastavitve."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Obvestila."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Prikaži vsa obvestila"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Izbriši obvestilo."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS omogočen."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Pridobivanje GPS."</string>
@@ -753,9 +752,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je izklopljen"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth je izklopljen"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Način »ne moti« je izklopljen"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Samodejno pravilo (<xliff:g id="ID_1">%s</xliff:g>) je vklopilo način »ne moti«. Želite obdržati trenutne nastavitve?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Aplikacija (<xliff:g id="ID_1">%s</xliff:g>) je vklopila način »ne moti«. Želite obdržati trenutne nastavitve?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Način »ne moti« je vklopljen zaradi samodejnega pravila ali aplikacije. Želite obdržati trenutne nastavitve?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Obdrži"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Zamenjaj"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index c47fc40..12573bc 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Bateria po ngarkohet, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> për qind."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Cilësimet e sistemit."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Njoftimet."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Shiko të gjitha njoftimet"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Pastro njoftimin."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS-ja është e aktivizuar."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Po siguron GPS-në."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi është joaktiv"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth-i është joaktiv"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Modaliteti \"Mos shqetëso\" është joaktiv"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Modaliteti \"Mos shqetëso\" është aktivizuar nga një rregull automatik (<xliff:g id="ID_1">%s</xliff:g>). Të mbahen cilësimet aktuale?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Modaliteti \"Mos shqetëso\" është aktivizuar nga një aplikacion (<xliff:g id="ID_1">%s</xliff:g>). Të mbahen cilësimet aktuale?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Modaliteti \"Mos shqetëso\" është aktivizuar nga një rregull automatik ose një aplikacion. Të mbahen cilësimet aktuale?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Deri në <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Mbaj"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Zëvendëso"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 2c75e255..664c3084 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -165,8 +165,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Батерија се пуни, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> процената."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Системска подешавања."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Обавештења."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Погледајте сва обавештења"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Обриши обавештење."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS је омогућен."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Учитавање GPS-а."</string>
@@ -747,9 +746,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi је искључен"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth је искључен"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Режим Не узнемиравај је искључен"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Аутоматско правило (<xliff:g id="ID_1">%s</xliff:g>) је укључило режим Не узнемиравај. Желите ли да задржите актуелна подешавања?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Апликација (<xliff:g id="ID_1">%s</xliff:g>) је укључила режим Не узнемиравај. Желите ли да задржите актуелна подешавања?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Аутоматско правило или апликација су укључили режим Не узнемиравај. Желите ли да задржите актуелна подешавања?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Задржи"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Замени"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 19fb2f5..65d0712 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Batteriet laddas, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> procent."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Systeminställningar."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Meddelanden."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Visa alla aviseringar"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Ta bort meddelandet."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktiverad."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Tar emot GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi är inaktiverat"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth är inaktiverat"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Stör ej är inaktiverat"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Stör ej aktiverades av en automatisk regel (<xliff:g id="ID_1">%s</xliff:g>). Vill du behålla de nuvarande inställningarna?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Stör ej aktiverades av en app (<xliff:g id="ID_1">%s</xliff:g>). Vill du behålla de nuvarande inställningarna?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Stör ej aktiverades av en automatisk regel eller app. Vill du behålla de nuvarande inställningarna?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Till <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Behåll"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Ersätt"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 5a69fb3..1935944 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Betri inachaji, asilimia <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Mipangilio ya mfumo."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Arifa."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Angalia arifa zote"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Futa arifa"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS imewashwa."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Kupata GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi imezimwa"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth imezimwa"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Kipengele cha Usinisumbue kimezimwa"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Kipengele cha Usinisumbue kimewashwa na sheria ya kiotomatiki (<xliff:g id="ID_1">%s</xliff:g>). Ungependa kutumia mipangilio ya sasa?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Kipengele cha Usinisumbue kimewashwa na programu (<xliff:g id="ID_1">%s</xliff:g>). Ungependa kutumia mipangilio ya sasa?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Kipengele cha Usinisumbue kimewashwa na sheria ya kiotomatiki au programu. Ungependa kutumia mipangilio ya sasa?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Hadi <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Usibadilishe"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Badilisha"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index e33e41e..36d247f 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"பேட்டரி சார்ஜ் செய்யப்படுகிறது, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> சதவீதம்."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"கணினி அமைப்பு."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"அறிவிப்புகள்."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"எல்லா அறிவிப்புகளையும் காட்டும்"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"அறிவிப்பை அழி."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS இயக்கப்பட்டது."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS பெறப்படுகிறது."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"வைஃபை முடக்கத்தில் உள்ளது"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"புளூடூத் முடக்கத்தில் உள்ளது"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"தொந்தரவு செய்ய வேண்டாம்\" முடக்கத்தில் உள்ளது"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\"தொந்தரவு செய்ய வேண்டாம்\" எனும் பயன்முறையை, தானியங்கு விதி (<xliff:g id="ID_1">%s</xliff:g>) இயக்கியுள்ளது. தற்போதைய அமைப்புகளையே வைத்திருக்கவா?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\"தொந்தரவு செய்ய வேண்டாம்\" எனும் பயன்முறையை, பயன்பாடு (<xliff:g id="ID_1">%s</xliff:g>) இயக்கியுள்ளது. தற்போதைய அமைப்புகளையே வைத்திருக்கவா?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\"தொந்தரவு செய்ய வேண்டாம்\" எனும் பயன்முறையை, தானியங்கு விதி அல்லது பயன்பாடு இயக்கியுள்ளது. தற்போதைய அமைப்புகளையே வைத்திருக்கவா?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> வரை"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"வைத்திரு"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"மாற்று"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 07447cf..766ee06 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"బ్యాటరీ ఛార్జ్ అవుతోంది, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> శాతం."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"సిస్టమ్ సెట్టింగ్‌లు."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"నోటిఫికేషన్‌లు."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"అన్ని నోటిఫికేషన్‌లను చూడండి"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"నోటిఫికేషన్‌ను క్లియర్ చేయండి."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ప్రారంభించబడింది."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPSని పొందడం."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ఆఫ్‌లో ఉంది"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"బ్లూటూత్ ఆఫ్‌లో ఉంది"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"అంతరాయం కలిగించవద్దు ఆఫ్‌లో ఉంది"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"స్వయంచాలక నియమం (<xliff:g id="ID_1">%s</xliff:g>) ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది. ప్రస్తుత సెట్టింగ్‌లను కొనసాగించాలా?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"అనువర్తనం (<xliff:g id="ID_1">%s</xliff:g>) ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది. ప్రస్తుత సెట్టింగ్‌లను కొనసాగించాలా?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"స్వయంచాలక నియమం లేదా అనువర్తనం ద్వారా అంతరాయం కలిగించవద్దు ఆన్ చేయబడింది. ప్రస్తుత సెట్టింగ్‌లను కొనసాగించాలా?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> వరకు"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"ఉంచు"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"భర్తీ చేయి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 09a734e..ef281dc 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"กำลังชาร์จแบตเตอรี่ <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> เปอร์เซ็นต์"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"การตั้งค่าระบบ"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"การแจ้งเตือน"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"ดูการแจ้งเตือนทั้งหมด"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"ล้างการแจ้งเตือน"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"เปิดใช้งาน GPS แล้ว"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"การดึงข้อมูล GPS"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ปิดอยู่"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"บลูทูธปิดอยู่"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\"ห้ามรบกวน\" ปิดอยู่"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"มีการเปิด \"ห้ามรบกวน\" โดยกฎอัตโนมัติ (<xliff:g id="ID_1">%s</xliff:g>) ให้คงการตั้งค่าปัจจุบันใช่ไหม"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"มีการเปิด \"ห้ามรบกวน\" โดยแอป (<xliff:g id="ID_1">%s</xliff:g>) ให้คงการตั้งค่าปัจจุบันใช่ไหม"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"มีการเปิด \"ห้ามรบกวน\" โดยกฎอัตโนมัติหรือแอป ให้คงการตั้งค่าปัจจุบันใช่ไหม"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"จนถึง <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"เก็บไว้"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"แทนที่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index c902863..9a0bad7 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Nagcha-charge ang baterya, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> (na) porsyento."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Mga setting ng system."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Mga Notification."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Tingnan ang lahat ng notification"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"I-clear ang notification."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"Pinapagana ang GPS."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Kumukuha ng GPS."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Naka-off ang Wi-Fi"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Naka-off ang Bluetooth"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Naka-off ang Huwag Istorbohin"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Na-on ang Huwag Istorbohin dahil sa isang awtomatikong panuntunan (<xliff:g id="ID_1">%s</xliff:g>). Panatilihin ang mga kasalukuyang setting?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Na-on ang Huwag Istorbohin dahil sa isang app (<xliff:g id="ID_1">%s</xliff:g>). Panatilihin ang mga kasalukuyang setting?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Na-on ang Huwag Istorbohin dahil sa isang awtomatikong panuntunan o app. Panatilihin ang mga kasalukuyang setting?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Hanggang <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Panatilihin"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Palitan"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index de8f193..af703c0 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Pil şarj oluyor, yüzde <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Sistem ayarları."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Bildirimler."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Tüm bildirimleri göster"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Bildirimi temizle."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS etkin."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS alınıyor."</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Kablosuz bağlantı kapalı"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth kapalı"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Rahatsız Etmeyin kapalı"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Rahatsız Etmeyin ayarı bir otomatik kural (<xliff:g id="ID_1">%s</xliff:g>) tarafından açıldı. Geçerli ayarlar korunsun mu?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Rahatsız Etmeyin ayarı bir uygulama (<xliff:g id="ID_1">%s</xliff:g>) tarafından açıldı. Geçerli ayarlar korunsun mu?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Rahatsız Etmeyin ayarı bir otomatik kural veya uygulama tarafından açıldı. Geçerli ayarlar korunsun mu?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Bitiş: <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Koru"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Değiştir"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index aa3f490..8edfa59 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -168,8 +168,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Налаштування системи."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Сповіщення."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Переглянути всі сповіщення"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Очистити сповіщення."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS увімкнено."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Встановлення зв’язку з GPS."</string>
@@ -753,9 +752,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi вимкнено"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth вимкнено"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Режим \"Не турбувати\" вимкнено"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Автоматичне правило ввімкнуло режим \"Не турбувати\" (<xliff:g id="ID_1">%s</xliff:g>). Залишити поточні налаштування?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Додаток увімкнув режим \"Не турбувати\" (<xliff:g id="ID_1">%s</xliff:g>). Залишити поточні налаштування?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Автоматичне правило або додаток увімкнули режим \"Не турбувати\". Залишити поточні налаштування?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"До <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Залишити"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Замінити"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 37b38cc..572f327 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"بیٹری چارجنگ، <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> فیصد۔"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"سسٹم کی ترتیبات۔"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"اطلاعات۔"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"تمام اطلاعات دیکھیں"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"اطلاع صاف کریں۔"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"‏GPS فعال ہے۔"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"‏GPS حاصل کرنا۔"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi آف ہے"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"بلوٹوتھ آف ہے"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"\'ڈسٹرب نہ کریں\' آف ہے"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"\'ڈسٹرب نہ کریں\' کسی خودکار اصول (<xliff:g id="ID_1">%s</xliff:g>) کے ذریعے آن ہو گیا تھا۔ موجودہ ترتیبات برقرار رکھیں؟"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"\'ڈسٹرب نہ کریں\' کسی ایپ (<xliff:g id="ID_1">%s</xliff:g>) کے ذریعے آن ہو گیا تھا۔ موجودہ ترتیبات برقرار رکھیں؟"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"\'ڈسٹرب نہ کریں\' کسی خودکار اصول یا ایپ کے ذریعے آن ہو گیا تھا۔ موجودہ ترتیبات برقرار رکھیں؟"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> تک"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"رکھیں"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"بدلیں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 4fb237f..2f0fa7f 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"Tizim sozlamalari."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Eslatmalar."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Barcha bildirishnomalarni ko‘rish"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Eslatmalarni tozalash."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS yoqildi."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS so‘rovi."</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi o‘chiq"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth o‘chiq"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Bezovta qilinmasin rejimi o‘chiq"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Bezovta qilinmasin rejimi avtomatik qoida (<xliff:g id="ID_1">%s</xliff:g>) tomonidan yoqilgan. Joriy sozlamalar saqlab qolinsimi?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Bezovta qilinmasin rejimi ilova (<xliff:g id="ID_1">%s</xliff:g>) tomonidan yoqilgan. Joriy sozlamalar saqlab qolinsimi?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Bezovta qilinmasin rejimi ilova yoki avtomatik qoida tomonidan yoqilgan. Joriy sozlamalar saqlab qolinsimi?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> gacha"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Saqlab qolish"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Almashtirish"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 942545f..e9bc587 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Đang sạc pin, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> phần trăm."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Cài đặt hệ thống"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Thông báo."</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Xem tất cả thông báo"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Xóa thông báo"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"Đã bật GPS."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Nhận GPS."</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi tắt"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth tắt"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Không làm phiền tắt"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Không làm phiền đã được một quy tắc tự động (<xliff:g id="ID_1">%s</xliff:g>) bật. Giữ cài đặt hiện tại?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Không làm phiền đã được một ứng dụng (<xliff:g id="ID_1">%s</xliff:g>) bật. Giữ cài đặt hiện tại?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Không làm phiền đã được một quy tắc tự động hoặc ứng dụng bật. Giữ cài đặt hiện tại?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Cho tới <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Giữ"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Thay thế"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 35958ff..a855481 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"正在充电,已完成百分之<xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>。"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"系统设置。"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"查看所有通知"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS已启用。"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"正在获取GPS信号。"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"WLAN 已关闭"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"蓝牙已关闭"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"“勿扰”模式已关闭"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"有个自动规则(<xliff:g id="ID_1">%s</xliff:g>)已开启“勿扰”模式。要保留当前的设置吗?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"有个应用(<xliff:g id="ID_1">%s</xliff:g>)已开启“勿扰”模式。要保留当前的设置吗?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"有个自动规则或应用已开启“勿扰”模式。要保留当前的设置吗?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"直到<xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"替换"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 5a7d676..52d7650 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -166,8 +166,7 @@
     <skip />
     <string name="accessibility_settings_button" msgid="799583911231893380">"系統設定"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"睇所有通知"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS 已啟用。"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"正在取得 GPS 訊號。"</string>
@@ -745,9 +744,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"藍牙已關閉"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"「請勿騷擾」已關閉"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"「<xliff:g id="ID_1">%s</xliff:g>」自動規則已開啟「請勿騷擾」。要保留目前的設定嗎?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"「<xliff:g id="ID_1">%s</xliff:g>」應用程式已開啟「請勿騷擾」。要保留目前的設定嗎?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"某個自動規則或應用程式已開啟「請勿騷擾」。要保留目前的設定嗎?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"直至<xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"取代"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 15b4c2c9..cd3eb55 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"充電中,已完成百分之 <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g>。"</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"系統設定"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"查看所有通知"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS 已啟用。"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"正在取得 GPS 訊號。"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"藍牙已關閉"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"零打擾模式已關閉"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"「<xliff:g id="ID_1">%s</xliff:g>」自動規則已將零打擾模式開啟。要保留目前的設定嗎?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"「<xliff:g id="ID_1">%s</xliff:g>」應用程式已將零打擾模式開啟。要保留目前的設定嗎?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"某個自動規則或應用程式已將零打擾模式開啟。要保留目前的設定嗎?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"直到 <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"保留"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"取代"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index dc235cc..4914477 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -164,8 +164,7 @@
     <string name="accessibility_battery_level_charging" msgid="1147587904439319646">"Ibhethri liyashaja, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> iphesenti."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Izilungiselelo zesistimu"</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Izaziso"</string>
-    <!-- no translation found for accessibility_overflow_action (5681882033274783311) -->
-    <skip />
+    <string name="accessibility_overflow_action" msgid="5681882033274783311">"Bona zonke izaziso"</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Sula isaziso"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"i-GPS inikwe amandla"</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"i-GPS iyafuna"</string>
@@ -743,9 +742,12 @@
     <string name="wifi_is_off" msgid="1838559392210456893">"I-Wi-Fi ivaliwe"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"I-Bluetooth ivaliwe"</string>
     <string name="dnd_is_off" msgid="6167780215212497572">"Ungaphazamisi kuvaliwe"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="1570808639425342">"Ungaphazamisi kuvulwe umthetho wokuzenzakalelayo (<xliff:g id="ID_1">%s</xliff:g>). Gcina izilungiselelo zamanje?"</string>
-    <string name="qs_dnd_prompt_app" msgid="1131614608680529190">"Ungaphazamisi kuvulwe uhlelo lokusebenza (<xliff:g id="ID_1">%s</xliff:g>). Gcina izilungiselelo zamanje?"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="3685659782196144067">"Ungaphazamisi kuvulwe umthetho ozenzakalelayo noma uhlelo lokusebenza. Gcina izilungiselelo zamanje?"</string>
+    <!-- no translation found for qs_dnd_prompt_auto_rule (862559028345233052) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_app (7978037419334156034) -->
+    <skip />
+    <!-- no translation found for qs_dnd_prompt_auto_rule_app (2599343675391111951) -->
+    <skip />
     <string name="qs_dnd_until" msgid="3469471136280079874">"Kuze kube-<xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Gcina"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Buyisela"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index f461bb3..83a0b7b 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -96,10 +96,6 @@
     <!-- The "inside" of a notification, reached via longpress -->
     <color name="notification_guts_bg_color">#eeeeee</color>
 
-    <!-- Colors of the snooze menu reached via snooze icon behind a notification -->
-    <color name="snooze_snackbar_bg">#FF4A4A4A</color>
-	<color name="snooze_snackbar_text">#FFA6BAFF</color>
-
     <color name="assist_orb_color">#ffffff</color>
 
     <color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index 3817da0..6e56d4a 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -21,4 +21,4 @@
     <color name="recents_tv_card_title_text_color">#CCEEEEEE</color>
     <color name="recents_tv_dismiss_text_color">#7FEEEEEE</color>
     <color name="recents_tv_text_shadow_color">#7F000000</color>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 263a4698..4b15f72 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -338,4 +338,7 @@
     <!-- Whether to show activity indicators in the status bar -->
     <bool name="config_showActivity">false</bool>
 
+    <!-- Whether or not the button to clear all notifications will be shown. -->
+    <bool name="config_enableNotificationsClearAll">true</bool>
+
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6837340..4edadea 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -119,7 +119,7 @@
     <dimen name="notification_menu_icon_padding">20dp</dimen>
 
     <!-- The minimum height for the snackbar shown after the snooze option has been chosen. -->
-    <dimen name="snooze_snackbar_min_height">48dp</dimen>
+    <dimen name="snooze_snackbar_min_height">56dp</dimen>
 
     <!-- The text size of options in the snooze menu. -->
     <dimen name="snooze_option_text_size">14sp</dimen>
@@ -263,6 +263,9 @@
     <dimen name="qs_detail_item_icon_size">24dp</dimen>
     <dimen name="qs_detail_item_icon_marginStart">0dp</dimen>
     <dimen name="qs_detail_item_icon_marginEnd">20dp</dimen>
+    <dimen name="qs_footer_padding_start">16dp</dimen>
+    <dimen name="qs_footer_padding_end">24dp</dimen>
+    <dimen name="qs_footer_icon_size">16dp</dimen>
 
     <!-- Desired qs icon overlay size. -->
     <dimen name="qs_detail_icon_overlay_size">24dp</dimen>
@@ -738,7 +741,7 @@
     <dimen name="pip_dismiss_gradient_height">196dp</dimen>
 
     <!-- The bottom margin of the PIP drag to dismiss info text shown when moving a PIP. -->
-    <dimen name="pip_dismiss_text_bottom_margin">36dp</dimen>
+    <dimen name="pip_dismiss_text_bottom_margin">24dp</dimen>
 
     <!-- The shortest-edge size of the expanded PiP. -->
     <dimen name="pip_expanded_shortest_edge_size">160dp</dimen>
@@ -760,4 +763,6 @@
     <dimen name="default_gear_space">18dp</dimen>
     <dimen name="cell_overlay_padding">18dp</dimen>
 
+    <dimen name="signal_icon_size">17dp</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/integers_tv.xml b/packages/SystemUI/res/values/integers_tv.xml
deleted file mode 100644
index 09547da..0000000
--- a/packages/SystemUI/res/values/integers_tv.xml
+++ /dev/null
@@ -1,21 +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>
-    <!-- Delay of the onboarding animation start after it launches -->
-    <integer name="tv_pip_onboarding_anim_start_delay">1000</integer>
-    <!-- Duration of the onboarding animation duration -->
-    <integer name="tv_pip_onboarding_anim_duration">1000</integer>
-</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index eeb28c8..5f88773 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -376,13 +376,13 @@
     <string name="accessibility_no_sim">No SIM.</string>
 
     <!-- Content description of the cell data. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_cell_data">Cellular Data</string>
+    <string name="accessibility_cell_data">Mobile Data</string>
 
     <!-- Content description of the cell data being enabled. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_cell_data_on">Cellular Data On</string>
+    <string name="accessibility_cell_data_on">Mobile Data On</string>
 
     <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
-    <string name="accessibility_cell_data_off">Cellular Data Off</string>
+    <string name="accessibility_cell_data_off">Mobile Data Off</string>
 
     <!-- Content description of the bluetooth tethering icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_bluetooth_tether">Bluetooth tethering.</string>
@@ -574,11 +574,11 @@
     <!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
     <string name="data_usage_disabled_dialog_4g_title">4G data is paused</string>
     <!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
-    <string name="data_usage_disabled_dialog_mobile_title">Cellular data is paused</string>
+    <string name="data_usage_disabled_dialog_mobile_title">Mobile data is paused</string>
     <!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
     <string name="data_usage_disabled_dialog_title">Data is paused</string>
     <!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
-    <string name="data_usage_disabled_dialog">The data limit you set has been reached. You are no longer using cellular data.\n\nIf you resume, charges may apply for data usage.</string>
+    <string name="data_usage_disabled_dialog">The data limit you set has been reached. You are no longer using mobile data.\n\nIf you resume, charges may apply for data usage.</string>
     <!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
     <string name="data_usage_disabled_dialog_enable">Resume</string>
 
@@ -749,7 +749,7 @@
     <!-- QuickSettings: Flashlight [CHAR LIMIT=NONE] -->
     <string name="quick_settings_flashlight_label">Flashlight</string>
     <!-- QuickSettings: Cellular detail panel title [CHAR LIMIT=NONE] -->
-    <string name="quick_settings_cellular_detail_title">Cellular data</string>
+    <string name="quick_settings_cellular_detail_title">Mobile data</string>
     <!-- QuickSettings: Cellular detail panel, data usage title [CHAR LIMIT=NONE] -->
     <string name="quick_settings_cellular_detail_data_usage">Data usage</string>
     <!-- QuickSettings: Cellular detail panel, remaining data title [CHAR LIMIT=NONE] -->
@@ -1466,6 +1466,15 @@
         <item quantity="other"><xliff:g id="channel_name_1">%1$s</xliff:g>, <xliff:g id="channel_name_2">%2$s</xliff:g>, and <xliff:g id="number">%3$d</xliff:g> others</item>
     </plurals>
 
+    <!-- Notification: Control panel: Accessibility description for expanded inline controls view, used
+        to control settings about notifications related to the current notification.  -->
+    <string name="notification_channel_controls_opened_accessibility">Notification controls for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> opened</string>
+    <!-- Notification: Control panel: Accessibility description for announcing the closing of the
+        inline controls view.  -->
+    <string name="notification_channel_controls_closed_accessibility">Notification controls for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> closed</string>
+    <!-- Notification: Control panel: Accessibility description for switch that is used to enable
+        or disable notifications from this channel -->
+    <string name="notification_channel_switch_accessibility">Allow notifications from this channel</string>
     <!-- Notification: Control panel: Label for button that launches notification settings. Used
         when this app has defined more than a single channel for notifications. -->
     <string name="notification_all_categories">All Categories</string>
@@ -1493,8 +1502,6 @@
     <string name="snooze_option_30_min">30 minutes</string>
     <!-- Notification: Menu row: Snooze options: 1 hour option. [CHAR LIMIT=50]-->
     <string name="snooze_option_1_hour">1 hour</string>
-    <!-- Notification: Menu row: Snooze options: cancel snoozing option. [CHAR LIMIT=50] -->
-    <string name="snooze_option_dont_snooze">Cancel</string>
     <!-- Notification: Menu row: Snooze undo button label. [CHAR LIMIT=50]-->
     <string name="snooze_undo">UNDO</string>
 
@@ -1888,6 +1895,18 @@
     <!-- PiP minimize description. [CHAR LIMIT=NONE] -->
     <string name="pip_minimize_description" translatable="false">Drag or fling the PIP to the edges of the screen to minimize it.</string>
 
+    <!-- Button to play the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
+    <string name="pip_play">Play</string>
+
+    <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
+    <string name="pip_pause">Pause</string>
+
+    <!-- Button to skip to the next media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
+    <string name="pip_skip_to_next">Skip to next</string>
+
+    <!-- Button to skip to the prev media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
+    <string name="pip_skip_to_prev">Skip to previous</string>
+
     <!-- Tuner string -->
     <string name="change_theme_reboot" translatable="false">Changing the theme requires a restart.</string>
     <!-- Tuner string -->
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index fb9e1f2..e578068 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -23,18 +23,4 @@
     <string name="pip_close">Close PIP</string>
     <!-- Button to move picture-in-picture (PIP) screen to the fullscreen in PIP menu [CHAR LIMIT=30] -->
     <string name="pip_fullscreen">Full screen</string>
-    <!-- Button to play the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
-    <string name="pip_play">Play</string>
-    <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
-    <string name="pip_pause">Pause</string>
-    <!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=52] -->
-    <string name="pip_hold_home">Hold <b>HOME</b> to control PIP</string>
-    <!-- Picture-in-Picture (PIP) onboarding screen -->
-    <eat-comment />
-    <!-- Title for picture-in-picture (PIP) onboarding screen to indicate that an user is in PIP mode. [CHAR LIMIT=NONE] -->
-    <string name="pip_onboarding_title">Picture-in-picture</string>
-    <!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP. [CHAR LIMIT=NONE] -->
-    <string name="pip_onboarding_description">This keeps your video in view until you play another one. Press and hold <b>HOME</b> to control it.</string>
-    <!-- Button to close picture-in-picture (PIP) onboarding screen. -->
-    <string name="pip_onboarding_button">Got it</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index c9479b8..dbdbd1e 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -299,13 +299,13 @@
 
     <style name="TextAppearance.Volume">
         <item name="android:textStyle">normal</item>
-        <item name="android:textColor">#ffffffff</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:fontFamily">sans-serif</item>
     </style>
 
     <style name="TextAppearance.Volume.Header">
         <item name="android:textSize">12sp</item>
-        <item name="android:textColor">@color/volume_slider_inactive</item>
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
 
     <style name="TextAppearance.Volume.ZenSummary">
@@ -316,7 +316,7 @@
     <style name="TextAppearance.Volume.ZenDetail">
         <item name="android:textSize">14sp</item>
         <item name="android:fontFamily">sans-serif</item>
-        <item name="android:textColor">@*android:color/quaternary_device_default_settings</item>
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
 
     <style name="VolumeButtons" parent="@android:style/Widget.Material.Button.Borderless">
@@ -386,20 +386,6 @@
         <item name="android:paddingEnd">8dp</item>
     </style>
 
-    <style name="TextAppearance.SnoozeSnackBar">
-        <item name="android:textSize">14sp</item>
-        <item name="android:fontFamily">sans-serif</item>
-        <item name="android:textColor">@android:color/white</item>
-    </style>
-
-    <style name="TextAppearance.SnoozeSnackBar.Button">
-        <item name="android:textSize">14sp</item>
-        <item name="android:textAllCaps">true</item>
-        <item name="android:fontFamily">sans-serif-medium</item>
-        <item name="android:gravity">center</item>
-        <item name="android:textColor">@color/snooze_snackbar_text</item>
-    </style>
-
     <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
         <item name="android:colorBackground">?android:attr/colorSecondary</item>
     </style>
diff --git a/packages/SystemUI/res/values/styles_tv.xml b/packages/SystemUI/res/values/styles_tv.xml
index 3f0caab..0c4fd23 100644
--- a/packages/SystemUI/res/values/styles_tv.xml
+++ b/packages/SystemUI/res/values/styles_tv.xml
@@ -21,5 +21,6 @@
     <style name="PipTheme" parent="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:backgroundDimEnabled">false</item>
+        <item name="android:windowDisablePreview">true</item>
      </style>
 </resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java b/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
index 0a89d9b..e98ef06 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
@@ -37,8 +37,8 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mCarrierText = (CarrierText) findViewById(R.id.carrier_text);
-        mEmergencyButton = (EmergencyButton) findViewById(R.id.emergency_call_button);
+        mCarrierText = findViewById(R.id.carrier_text);
+        mEmergencyButton = findViewById(R.id.emergency_call_button);
 
         // The emergency button overlaps the carrier text, only noticeable when highlighted.
         // So temporarily hide the carrier text while the emergency button is pressed.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 5aa673b..abc3b94 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -98,7 +98,7 @@
         mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
 
-        EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
+        EmergencyButton button = findViewById(R.id.emergency_call_button);
         if (button != null) {
             button.setCallback(this);
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
new file mode 100644
index 0000000..3fd950b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.telephony.euicc.EuiccManager;
+
+import java.lang.ref.WeakReference;
+
+/***
+ * This button is used by the device with embedded SIM card to disable current carrier to unlock
+ * the device with no cellular service.
+ */
+class KeyguardEsimArea extends Button implements View.OnClickListener {
+    private EuiccManager mEuiccManager;
+
+    public KeyguardEsimArea(Context context) {
+        this(context, null);
+    }
+
+    public KeyguardEsimArea(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public KeyguardEsimArea(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, android.R.style.Widget_Material_Button_Borderless);
+    }
+
+    public KeyguardEsimArea(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mEuiccManager = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE);
+        if (mEuiccManager.isEnabled()) {
+            setVisibility(View.VISIBLE);
+        }
+        setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(View v) {
+        // STOPSHIP(b/37353596): use EuiccManager API to disable current carrier.
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index dd5544d..27a3f7d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -143,7 +143,7 @@
     @Override
     protected void onFinishInflate() {
         mSecurityContainer =
-                (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
+                findViewById(R.id.keyguard_security_container);
         mLockPatternUtils = new LockPatternUtils(mContext);
         mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
         mSecurityContainer.setSecurityCallback(this);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 590d8d5..c1cff9e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -79,11 +79,11 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mContainer = (ViewGroup) findViewById(R.id.container);
-        mRow0 = (ViewGroup) findViewById(R.id.row0);
-        mRow1 = (ViewGroup) findViewById(R.id.row1);
-        mRow2 = (ViewGroup) findViewById(R.id.row2);
-        mRow3 = (ViewGroup) findViewById(R.id.row3);
+        mContainer = findViewById(R.id.container);
+        mRow0 = findViewById(R.id.row0);
+        mRow1 = findViewById(R.id.row1);
+        mRow2 = findViewById(R.id.row2);
+        mRow3 = findViewById(R.id.row3);
         mDivider = findViewById(R.id.divider);
         mViews = new View[][]{
                 new View[]{
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index d49ff97..b6184a8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -174,7 +174,7 @@
         mImm = (InputMethodManager) getContext().getSystemService(
                 Context.INPUT_METHOD_SERVICE);
 
-        mPasswordEntry = (TextView) findViewById(getPasswordTextViewId());
+        mPasswordEntry = findViewById(getPasswordTextViewId());
         mPasswordEntryDisabler = new TextViewInputDisabler(mPasswordEntry);
         mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
         mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index c2b57ff..3c9a6b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -140,7 +140,7 @@
         mLockPatternUtils = mLockPatternUtils == null
                 ? new LockPatternUtils(mContext) : mLockPatternUtils;
 
-        mLockPatternView = (LockPatternView) findViewById(R.id.lockPatternView);
+        mLockPatternView = findViewById(R.id.lockPatternView);
         mLockPatternView.setSaveEnabled(false);
         mLockPatternView.setOnPatternListener(new UnlockPatternListener());
 
@@ -150,9 +150,9 @@
         mSecurityMessageDisplay =
                 (KeyguardMessageArea) KeyguardMessageArea.findSecurityMessageDisplay(this);
         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
-        mContainer = (ViewGroup) findViewById(R.id.container);
+        mContainer = findViewById(R.id.container);
 
-        EmergencyButton button = (EmergencyButton) findViewById(R.id.emergency_call_button);
+        EmergencyButton button = findViewById(R.id.emergency_call_button);
         if (button != null) {
             button.setCallback(this);
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 108b466..c04ae68 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -171,7 +171,7 @@
 
     @Override
     protected void onFinishInflate() {
-        mPasswordEntry = (PasswordTextView) findViewById(getPasswordTextViewId());
+        mPasswordEntry = findViewById(getPasswordTextViewId());
         mPasswordEntry.setOnKeyListener(this);
 
         // Set selected property on so the view can send accessibility events.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8cdb906..616e5b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -15,6 +15,7 @@
  */
 package com.android.keyguard;
 
+import android.R.style;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.admin.DevicePolicyManager;
@@ -23,6 +24,7 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
+import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
@@ -73,7 +75,8 @@
     }
 
     public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
+        super(new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault), attrs,
+                defStyle);
         mSecurityModel = new KeyguardSecurityModel(context);
         mLockPatternUtils = new LockPatternUtils(context);
         mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
@@ -160,7 +163,7 @@
     }
 
     protected void onFinishInflate() {
-        mSecurityViewFlipper = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
+        mSecurityViewFlipper = findViewById(R.id.view_flipper);
         mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 839d3ce..d5be186 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -35,6 +35,7 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.WindowManager;
@@ -80,7 +81,7 @@
         if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
             int count = TelephonyManager.getDefault().getSimCount();
             Resources rez = getResources();
-            final String msg;
+            String msg;
             int color = Color.WHITE;
             if (count < 2) {
                 msg = rez.getString(R.string.kg_sim_pin_instructions);
@@ -92,6 +93,11 @@
                     color = info.getIconTint();
                 }
             }
+            EuiccManager euiccManager =
+                    (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE);
+            if (euiccManager.isEnabled()) {
+                msg = msg + " " + rez.getString(R.string.kg_sim_lock_instructions_esim);
+            }
             mSecurityMessageDisplay.setMessage(msg);
             mSimImageView.setImageTintList(ColorStateList.valueOf(color));
         }
@@ -144,7 +150,7 @@
         if (mEcaView instanceof EmergencyCarrierArea) {
             ((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
         }
-        mSimImageView = (ImageView) findViewById(R.id.keyguard_sim);
+        mSimImageView = findViewById(R.id.keyguard_sim);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 3871448..61a1488 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -29,6 +29,7 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.euicc.EuiccManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.WindowManager;
@@ -121,7 +122,7 @@
             if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
                 int count = TelephonyManager.getDefault().getSimCount();
                 Resources rez = getResources();
-                final String msg;
+                String msg;
                 int color = Color.WHITE;
                 if (count < 2) {
                     msg = rez.getString(R.string.kg_puk_enter_puk_hint);
@@ -133,6 +134,11 @@
                         color = info.getIconTint();
                     }
                 }
+                EuiccManager euiccManager =
+                        (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE);
+                if (euiccManager.isEnabled()) {
+                    msg = msg + " " + rez.getString(R.string.kg_sim_lock_instructions_esim);
+                }
                 mSecurityMessageDisplay.setMessage(msg);
                 mSimImageView.setImageTintList(ColorStateList.valueOf(color));
             }
@@ -187,7 +193,7 @@
         if (mEcaView instanceof EmergencyCarrierArea) {
             ((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
         }
-        mSimImageView = (ImageView) findViewById(R.id.keyguard_sim);
+        mSimImageView = findViewById(R.id.keyguard_sim);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index b2b0ee4..162faa5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -115,14 +115,14 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mClockContainer = (ViewGroup) findViewById(R.id.keyguard_clock_container);
-        mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
-        mDateView = (TextClock) findViewById(R.id.date_view);
-        mClockView = (TextClock) findViewById(R.id.clock_view);
+        mClockContainer = findViewById(R.id.keyguard_clock_container);
+        mAlarmStatusView = findViewById(R.id.alarm_status);
+        mDateView = findViewById(R.id.date_view);
+        mClockView = findViewById(R.id.clock_view);
         mDateView.setShowCurrentUserTime(true);
         mClockView.setShowCurrentUserTime(true);
-        mOwnerInfo = (TextView) findViewById(R.id.owner_info);
-        mBatteryDoze = (ChargingView) findViewById(R.id.battery_doze);
+        mOwnerInfo = findViewById(R.id.owner_info);
+        mBatteryDoze = findViewById(R.id.battery_doze);
         mVisibleInDoze = new View[]{mBatteryDoze, mClockView};
 
         boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f8d1bfb..7a6ac57 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -165,11 +165,6 @@
     private int mPhoneState;
     private boolean mKeyguardIsVisible;
 
-    /**
-     * If true, fingerprint was already authenticated and we don't need to start listening again
-     * until the Keyguard has been dismissed.
-     */
-    private boolean mFingerprintAlreadyAuthenticated;
     private boolean mGoingToSleep;
     private boolean mBouncer;
     private boolean mBootCompleted;
@@ -409,11 +404,8 @@
     private void onFingerprintAuthenticated(int userId) {
         Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
         mUserFingerprintAuthenticated.put(userId, true);
-
-        // If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a
-        // wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is
-        // fully gone.
-        mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed();
+        // Don't send cancel if authentication succeeds
+        mFingerprintCancelSignal = null;
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -922,7 +914,6 @@
             }
         }
         mGoingToSleep = true;
-        mFingerprintAlreadyAuthenticated = false;
         updateFingerprintListeningState();
     }
 
@@ -1092,8 +1083,7 @@
 
     private boolean shouldListenForFingerprint() {
         return (mKeyguardIsVisible || !mDeviceInteractive || mBouncer || mGoingToSleep)
-                && !mSwitchingUser && !mFingerprintAlreadyAuthenticated
-                && !isFingerprintDisabled(getCurrentUser());
+                && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser());
     }
 
     private void startListeningForFingerprint() {
@@ -1416,9 +1406,6 @@
                 cb.onKeyguardVisibilityChangedRaw(showing);
             }
         }
-        if (!showing) {
-            mFingerprintAlreadyAuthenticated = false;
-        }
         updateFingerprintListeningState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index d57e88c..911ef24 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -149,7 +149,7 @@
     @Override
     public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
         mDrawable.setBatteryLevel(level);
-        mDrawable.setPluggedIn(pluggedIn);
+        mDrawable.setCharging(pluggedIn);
         mLevel = level;
         updatePercentText();
         setContentDescription(
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 0b0ea720..7fed3e8 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -31,6 +31,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -130,6 +131,11 @@
         }
     };
 
+    @VisibleForTesting
+    ObjectAnimator getScaleAnimation() {
+        return mScaleAnimation;
+    }
+
     private class ViewScaler {
         ExpandableView mView;
 
@@ -176,7 +182,8 @@
         mFlingAnimationUtils = new FlingAnimationUtils(context, EXPAND_DURATION);
     }
 
-    private void updateExpansion() {
+    @VisibleForTesting
+    void updateExpansion() {
         if (DEBUG_SCALE) Log.v(TAG, "updateExpansion()");
         // are we scaling or dragging?
         float span = mSGD.getCurrentSpan() - mInitialTouchSpan;
@@ -500,7 +507,8 @@
     /**
      * @return True if the view is expandable, false otherwise.
      */
-    private boolean startExpanding(ExpandableView v, int expandType) {
+    @VisibleForTesting
+    boolean startExpanding(ExpandableView v, int expandType) {
         if (!(v instanceof ExpandableNotificationRow)) {
             return false;
         }
@@ -535,7 +543,8 @@
      *                   state
      * @param velocity the velocity this was expanded/ collapsed with
      */
-    private void finishExpanding(boolean forceAbort, float velocity) {
+    @VisibleForTesting
+    void finishExpanding(boolean forceAbort, float velocity) {
         if (!mExpanding) return;
 
         if (DEBUG) Log.d(TAG, "scale in finishing on view: " + mResizedView);
@@ -571,7 +580,9 @@
                 public void onAnimationEnd(Animator animation) {
                     if (!mCancelled) {
                         mCallback.setUserExpandedChild(scaledView, expand);
-                        mScaler.setView(null);
+                        if (!mExpanding) {
+                            mScaler.setView(null);
+                        }
                     } else {
                         mCallback.setExpansionCancelled(scaledView);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index e1aaaa3..1e9cbdc 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -41,7 +41,6 @@
         Key.DND_FAVORITE_BUCKET_INDEX,
         Key.DND_NONE_SELECTED,
         Key.DND_FAVORITE_ZEN,
-        Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN,
         Key.QS_HOTSPOT_ADDED,
         Key.QS_DATA_SAVER_ADDED,
         Key.QS_DATA_SAVER_DIALOG_SHOWN,
@@ -62,7 +61,6 @@
         String DND_FAVORITE_BUCKET_INDEX = "DndCountdownMinuteIndex";
         String DND_NONE_SELECTED = "DndNoneSelected";
         String DND_FAVORITE_ZEN = "DndFavoriteZen";
-        String TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN = "TvPictureInPictureOnboardingShown";
         String QS_HOTSPOT_ADDED = "QsHotspotAdded";
         String QS_DATA_SAVER_ADDED = "QsDataSaverAdded";
         String QS_DATA_SAVER_DIALOG_SHOWN = "QsDataSaverDialogShown";
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 5a04108d..8c4159a 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -462,11 +462,20 @@
         int duration = SNAP_ANIM_LEN;
         anim.setDuration(duration);
         anim.addListener(new AnimatorListenerAdapter() {
+            boolean wasCancelled = false;
+
+            @Override
+            public void onAnimationCancel(Animator animator) {
+                wasCancelled = true;
+            }
+
             @Override
             public void onAnimationEnd(Animator animator) {
                 mSnappingChild = false;
-                updateSwipeProgressFromOffset(animView, canBeDismissed);
-                mCallback.onChildSnappedBack(animView, targetLeft);
+                if (!wasCancelled) {
+                    updateSwipeProgressFromOffset(animView, canBeDismissed);
+                    mCallback.onChildSnappedBack(animView, targetLeft);
+                }
             }
         });
         prepareSnapBackAnimation(animView, anim);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
index abcf27d..1d032e8 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
@@ -137,7 +137,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mLogo = (ImageView) findViewById(R.id.search_logo);
+        mLogo = findViewById(R.id.search_logo);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index f3fb1ef..ec56e15 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -33,6 +33,8 @@
     boolean isPulsingBlocked();
 
     void startPendingIntentDismissingKeyguard(PendingIntent intent);
+    void abortPulsing();
+    void extendPulse();
 
     interface Callback {
         default void onNotificationHeadsUp() {}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 870d4d1..90e1c07 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -145,6 +145,11 @@
         log("screenOff why=" + why);
     }
 
+    public static void traceMissedTick(String delay) {
+        if (!ENABLED) return;
+        log("missedTick by=" + delay);
+    }
+
     public static void traceKeyguard(boolean showing) {
         if (!ENABLED) return;
         log("keyguard " + showing);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index f498410..3468ed4 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -58,12 +58,15 @@
         /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
         DOZE_PULSE_DONE,
         /** Doze is done. DozeService is finished. */
-        FINISH;
+        FINISH,
+        /** AOD, but the display is temporarily off. */
+        DOZE_AOD_PAUSED;
 
         boolean canPulse() {
             switch (this) {
                 case DOZE:
                 case DOZE_AOD:
+                case DOZE_AOD_PAUSED:
                     return true;
                 default:
                     return false;
@@ -85,6 +88,7 @@
                 case UNINITIALIZED:
                 case INITIALIZED:
                 case DOZE:
+                case DOZE_AOD_PAUSED:
                     return Display.STATE_OFF;
                 case DOZE_PULSING:
                     return Display.STATE_DOZE;
@@ -242,6 +246,11 @@
         if (mState == State.FINISH) {
             return State.FINISH;
         }
+        if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD || mState == State.DOZE)
+                && requestedState == State.DOZE_PULSE_DONE) {
+            Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
+            return mState;
+        }
         if (requestedState == State.DOZE_REQUEST_PULSE && !mState.canPulse()) {
             Log.i(TAG, "Dropping pulse request because current state can't pulse: " + mState);
             return mState;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 2ac0657..73f5222 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -22,6 +22,8 @@
 import android.content.Context;
 import android.database.ContentObserver;
 import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.hardware.TriggerEvent;
 import android.hardware.TriggerEventListener;
@@ -40,6 +42,7 @@
 
 import java.io.PrintWriter;
 import java.util.List;
+import java.util.function.Consumer;
 
 public class DozeSensors {
 
@@ -55,18 +58,22 @@
     private final DozeParameters mDozeParameters;
     private final AmbientDisplayConfiguration mConfig;
     private final WakeLock mWakeLock;
+    private final Consumer<Boolean> mProxCallback;
     private final Callback mCallback;
 
     private final Handler mHandler = new Handler();
+    private final ProxSensor mProxSensor;
 
 
     public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters,
-            AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback) {
+            AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback,
+            Consumer<Boolean> proxCallback) {
         mContext = context;
         mSensorManager = sensorManager;
         mDozeParameters = dozeParameters;
         mConfig = config;
         mWakeLock = wakeLock;
+        mProxCallback = proxCallback;
         mResolver = mContext.getContentResolver();
 
         mSensors = new TriggerSensor[] {
@@ -86,6 +93,8 @@
                         true /* configured */,
                         DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
         };
+
+        mProxSensor = new ProxSensor();
         mCallback = callback;
     }
 
@@ -129,6 +138,10 @@
         }
     }
 
+    public void setProxListening(boolean listen) {
+        mProxSensor.setRegistered(listen);
+    }
+
     private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange, Uri uri, int userId) {
@@ -152,6 +165,43 @@
         }
     }
 
+    private class ProxSensor implements SensorEventListener {
+
+        boolean mRegistered;
+        Boolean mCurrentlyFar;
+
+        void setRegistered(boolean register) {
+            if (mRegistered == register) {
+                // Send an update even if we don't re-register.
+                mHandler.post(() -> {
+                    if (mCurrentlyFar != null) {
+                        mProxCallback.accept(mCurrentlyFar);
+                    }
+                });
+                return;
+            }
+            if (register) {
+                mRegistered = mSensorManager.registerListener(this,
+                        mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
+                        SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+            } else {
+                mSensorManager.unregisterListener(this);
+                mRegistered = false;
+                mCurrentlyFar = null;
+            }
+        }
+
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
+            mProxCallback.accept(mCurrentlyFar);
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        }
+    }
+
     private class TriggerSensor extends TriggerEventListener {
         final Sensor mSensor;
         final boolean mConfigured;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 1b9bf73..9b3593b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -46,6 +46,7 @@
 public class DozeTriggers implements DozeMachine.Part {
 
     private static final String TAG = "DozeTriggers";
+    private static final boolean DEBUG = DozeService.DEBUG;
 
     /** adb shell am broadcast -a com.android.systemui.doze.pulse com.android.systemui */
     private static final String PULSE_ACTION = "com.android.systemui.doze.pulse";
@@ -81,7 +82,7 @@
         mWakeLock = wakeLock;
         mAllowPulseTriggers = allowPulseTriggers;
         mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config,
-                wakeLock, this::onSensor);
+                wakeLock, this::onSensor, this::onProximityFar);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
     }
 
@@ -113,6 +114,22 @@
         }
     }
 
+    private void onProximityFar(boolean far) {
+        final boolean near = !far;
+        DozeMachine.State state = mMachine.getState();
+        if (near && state == DozeMachine.State.DOZE_PULSING) {
+            if (DEBUG) Log.i(TAG, "Prox NEAR, ending pulse");
+            mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE);
+        }
+        if (far && state == DozeMachine.State.DOZE_AOD_PAUSED) {
+            if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
+            mMachine.requestState(DozeMachine.State.DOZE_AOD);
+        } else if (near && state == DozeMachine.State.DOZE_AOD) {
+            if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
+            mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSED);
+        }
+    }
+
     private void onCarMode() {
         mMachine.requestState(DozeMachine.State.FINISH);
     }
@@ -131,15 +148,21 @@
                 break;
             case DOZE:
             case DOZE_AOD:
+            case DOZE_AOD_PAUSED:
+                mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
                 mDozeSensors.setListening(true);
                 if (oldState != DozeMachine.State.INITIALIZED) {
                     mDozeSensors.reregisterAllSensors();
                 }
                 break;
+            case DOZE_PULSING:
+                mDozeSensors.setProxListening(true);
+                break;
             case FINISH:
                 mBroadcastReceiver.unregister(mContext);
                 mDozeHost.removeCallback(mHostCallback);
                 mDozeSensors.setListening(false);
+                mDozeSensors.setProxListening(false);
                 break;
             default:
         }
@@ -156,6 +179,7 @@
 
     private void requestPulse(final int reason, boolean performedProxCheck) {
         Assert.isMainThread();
+        mDozeHost.extendPulse();
         if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
             return;
         }
@@ -286,6 +310,8 @@
     }
 
     private class TriggerReceiver extends BroadcastReceiver {
+        private boolean mRegistered;
+
         @Override
         public void onReceive(Context context, Intent intent) {
             if (PULSE_ACTION.equals(intent.getAction())) {
@@ -301,14 +327,22 @@
         }
 
         public void register(Context context) {
+            if (mRegistered) {
+                return;
+            }
             IntentFilter filter = new IntentFilter(PULSE_ACTION);
             filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
             filter.addAction(Intent.ACTION_USER_SWITCHED);
             context.registerReceiver(this, filter);
+            mRegistered = true;
         }
 
         public void unregister(Context context) {
+            if (!mRegistered) {
+                return;
+            }
             context.unregisterReceiver(this);
+            mRegistered = false;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index f577654..03076cc 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -20,6 +20,8 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.text.format.Formatter;
+import android.util.Log;
 
 import com.android.systemui.util.wakelock.WakeLock;
 
@@ -31,6 +33,7 @@
  */
 public class DozeUi implements DozeMachine.Part {
 
+    private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
     private final Context mContext;
     private final AlarmManager mAlarmManager;
     private final DozeHost mHost;
@@ -40,6 +43,7 @@
     private final AlarmManager.OnAlarmListener mTimeTick;
 
     private boolean mTimeTickScheduled = false;
+    private long mLastTimeTickElapsed = 0;
 
     public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
             WakeLock wakeLock, DozeHost host, Handler handler) {
@@ -75,11 +79,14 @@
                 scheduleTimeTick();
                 break;
             case DOZE:
+            case DOZE_AOD_PAUSED:
                 unscheduleTimeTick();
                 break;
             case DOZE_REQUEST_PULSE:
                 pulseWhileDozing(DozeLog.PULSE_REASON_NOTIFICATION /* TODO */);
                 break;
+            case DOZE_PULSE_DONE:
+                mHost.abortPulsing();
             case INITIALIZED:
                 mHost.startDozing();
                 break;
@@ -100,15 +107,26 @@
                 SystemClock.elapsedRealtime() + delta, "doze_time_tick", mTimeTick, mHandler);
 
         mTimeTickScheduled = true;
+        mLastTimeTickElapsed = SystemClock.elapsedRealtime();
     }
 
     private void unscheduleTimeTick() {
         if (!mTimeTickScheduled) {
             return;
         }
+        verifyLastTimeTick();
         mAlarmManager.cancel(mTimeTick);
     }
 
+    private void verifyLastTimeTick() {
+        long millisSinceLastTick = SystemClock.elapsedRealtime() - mLastTimeTickElapsed;
+        if (millisSinceLastTick > TIME_TICK_DEADLINE_MILLIS) {
+            String delay = Formatter.formatShortElapsedTime(mContext, millisSinceLastTick);
+            DozeLog.traceMissedTick(delay);
+            Log.e(DozeMachine.TAG, "Missed AOD time tick by " + delay);
+        }
+    }
+
     private long roundToNextMinute(long timeInMillis) {
         Calendar calendar = GregorianCalendar.getInstance();
         calendar.setTimeInMillis(timeInMillis);
@@ -124,6 +142,7 @@
             // Alarm was canceled, but we still got the callback. Ignore.
             return;
         }
+        verifyLastTimeTick();
 
         mHost.dozeTimeTick();
 
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
index cdda45f..f06ea45 100644
--- a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
@@ -30,8 +30,8 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.mland);
-        mLand = (MLand) findViewById(R.id.world);
-        mLand.setScoreFieldHolder((ViewGroup) findViewById(R.id.scores));
+        mLand = findViewById(R.id.world);
+        mLand.setScoreFieldHolder(findViewById(R.id.scores));
         final View welcome = findViewById(R.id.welcome);
         mLand.setSplash(welcome);
         final int numControllers = mLand.getGameControllers().size();
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 2b6ea15..8ac97f3 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -35,6 +35,7 @@
 import com.android.settingslib.applications.InterestingConfigChanges;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.Plugin;
+import com.android.systemui.util.leak.LeakDetector;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -77,6 +78,11 @@
             public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
                 FragmentHostManager.this.onFragmentViewDestroyed(f);
             }
+
+            @Override
+            public void onFragmentDestroyed(FragmentManager fm, Fragment f) {
+                Dependency.get(LeakDetector.class).trackGarbage(f);
+            }
         };
         mFragments.getFragmentManager().registerFragmentLifecycleCallbacks(mLifecycleCallbacks,
                 true);
@@ -157,7 +163,7 @@
         // TODO: Do something?
     }
 
-    private View findViewById(int id) {
+    private <T extends View> T findViewById(int id) {
         return mRootView.findViewById(id);
     }
 
@@ -245,7 +251,7 @@
 
         @Override
         @Nullable
-        public View onFindViewById(int id) {
+        public <T extends View> T onFindViewById(int id) {
             return FragmentHostManager.this.findViewById(id);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 86bb0de..4b3cdfb 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -39,7 +39,8 @@
     // This delay controls how long to wait before we show the target when the user first moves
     // the PIP, to prevent the target from animating if the user just wants to fling the PIP
     private static final int SHOW_TARGET_DELAY = 100;
-    private static final int SHOW_TARGET_DURATION = 200;
+    private static final int SHOW_TARGET_DURATION = 350;
+    private static final int HIDE_TARGET_DURATION = 225;
 
     private Context mContext;
     private WindowManager mWindowManager;
@@ -96,7 +97,7 @@
     public void showDismissTarget() {
         mDismissView.animate()
                 .alpha(1f)
-                .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+                .setInterpolator(Interpolators.LINEAR)
                 .setStartDelay(SHOW_TARGET_DELAY)
                 .setDuration(SHOW_TARGET_DURATION)
                 .start();
@@ -109,9 +110,9 @@
         if (mDismissView != null) {
             mDismissView.animate()
                     .alpha(0f)
-                    .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
+                    .setInterpolator(Interpolators.LINEAR)
                     .setStartDelay(0)
-                    .setDuration(SHOW_TARGET_DURATION)
+                    .setDuration(HIDE_TARGET_DURATION)
                     .withEndAction(new Runnable() {
                         @Override
                         public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 114a594..28bd23c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -86,6 +86,7 @@
 
             ComponentName topPipActivity = PipUtils.getTopPinnedActivity(mContext,
                     mActivityManager);
+            mMenuController.hideMenu();
             mNotificationController.onActivityUnpinned(topPipActivity);
 
             SystemServicesProxy.getInstance(mContext).setPipVisibility(topPipActivity != null);
@@ -142,10 +143,10 @@
 
         @Override
         public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
-                Rect animatingBounds, boolean fromImeAdjustement) {
+                Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) {
             mHandler.post(() -> {
                 mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds,
-                        fromImeAdjustement);
+                        fromImeAdjustement, displayRotation);
             });
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
index 3a4caa9..62ec09b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
@@ -48,6 +48,8 @@
 
     private static final String ACTION_PLAY = "com.android.systemui.pip.phone.PLAY";
     private static final String ACTION_PAUSE = "com.android.systemui.pip.phone.PAUSE";
+    private static final String ACTION_NEXT = "com.android.systemui.pip.phone.NEXT";
+    private static final String ACTION_PREV = "com.android.systemui.pip.phone.PREV";
 
     /**
      * A listener interface to receive notification on changes to the media actions.
@@ -67,6 +69,8 @@
 
     private RemoteAction mPauseAction;
     private RemoteAction mPlayAction;
+    private RemoteAction mNextAction;
+    private RemoteAction mPrevAction;
 
     private BroadcastReceiver mPlayPauseActionReceiver = new BroadcastReceiver() {
         @Override
@@ -76,6 +80,10 @@
                 mMediaController.getTransportControls().play();
             } else if (action.equals(ACTION_PAUSE)) {
                 mMediaController.getTransportControls().pause();
+            } else if (action.equals(ACTION_NEXT)) {
+                mMediaController.getTransportControls().skipToNext();
+            } else if (action.equals(ACTION_PREV)) {
+                mMediaController.getTransportControls().skipToPrevious();
             }
         }
     };
@@ -95,6 +103,8 @@
         IntentFilter mediaControlFilter = new IntentFilter();
         mediaControlFilter.addAction(ACTION_PLAY);
         mediaControlFilter.addAction(ACTION_PAUSE);
+        mediaControlFilter.addAction(ACTION_NEXT);
+        mediaControlFilter.addAction(ACTION_PREV);
         mContext.registerReceiver(mPlayPauseActionReceiver, mediaControlFilter);
 
         createMediaActions();
@@ -143,11 +153,21 @@
         int state = mMediaController.getPlaybackState().getState();
         boolean isPlaying = MediaSession.isActiveState(state);
         long actions = mMediaController.getPlaybackState().getActions();
+
+        // Prev action
+        mPrevAction.setEnabled((actions & PlaybackState.ACTION_SKIP_TO_PREVIOUS) != 0);
+        mediaActions.add(mPrevAction);
+
+        // Play/pause action
         if (!isPlaying && ((actions & PlaybackState.ACTION_PLAY) != 0)) {
             mediaActions.add(mPlayAction);
         } else if (isPlaying && ((actions & PlaybackState.ACTION_PAUSE) != 0)) {
             mediaActions.add(mPauseAction);
         }
+
+        // Next action
+        mNextAction.setEnabled((actions & PlaybackState.ACTION_SKIP_TO_NEXT) != 0);
+        mediaActions.add(mNextAction);
         return mediaActions;
     }
 
@@ -157,15 +177,27 @@
     private void createMediaActions() {
         String pauseDescription = mContext.getString(R.string.pip_pause);
         mPauseAction = new RemoteAction(Icon.createWithResource(mContext,
-                R.drawable.ic_pause_white_24dp), pauseDescription, pauseDescription,
+                R.drawable.ic_pause_white), pauseDescription, pauseDescription,
                         PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PAUSE),
                                 FLAG_UPDATE_CURRENT));
 
         String playDescription = mContext.getString(R.string.pip_play);
         mPlayAction = new RemoteAction(Icon.createWithResource(mContext,
-                R.drawable.ic_play_arrow_white_24dp), playDescription, playDescription,
+                R.drawable.ic_play_arrow_white), playDescription, playDescription,
                         PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PLAY),
                                 FLAG_UPDATE_CURRENT));
+
+        String nextDescription = mContext.getString(R.string.pip_skip_to_next);
+        mNextAction = new RemoteAction(Icon.createWithResource(mContext,
+                R.drawable.ic_skip_next_white), nextDescription, nextDescription,
+                        PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NEXT),
+                                FLAG_UPDATE_CURRENT));
+
+        String prevDescription = mContext.getString(R.string.pip_skip_to_prev);
+        mPrevAction = new RemoteAction(Icon.createWithResource(mContext,
+                R.drawable.ic_skip_previous_white), prevDescription, prevDescription,
+                        PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PREV),
+                                FLAG_UPDATE_CURRENT));
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index c06e56a..79ac816 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -188,13 +188,14 @@
         mDismissButton.setOnClickListener((v) -> {
             dismissPip();
         });
-        mActionsGroup = (LinearLayout) findViewById(R.id.actions_group);
+        mActionsGroup = findViewById(R.id.actions_group);
         mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
                 R.dimen.pip_between_action_padding_land);
-        mExpandButton = (ImageView) findViewById(R.id.expand_button);
+        mExpandButton = findViewById(R.id.expand_button);
 
         updateFromIntent(getIntent());
         setTitle(R.string.pip_menu_title);
+        setDisablePreviewScreenshots(true);
     }
 
     @Override
@@ -220,6 +221,13 @@
     }
 
     @Override
+    protected void onStop() {
+        super.onStop();
+
+        cancelDelayedFinish();
+    }
+
+    @Override
     protected void onDestroy() {
         super.onDestroy();
 
@@ -392,8 +400,8 @@
     }
 
     private void updateActionViews(Rect stackBounds) {
-        ViewGroup expandContainer = (ViewGroup) findViewById(R.id.expand_container);
-        ViewGroup actionsContainer = (ViewGroup) findViewById(R.id.actions_container);
+        ViewGroup expandContainer = findViewById(R.id.expand_container);
+        ViewGroup actionsContainer = findViewById(R.id.actions_container);
         actionsContainer.setOnTouchListener((v, ev) -> {
             // Do nothing, prevent click through to parent
             return true;
@@ -404,16 +412,26 @@
         } else {
             actionsContainer.setVisibility(View.VISIBLE);
             if (mActionsGroup != null) {
-                mActionsGroup.removeAllViews();
+                // Hide extra views
+                for (int i = mActions.size(); i < mActionsGroup.getChildCount(); i++) {
+                    mActionsGroup.getChildAt(i).setVisibility(View.GONE);
+                }
+                // Add needed views
+                final LayoutInflater inflater = LayoutInflater.from(this);
+                while (mActionsGroup.getChildCount() < mActions.size()) {
+                    final ImageView actionView = (ImageView) inflater.inflate(
+                            R.layout.pip_menu_action, mActionsGroup, false);
+                    mActionsGroup.addView(actionView);
+                }
 
                 // Recreate the layout
                 final boolean isLandscapePip = stackBounds != null &&
                         (stackBounds.width() > stackBounds.height());
-                final LayoutInflater inflater = LayoutInflater.from(this);
                 for (int i = 0; i < mActions.size(); i++) {
                     final RemoteAction action = mActions.get(i);
-                    final ImageView actionView = (ImageView) inflater.inflate(
-                            R.layout.pip_menu_action, mActionsGroup, false);
+                    final ImageView actionView = (ImageView) mActionsGroup.getChildAt(i);
+
+                    // TODO: Check if the action drawable has changed before we reload it
                     action.getIcon().loadDrawableAsync(this, d -> {
                         d.setTint(Color.WHITE);
                         actionView.setImageDrawable(d);
@@ -431,12 +449,11 @@
                         actionView.setAlpha(DISABLED_ACTION_ALPHA);
                         actionView.setEnabled(false);
                     }
-                    if (isLandscapePip && i > 0) {
-                        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
-                                actionView.getLayoutParams();
-                        lp.leftMargin = mBetweenActionPaddingLand;
-                    }
-                    mActionsGroup.addView(actionView);
+
+                    // Update the margin between actions
+                    LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+                            actionView.getLayoutParams();
+                    lp.leftMargin = (isLandscapePip && i > 0) ? mBetweenActionPaddingLand : 0;
                 }
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index fb8574d..67255d3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -37,10 +37,12 @@
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.Choreographer;
 import android.view.animation.Interpolator;
 
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
@@ -72,6 +74,7 @@
 
     private Context mContext;
     private IActivityManager mActivityManager;
+    private SurfaceFlingerVsyncChoreographer mVsyncChoreographer;
     private Handler mHandler;
 
     private PipSnapAlgorithm mSnapAlgorithm;
@@ -96,6 +99,8 @@
         mActivityManager = activityManager;
         mSnapAlgorithm = snapAlgorithm;
         mFlingAnimationUtils = flingAnimationUtils;
+        mVsyncChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, mContext.getDisplay(),
+                Choreographer.getInstance());
         onConfigurationChanged();
     }
 
@@ -311,7 +316,8 @@
      * Animates the PiP from the expanded state to the normal state after the menu is hidden.
      */
     void animateToUnexpandedState(Rect normalBounds, float savedSnapFraction,
-            Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized) {
+            Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized,
+            boolean immediate) {
         if (savedSnapFraction < 0f) {
             // If there are no saved snap fractions, then just use the current bounds
             savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds),
@@ -321,7 +327,11 @@
         if (minimized) {
             normalBounds = getClosestMinimizedBounds(normalBounds, normalMovementBounds);
         }
-        resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION);
+        if (immediate) {
+            movePip(normalBounds);
+        } else {
+            resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION);
+        }
     }
 
     /**
@@ -394,7 +404,7 @@
      */
     private void resizePipUnchecked(Rect toBounds) {
         if (!toBounds.equals(mBounds)) {
-            mHandler.post(() -> {
+            mVsyncChoreographer.scheduleAtSfVsync(() -> {
                 try {
                     mActivityManager.resizePinnedStack(toBounds, null /* tempPinnedTaskBounds */);
                     mBounds.set(toBounds);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index c3c09a0..3223f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -63,7 +63,7 @@
     private static final int METRIC_VALUE_DISMISSED_BY_TAP = 0;
     private static final int METRIC_VALUE_DISMISSED_BY_DRAG = 1;
 
-    private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 200;
+    private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 225;
 
     // Allow dragging the PIP to a location to close it
     private static final boolean ENABLE_DISMISS_DRAG_TO_EDGE = true;
@@ -78,6 +78,7 @@
     private final PipDismissViewController mDismissViewController;
     private final PipSnapAlgorithm mSnapAlgorithm;
     private final AccessibilityManager mAccessibilityManager;
+    private boolean mShowPipMenuOnAnimationEnd = false;
 
     // The current movement bounds
     private Rect mMovementBounds = new Rect();
@@ -89,6 +90,11 @@
     private Rect mExpandedMovementBounds = new Rect();
     private int mExpandedShortestEdgeSize;
 
+    // Used to workaround an issue where the WM rotation happens before we are notified, allowing
+    // us to send stale bounds
+    private int mDeferResizeToNormalBoundsUntilRotation = -1;
+    private int mDisplayRotation;
+
     private Handler mHandler = new Handler();
     private Runnable mShowDismissAffordance = new Runnable() {
         @Override
@@ -216,13 +222,18 @@
             setMinimizedStateInternal(false);
         }
         mDismissViewController.destroyDismissTarget();
-        mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
-                mMovementBounds, true /* allowMenuTimeout */);
+        mShowPipMenuOnAnimationEnd = true;
     }
 
     public void onPinnedStackAnimationEnded() {
         // Always synchronize the motion helper bounds once PiP animations finish
         mMotionHelper.synchronizePinnedStackBounds();
+
+        if (mShowPipMenuOnAnimationEnd) {
+            mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
+                    mMovementBounds, true /* allowMenuTimeout */);
+            mShowPipMenuOnAnimationEnd = false;
+        }
     }
 
     @Override
@@ -250,7 +261,7 @@
     }
 
     public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds,
-            boolean fromImeAdjustement) {
+            boolean fromImeAdjustement, int displayRotation) {
         // Re-calculate the expanded bounds
         mNormalBounds = normalBounds;
         Rect normalMovementBounds = new Rect();
@@ -304,7 +315,17 @@
         // above
         mNormalMovementBounds = normalMovementBounds;
         mExpandedMovementBounds = expandedMovementBounds;
+        mDisplayRotation = displayRotation;
         updateMovementBounds(mMenuState);
+
+        // If we have a deferred resize, apply it now
+        if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) {
+            mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
+                    mNormalMovementBounds, mMovementBounds, mIsMinimized,
+                    true /* immediate */);
+            mSavedSnapFraction = -1f;
+            mDeferResizeToNormalBoundsUntilRotation = -1;
+        }
     }
 
     private void onRegistrationChanged(boolean isRegistered) {
@@ -474,11 +495,34 @@
             // Try and restore the PiP to the closest edge, using the saved snap fraction
             // if possible
             if (resize) {
-                Rect normalBounds = new Rect(mNormalBounds);
-                mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
-                        mNormalMovementBounds, mMovementBounds, mIsMinimized);
+                // This is a very special case: when the menu is expanded and visible, navigating to
+                // another activity can trigger auto-enter PiP, and if the revealed activity has a
+                // forced rotation set, then the controller will get updated with the new rotation
+                // of the display. However, at the same time, SystemUI will try to hide the menu by
+                // creating an animation to the normal bounds which are now stale.  In such a case
+                // we defer the animation to the normal bounds until after the next
+                // onMovementBoundsChanged() call to get the bounds in the new orientation
+                if (mDeferResizeToNormalBoundsUntilRotation == -1) {
+                    try {
+                        int displayRotation = mPinnedStackController.getDisplayRotation();
+                        if (mDisplayRotation != displayRotation) {
+                            mDeferResizeToNormalBoundsUntilRotation = displayRotation;
+                        }
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Could not get display rotation from controller");
+                    }
+                }
+
+                if (mDeferResizeToNormalBoundsUntilRotation == -1) {
+                    Rect normalBounds = new Rect(mNormalBounds);
+                    mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
+                            mNormalMovementBounds, mMovementBounds, mIsMinimized,
+                            false /* immediate */);
+                    mSavedSnapFraction = -1f;
+                }
+            } else {
+                mSavedSnapFraction = -1f;
             }
-            mSavedSnapFraction = -1f;
         }
         mMenuState = menuState;
         updateMovementBounds(menuState);
@@ -662,6 +706,7 @@
                 mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
                         mMovementBounds, true /* allowMenuTimeout */);
             } else {
+                mMenuController.hideMenu();
                 mMotionHelper.expandPip();
             }
             return true;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
index 59cb086..40a63d7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
@@ -77,9 +77,9 @@
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(R.layout.tv_pip_control_button, this);
 
-        mIconImageView = (ImageView) findViewById(R.id.icon);
-        mButtonImageView = (ImageView) findViewById(R.id.button);
-        mDescriptionTextView = (TextView) findViewById(R.id.desc);
+        mIconImageView = findViewById(R.id.icon);
+        mButtonImageView = findViewById(R.id.button);
+        mDescriptionTextView = findViewById(R.id.desc);
 
         int[] values = new int[] {android.R.attr.src, android.R.attr.text};
         TypedArray typedArray =
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
index a2aff2d..acea3b6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
@@ -107,7 +107,7 @@
     public void onFinishInflate() {
         super.onFinishInflate();
 
-        mFullButtonView = (PipControlButtonView) findViewById(R.id.full_button);
+        mFullButtonView = findViewById(R.id.full_button);
         mFullButtonView.setOnFocusChangeListener(mFocusChangeListener);
         mFullButtonView.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -116,7 +116,7 @@
             }
         });
 
-        mCloseButtonView = (PipControlButtonView) findViewById(R.id.close_button);
+        mCloseButtonView = findViewById(R.id.close_button);
         mCloseButtonView.setOnFocusChangeListener(mFocusChangeListener);
         mCloseButtonView.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -128,7 +128,7 @@
             }
         });
 
-        mPlayPauseButtonView = (PipControlButtonView) findViewById(R.id.play_pause_button);
+        mPlayPauseButtonView = findViewById(R.id.play_pause_button);
         mPlayPauseButtonView.setOnFocusChangeListener(mFocusChangeListener);
         mPlayPauseButtonView.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -186,10 +186,10 @@
         } else {
             mPlayPauseButtonView.setVisibility(View.VISIBLE);
             if (state == PipManager.PLAYBACK_STATE_PLAYING) {
-                mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white_24dp);
+                mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white);
                 mPlayPauseButtonView.setText(R.string.pip_pause);
             } else {
-                mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white_24dp);
+                mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white);
                 mPlayPauseButtonView.setText(R.string.pip_play);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index ad290c3..657f08b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -56,16 +56,12 @@
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 
-import static com.android.systemui.Prefs.Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN;
-
 /**
  * Manages the picture-in-picture (PIP) UI and states.
  */
 public class PipManager implements BasePipManager {
     private static final String TAG = "PipManager";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    private static final boolean DEBUG_FORCE_ONBOARDING =
-            SystemProperties.getBoolean("debug.tv.pip_force_onboarding", false);
     private static final String SETTINGS_PACKAGE_AND_CLASS_DELIMITER = "/";
 
     private static PipManager sPipManager;
@@ -76,10 +72,9 @@
      */
     public static final int STATE_NO_PIP = 0;
     /**
-     * State when PIP is shown with an overlay message on top of it.
-     * This is used as default PIP state.
+     * State when PIP is shown. This is used as default PIP state.
      */
-    public static final int STATE_PIP_OVERLAY = 1;
+    public static final int STATE_PIP = 1;
     /**
      * State when PIP menu dialog is shown.
      */
@@ -126,7 +121,6 @@
     private int mPipTaskId = TASK_ID_NO_PIP;
     private ComponentName mPipComponentName;
     private MediaController mPipMediaController;
-    private boolean mOnboardingShown;
     private String[] mLastPackagesResourceGranted;
 
     private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
@@ -184,7 +178,7 @@
 
         @Override
         public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
-                Rect animatingBounds, boolean fromImeAdjustement) {
+                Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) {
             mHandler.post(() -> {
                 mDefaultPipBounds.set(normalBounds);
             });
@@ -212,8 +206,6 @@
         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);
 
         if (sSettingsPackageAndClassNamePairList == null) {
             String[] settings = mContext.getResources().getStringArray(
@@ -267,7 +259,7 @@
         //   1. Configuration changed due to the language change (RTL <-> RTL)
         //   2. SystemUI restarts after the crash
         mPipBounds = isSettingsShown() ? mSettingsPipBounds : mDefaultPipBounds;
-        resizePinnedStack(getPinnedStackInfo() == null ? STATE_NO_PIP : STATE_PIP_OVERLAY);
+        resizePinnedStack(getPinnedStackInfo() == null ? STATE_NO_PIP : STATE_PIP);
     }
 
     /**
@@ -281,7 +273,7 @@
      * Shows the picture-in-picture menu if an activity is in picture-in-picture mode.
      */
     public void showPictureInPictureMenu() {
-        if (mState == STATE_PIP_OVERLAY) {
+        if (mState == STATE_PIP) {
             resizePinnedStack(STATE_PIP_MENU);
         }
     }
@@ -325,16 +317,6 @@
     }
 
     /**
-     * Shows PIP overlay UI by launching {@link PipOverlayActivity}. It also locates the pinned
-     * stack to the default PIP bound {@link com.android.internal.R.string
-     * .config_defaultPictureInPictureBounds}.
-     */
-    private void showPipOverlay() {
-        if (DEBUG) Log.d(TAG, "showPipOverlay()");
-        PipOverlayActivity.showPipOverlay(mContext);
-    }
-
-    /**
      * Suspends resizing operation on the Pip until {@link #resumePipResizing} is called
      * @param reason The reason for suspending resizing operations on the Pip.
      */
@@ -388,7 +370,7 @@
             case STATE_PIP_MENU:
                 mCurrentPipBounds = mMenuModePipBounds;
                 break;
-            case STATE_PIP_OVERLAY:
+            case STATE_PIP:
                 mCurrentPipBounds = mPipBounds;
                 break;
             default:
@@ -454,17 +436,6 @@
         mMediaListeners.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);
-        }
-    }
-
     /**
      * Returns {@code true} if PIP is shown.
      */
@@ -617,11 +588,11 @@
                     return;
                 }
             }
-            if (mState == STATE_PIP_OVERLAY) {
+            if (mState == STATE_PIP) {
                 Rect bounds = isSettingsShown() ? mSettingsPipBounds : mDefaultPipBounds;
                 if (mPipBounds != bounds) {
                     mPipBounds = bounds;
-                    resizePinnedStack(STATE_PIP_OVERLAY);
+                    resizePinnedStack(STATE_PIP);
                 }
             }
         }
@@ -641,10 +612,9 @@
             mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
             mPipComponentName = ComponentName.unflattenFromString(
                     stackInfo.taskNames[stackInfo.taskNames.length - 1]);
-            // Set state to overlay so we show it when the pinned stack animation ends.
-            mState = STATE_PIP_OVERLAY;
+            // Set state to STATE_PIP so we show it when the pinned stack animation ends.
+            mState = STATE_PIP;
             mCurrentPipBounds = mPipBounds;
-            launchPipOnboardingActivityIfNeeded();
             mMediaSessionManager.addOnActiveSessionsChangedListener(
                     mActiveMediaSessionListener, null);
             updateMediaController(mMediaSessionManager.getActiveSessions(null));
@@ -671,9 +641,6 @@
                 return;
             }
             switch (mState) {
-                case STATE_PIP_OVERLAY:
-                    showPipOverlay();
-                    break;
                 case STATE_PIP_MENU:
                     showPipMenu();
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
index 01d86b6..ce1bea1 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
@@ -44,7 +44,7 @@
         mPipManager.addListener(this);
 
         mRestorePipSizeWhenClose = true;
-        mPipControlsView = (PipControlsView) findViewById(R.id.pip_controls);
+        mPipControlsView = findViewById(R.id.pip_controls);
         mFadeInAnimation = AnimatorInflater.loadAnimator(
                 this, R.anim.tv_pip_menu_fade_in_animation);
         mFadeInAnimation.setTarget(mPipControlsView);
@@ -56,7 +56,7 @@
     private void restorePipAndFinish() {
         if (mRestorePipSizeWhenClose) {
             // When PIP menu activity is closed, restore to the default position.
-            mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
+            mPipManager.resizePinnedStack(PipManager.STATE_PIP);
         }
         finish();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java
deleted file mode 100644
index 57952f4..0000000
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOnboardingActivity.java
+++ /dev/null
@@ -1,131 +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.pip.tv;
-
-import android.animation.Animator;
-import android.animation.AnimatorInflater;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.app.Activity;
-import android.graphics.drawable.AnimationDrawable;
-import android.os.Bundle;
-import android.view.View;
-import android.view.KeyEvent;
-import android.widget.ImageView;
-
-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();
-    private AnimatorSet mEnterAnimator;
-
-    @Override
-    protected void onCreate(Bundle bundle) {
-        super.onCreate(bundle);
-        setContentView(R.layout.tv_pip_onboarding);
-        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                finish();
-            }
-        });
-
-        mPipManager.addListener(this);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        mEnterAnimator = new AnimatorSet();
-        mEnterAnimator.playTogether(
-                loadAnimator(R.id.background, R.anim.tv_pip_onboarding_background_enter_animation),
-                loadAnimator(R.id.remote, R.anim.tv_pip_onboarding_image_enter_animation),
-                loadAnimator(R.id.remote_button, R.anim.tv_pip_onboarding_image_enter_animation),
-                loadAnimator(R.id.title, R.anim.tv_pip_onboarding_title_enter_animation),
-                loadAnimator(R.id.description,
-                        R.anim.tv_pip_onboarding_description_enter_animation),
-                loadAnimator(R.id.button, R.anim.tv_pip_onboarding_button_enter_animation));
-        mEnterAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                ImageView button = (ImageView) findViewById(R.id.remote_button);
-                ((AnimationDrawable) button.getDrawable()).start();
-            }
-        });
-        int delay = getResources().getInteger(R.integer.tv_pip_onboarding_anim_start_delay);
-        mEnterAnimator.setStartDelay(delay);
-        mEnterAnimator.start();
-    }
-
-    private Animator loadAnimator(int viewResId, int animResId) {
-        Animator animator = AnimatorInflater.loadAnimator(this, animResId);
-        animator.setTarget(findViewById(viewResId));
-        return animator;
-    }
-
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (mEnterAnimator.isStarted()) {
-            return true;
-        }
-        return super.onKeyUp(keyCode, event);
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (mEnterAnimator.isStarted()) {
-            return true;
-        }
-        return super.onKeyDown(keyCode, event);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        finish();
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        mPipManager.removeListener(this);
-    }
-
-    @Override
-    public void onPipEntered() { }
-
-    @Override
-    public void onPipActivityClosed() {
-        finish();
-    }
-
-    @Override
-    public void onShowPipMenu() {
-        finish();
-    }
-
-    @Override
-    public void onMoveToFullscreen() {
-        finish();
-    }
-
-    @Override
-    public void onPipResizeAboutToStart() { }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipOverlayActivity.java
deleted file mode 100644
index f52121f..0000000
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipOverlayActivity.java
+++ /dev/null
@@ -1,138 +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.pip.tv;
-
-import android.animation.Animator;
-import android.animation.AnimatorInflater;
-import android.app.Activity;
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.View;
-import android.widget.ImageView;
-
-import com.android.systemui.R;
-
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-
-/**
- * Activity to show an overlay on top of PIP activity to show how to pop up PIP menu.
- */
-public class PipOverlayActivity extends Activity implements PipManager.Listener {
-    private static final long SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS = 4000;
-
-    /**
-     * A flag to ensure the single instance of PipOverlayActivity to prevent it from restarting.
-     * Note that {@link PipManager} moves the PIPed activity to fullscreen if the activity is
-     * restarted. It's because the activity may be started by the Launcher or an intent again,
-     * but we don't want do so for the PipOverlayActivity.
-     */
-    private static boolean sActivityCreated;
-
-    private final PipManager mPipManager = PipManager.getInstance();
-    private final Handler mHandler = new Handler();
-    private View mGuideOverlayView;
-    private View mGuideButtonsView;
-    private ImageView mGuideButtonPlayPauseImageView;
-    private final Runnable mHideGuideOverlayRunnable = new Runnable() {
-        public void run() {
-            mFadeOutAnimation.start();
-        }
-    };
-    private Animator mFadeInAnimation;
-    private Animator mFadeOutAnimation;
-
-    /**
-     * Shows PIP overlay UI only if it's not there.
-     */
-    static void showPipOverlay(Context context) {
-        if (!sActivityCreated) {
-            Intent intent = new Intent(context, PipOverlayActivity.class);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            final ActivityOptions options = ActivityOptions.makeBasic();
-            options.setLaunchStackId(PINNED_STACK_ID);
-            context.startActivity(intent, options.toBundle());
-        }
-    }
-
-    @Override
-    protected void onCreate(Bundle bundle) {
-        super.onCreate(bundle);
-        sActivityCreated = true;
-        setContentView(R.layout.tv_pip_overlay);
-        mGuideOverlayView = findViewById(R.id.guide_overlay);
-        mPipManager.addListener(this);
-        mFadeInAnimation = AnimatorInflater.loadAnimator(
-                this, R.anim.tv_pip_overlay_fade_in_animation);
-        mFadeInAnimation.setTarget(mGuideOverlayView);
-        mFadeOutAnimation = AnimatorInflater.loadAnimator(
-                this, R.anim.tv_pip_overlay_fade_out_animation);
-        mFadeOutAnimation.setTarget(mGuideOverlayView);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mFadeInAnimation.start();
-        mHandler.removeCallbacks(mHideGuideOverlayRunnable);
-        mHandler.postDelayed(mHideGuideOverlayRunnable, SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS);
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        mHandler.removeCallbacks(mHideGuideOverlayRunnable);
-        finish();
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        sActivityCreated = false;
-        mHandler.removeCallbacksAndMessages(null);
-        mPipManager.removeListener(this);
-        mPipManager.resumePipResizing(
-                PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH);
-    }
-
-    @Override
-    public void onPipEntered() { }
-
-    @Override
-    public void onPipActivityClosed() {
-        finish();
-    }
-
-    @Override
-    public void onShowPipMenu() {
-        finish();
-    }
-
-    @Override
-    public void onMoveToFullscreen() {
-        finish();
-    }
-
-    @Override
-    public void onPipResizeAboutToStart() {
-        finish();
-        mPipManager.suspendPipResizing(
-                PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_OVERLAY_ACTIVITY_FINISH);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index d2a2919..f124e86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -92,14 +92,14 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mDetailContent = (ViewGroup) findViewById(android.R.id.content);
-        mDetailSettingsButton = (TextView) findViewById(android.R.id.button2);
-        mDetailDoneButton = (TextView) findViewById(android.R.id.button1);
+        mDetailContent = findViewById(android.R.id.content);
+        mDetailSettingsButton = findViewById(android.R.id.button2);
+        mDetailDoneButton = findViewById(android.R.id.button1);
 
         mQsDetailHeader = findViewById(R.id.qs_detail_header);
         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);
+        mQsDetailHeaderProgress = findViewById(R.id.qs_detail_header_progress);
 
         updateDetailText();
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index efc0668..f91aa9a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -76,7 +76,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mItemList = (AutoSizingList) findViewById(android.R.id.list);
+        mItemList = findViewById(android.R.id.list);
         mItemList.setVisibility(GONE);
         mItemList.setAdapter(mAdapter);
         mEmpty = findViewById(android.R.id.empty);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index d51fe8a..53c36e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -167,6 +167,9 @@
         if (mAlarmShowing) {
             builder.addFloat(mDate, "alpha", 1, 0)
                     .addFloat(mDateTimeGroup, "translationX", 0, -mDate.getWidth());
+        } else {
+            mDate.setAlpha(1);
+            mDateTimeGroup.setTranslationX(0);
         }
         mAnimator = builder.build();
         setExpansion(mExpansionAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 38485c7..f5e096eb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -98,9 +98,6 @@
 
         setupTileLayout();
 
-        mFooter = new QSSecurityFooter(this, context);
-        addView(mFooter.getView());
-
         mPageIndicator = LayoutInflater.from(context).inflate(
                 R.layout.qs_page_indicator, this, false);
         addView(mPageIndicator);
@@ -110,6 +107,9 @@
 
         addDivider();
 
+        mFooter = new QSSecurityFooter(this, context);
+        addView(mFooter.getView());
+
         updateResources();
 
         mBrightnessController = new BrightnessController(getContext(),
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 5b9d95d..51c6ad8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2014 The Android Open Source Project
  *
@@ -51,24 +50,21 @@
     private final View mRootView;
     private final TextView mFooterText;
     private final ImageView mFooterIcon;
-    private final ImageView mFooterIcon2;
     private final Context mContext;
     private final Callback mCallback = new Callback();
     private final SecurityController mSecurityController;
     private final ActivityStarter mActivityStarter;
     private final Handler mMainHandler;
+    private final View mDivider;
 
     private AlertDialog mDialog;
     private QSTileHost mHost;
     protected H mHandler;
 
     private boolean mIsVisible;
-    private boolean mIsIconVisible;
-    private boolean mIsIcon2Visible;
     private CharSequence mFooterTextContent = null;
     private int mFooterTextId;
     private int mFooterIconId;
-    private int mFooterIcon2Id;
 
     public QSSecurityFooter(QSPanel qsPanel, Context context) {
         mRootView = LayoutInflater.from(context)
@@ -76,14 +72,13 @@
         mRootView.setOnClickListener(this);
         mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
         mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon);
-        mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2);
-        mFooterIconId = R.drawable.ic_qs_vpn;
-        mFooterIcon2Id = R.drawable.ic_qs_network_logging;
+        mFooterIconId = R.drawable.ic_info_outline;
         mContext = context;
         mMainHandler = new Handler(Looper.getMainLooper());
         mActivityStarter = Dependency.get(ActivityStarter.class);
         mSecurityController = Dependency.get(SecurityController.class);
         mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
+        mDivider = qsPanel == null ? null : qsPanel.getDivider();
     }
 
     public void setHostEnvironment(QSTileHost host) {
@@ -130,45 +125,102 @@
     }
 
     private void handleRefreshState() {
-        boolean isVpnEnabled = mSecurityController.isVpnEnabled();
-        boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
-        mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
-        mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
-        if (mSecurityController.isDeviceManaged()) {
-            final CharSequence organizationName =
-                    mSecurityController.getDeviceOwnerOrganizationName();
-            if (organizationName != null) {
-                mFooterTextContent = mContext.getResources().getString(
-                        R.string.do_disclosure_with_name, organizationName);
-            } else {
-                mFooterTextContent =
-                        mContext.getResources().getString(R.string.do_disclosure_generic);
-            }
-            mIsVisible = true;
-            int footerIconId = isVpnEnabled
-                    ? R.drawable.ic_qs_vpn
-                    : R.drawable.ic_qs_network_logging;
-            if (mFooterIconId != footerIconId) {
-                mFooterIconId = footerIconId;
-                mMainHandler.post(mUpdateIcon);
-            }
-        } else {
-            boolean isBranded = mSecurityController.isVpnBranded();
-            mFooterTextContent = mContext.getResources().getText(
-                    isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer);
-            // Update the VPN footer icon, if needed.
-            int footerIconId = isVpnEnabled
-                    ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn)
-                    : R.drawable.ic_qs_network_logging;
-            if (mFooterIconId != footerIconId) {
-                mFooterIconId = footerIconId;
-                mMainHandler.post(mUpdateIcon);
-            }
-            mIsVisible = mIsIconVisible;
+        final boolean isDeviceManaged = mSecurityController.isDeviceManaged();
+        final boolean hasWorkProfile = mSecurityController.hasWorkProfile();
+        final boolean hasCACerts = mSecurityController.hasCACertInCurrentUser();
+        final boolean hasCACertsInWorkProfile = mSecurityController.hasCACertInWorkProfile();
+        final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+        final String vpnName = mSecurityController.getPrimaryVpnName();
+        final String vpnNameWorkProfile = mSecurityController.getWorkProfileVpnName();
+        final CharSequence organizationName = mSecurityController.getDeviceOwnerOrganizationName();
+        final CharSequence workProfileName = mSecurityController.getWorkProfileOrganizationName();
+        // Update visibility of footer
+        mIsVisible = isDeviceManaged || hasCACerts || hasCACertsInWorkProfile ||
+            vpnName != null || vpnNameWorkProfile != null;
+        // Update the string
+        mFooterTextContent = getFooterText(isDeviceManaged, hasWorkProfile,
+                hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
+                vpnNameWorkProfile, organizationName, workProfileName);
+        // Update the icon
+        int footerIconId = vpnName != null || vpnNameWorkProfile != null
+                ? R.drawable.ic_qs_vpn
+                : R.drawable.ic_info_outline;
+        if (mFooterIconId != footerIconId) {
+            mFooterIconId = footerIconId;
+            mMainHandler.post(mUpdateIcon);
         }
         mMainHandler.post(mUpdateDisplayState);
     }
 
+    protected CharSequence getFooterText(boolean isDeviceManaged, boolean hasWorkProfile,
+            boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
+            String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
+            CharSequence workProfileName) {
+        if (isDeviceManaged) {
+            if (hasCACerts || hasCACertsInWorkProfile || isNetworkLoggingEnabled) {
+                if (organizationName == null) {
+                    return mContext.getString(
+                            R.string.quick_settings_disclosure_management_monitoring);
+                }
+                return mContext.getString(
+                        R.string.quick_settings_disclosure_named_management_monitoring,
+                        organizationName);
+            }
+            if (vpnName != null && vpnNameWorkProfile != null) {
+                if (organizationName == null) {
+                    return mContext.getString(R.string.quick_settings_disclosure_management_vpns);
+                }
+                return mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
+                        organizationName);
+            }
+            if (vpnName != null || vpnNameWorkProfile != null) {
+                if (organizationName == null) {
+                    return mContext.getString(
+                            R.string.quick_settings_disclosure_management_named_vpn,
+                            vpnName != null ? vpnName : vpnNameWorkProfile);
+                }
+                return mContext.getString(
+                        R.string.quick_settings_disclosure_named_management_named_vpn,
+                        organizationName,
+                        vpnName != null ? vpnName : vpnNameWorkProfile);
+            }
+            if (organizationName == null) {
+                return mContext.getString(R.string.quick_settings_disclosure_management);
+            }
+            return mContext.getString(R.string.quick_settings_disclosure_named_management,
+                    organizationName);
+        } // end if(isDeviceManaged)
+        if (hasCACertsInWorkProfile) {
+            if (workProfileName == null) {
+                return mContext.getString(
+                        R.string.quick_settings_disclosure_managed_profile_monitoring);
+            }
+            return mContext.getString(
+                    R.string.quick_settings_disclosure_named_managed_profile_monitoring,
+                    workProfileName);
+        }
+        if (hasCACerts) {
+            return mContext.getString(R.string.quick_settings_disclosure_monitoring);
+        }
+        if (vpnName != null && vpnNameWorkProfile != null) {
+            return mContext.getString(R.string.quick_settings_disclosure_vpns);
+        }
+        if (vpnNameWorkProfile != null) {
+            return mContext.getString(R.string.quick_settings_disclosure_managed_profile_named_vpn,
+                    vpnNameWorkProfile);
+        }
+        if (vpnName != null) {
+            if (hasWorkProfile) {
+                return mContext.getString(
+                        R.string.quick_settings_disclosure_personal_profile_named_vpn,
+                        vpnName);
+            }
+            return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
+                    vpnName);
+        }
+        return null;
+    }
+
     @Override
     public void onClick(DialogInterface dialog, int which) {
         if (which == DialogInterface.BUTTON_NEGATIVE) {
@@ -182,18 +234,15 @@
         final String profileOwnerPackage = mSecurityController.getProfileOwnerName();
         final boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
         final String primaryVpn = mSecurityController.getPrimaryVpnName();
-        final String profileVpn = mSecurityController.getProfileVpnName();
+        final String profileVpn = mSecurityController.getWorkProfileVpnName();
         final CharSequence deviceOwnerOrganization =
                 mSecurityController.getDeviceOwnerOrganizationName();
         boolean hasProfileOwner = mSecurityController.hasProfileOwner();
-        boolean isBranded = deviceOwnerPackage == null && mSecurityController.isVpnBranded();
 
         mDialog = new SystemUIDialog(mContext);
-        if (!isBranded) {
-            mDialog.setTitle(getTitle(deviceOwnerPackage));
-        }
+        mDialog.setTitle(getTitle(deviceOwnerPackage));
         CharSequence msg = getMessage(deviceOwnerPackage, profileOwnerPackage, primaryVpn,
-                profileVpn, deviceOwnerOrganization, hasProfileOwner, isBranded);
+                profileVpn, deviceOwnerOrganization, hasProfileOwner);
         if (deviceOwnerPackage == null) {
             mDialog.setMessage(msg);
             if (mSecurityController.isVpnEnabled() && !mSecurityController.isVpnRestricted()) {
@@ -235,7 +284,7 @@
             }
         }
 
-        mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(isBranded), this);
+        mDialog.setButton(DialogInterface.BUTTON_POSITIVE, getPositiveButton(), this);
         mDialog.show();
         mDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
     }
@@ -244,13 +293,13 @@
         return mContext.getString(R.string.status_bar_settings_settings_button);
     }
 
-    private String getPositiveButton(boolean isBranded) {
-        return mContext.getString(isBranded ? android.R.string.ok : R.string.quick_settings_done);
+    private String getPositiveButton() {
+        return mContext.getString(R.string.quick_settings_done);
     }
 
     protected CharSequence getMessage(String deviceOwnerPackage, String profileOwnerPackage,
             String primaryVpn, String profileVpn, CharSequence deviceOwnerOrganization,
-            boolean hasProfileOwner, boolean isBranded) {
+            boolean hasProfileOwner) {
         if (deviceOwnerPackage != null) {
             final SpannableStringBuilder message = new SpannableStringBuilder();
             if (deviceOwnerOrganization != null) {
@@ -273,13 +322,8 @@
                 return mContext.getString(R.string.monitoring_description_app_personal_work,
                         profileOwnerPackage, profileVpn, primaryVpn);
             } else {
-                if (isBranded) {
-                    return mContext.getString(R.string.branded_monitoring_description_app_personal,
-                            primaryVpn);
-                } else {
-                    return mContext.getString(R.string.monitoring_description_app_personal,
-                            primaryVpn);
-                }
+                return mContext.getString(R.string.monitoring_description_app_personal,
+                        primaryVpn);
             }
         } else if (profileVpn != null) {
             return mContext.getString(R.string.monitoring_description_app_work,
@@ -305,7 +349,6 @@
         @Override
         public void run() {
             mFooterIcon.setImageResource(mFooterIconId);
-            mFooterIcon2.setImageResource(mFooterIcon2Id);
         }
     };
 
@@ -316,8 +359,7 @@
                 mFooterText.setText(mFooterTextContent);
             }
             mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE);
-            mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE);
-            mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE);
+            if (mDivider != null) mDivider.setVisibility(mIsVisible ? View.GONE : View.VISIBLE);
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 7518527a..e457d72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -77,6 +77,9 @@
 
         BatteryMeterView battery = findViewById(R.id.battery);
         battery.setForceShowPercent(true);
+        // Don't show the Wi-Fi indicator here, because it is shown just below in the tile.
+        SignalClusterView signalCluster = findViewById(R.id.signal_cluster);
+        signalCluster.setForceBlockWifi();
 
         mActivityStarter = Dependency.get(ActivityStarter.class);
     }
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 596d3bc..30053e3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -82,7 +82,7 @@
 
         LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
 
-        mToolbar = (Toolbar) findViewById(com.android.internal.R.id.action_bar);
+        mToolbar = findViewById(com.android.internal.R.id.action_bar);
         TypedValue value = new TypedValue();
         mContext.getTheme().resolveAttribute(android.R.attr.homeAsUpIndicator, value, true);
         mToolbar.setNavigationIcon(
@@ -98,7 +98,7 @@
                 mContext.getString(com.android.internal.R.string.reset));
         mToolbar.setTitle(R.string.qs_edit);
 
-        mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
+        mRecyclerView = findViewById(android.R.id.list);
         mTileAdapter = new TileAdapter(getContext());
         mRecyclerView.setAdapter(mTileAdapter);
         mTileAdapter.getItemTouchHelper().attachToRecyclerView(mRecyclerView);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 6781c16..976efb2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -340,12 +340,12 @@
         switch (state) {
             case Tile.STATE_UNAVAILABLE:
                 return Utils.getDisabled(context,
-                        Utils.getColorAttr(context, android.R.attr.textColorTertiary));
+                        Utils.getColorAttr(context, android.R.attr.textColorPrimary));
             case Tile.STATE_INACTIVE:
                 return Utils.getDisabled(context,
-                        Utils.getColorAttr(context, android.R.attr.textColorSecondary));
+                        Utils.getColorAttr(context, android.R.attr.colorForeground));
             case Tile.STATE_ACTIVE:
-                return Utils.getColorAttr(context, attr.textColorSecondary);
+                return Utils.getColorAttr(context, android.R.attr.textColorPrimary);
             default:
                 Log.e("QSTile", "Invalid state " + state);
                 return 0;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 8209ee2..ecc275d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -181,7 +181,7 @@
                 return;
             }
             mDrawable.setBatteryLevel(100);
-            mDrawable.setPluggedIn(false);
+            mDrawable.setCharging(false);
             mDrawable.setPowerSave(true);
             mDrawable.setShowPercent(false);
             ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
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 9b3ee30..d74e3ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -35,8 +35,8 @@
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile.SignalState;
-import com.android.systemui.qs.CellTileView;
 import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.SignalTileView;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -83,7 +83,7 @@
 
     @Override
     public QSIconView createTileView(Context context) {
-        return new CellTileView(context);
+        return new SignalTileView(context);
     }
 
     @Override
@@ -118,15 +118,6 @@
         }
 
         final Resources r = mContext.getResources();
-        final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim
-                : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
-                : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
-                : R.drawable.ic_qs_signal_no_signal;
-        if (cb.dataTypeIconId != 0) {
-            state.icon = ResourceIcon.get(cb.dataTypeIconId);
-        } else {
-            state.icon = ResourceIcon.get(iconId);
-        }
         state.activityIn = cb.enabled && cb.activityIn;
         state.activityOut = cb.enabled && cb.activityOut;
 
@@ -136,8 +127,16 @@
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.value = mDataController.isMobileDataSupported()
                 && mDataController.isMobileDataEnabled();
-        state.state = cb.airplaneModeEnabled ? Tile.STATE_UNAVAILABLE
+        state.icon = ResourceIcon.get(R.drawable.ic_data_unavailable);
+        state.state = cb.airplaneModeEnabled || !cb.enabled || cb.noSim ? Tile.STATE_UNAVAILABLE
                 : state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+        if (state.state == Tile.STATE_ACTIVE) {
+            state.icon = ResourceIcon.get(R.drawable.ic_data_on);
+        } else if (state.state == Tile.STATE_INACTIVE) {
+            state.icon = ResourceIcon.get(R.drawable.ic_data_off);
+        } else {
+            state.icon = ResourceIcon.get(R.drawable.ic_data_unavailable);
+        }
     }
 
     @Override
@@ -162,46 +161,27 @@
 
     private static final class CallbackInfo {
         boolean enabled;
-        boolean wifiEnabled;
         boolean airplaneModeEnabled;
-        int mobileSignalIconId;
-        String signalContentDescription;
-        int dataTypeIconId;
-        String dataContentDescription;
         boolean activityIn;
         boolean activityOut;
-        String enabledDesc;
         boolean noSim;
-        boolean isDataTypeIconWide;
         boolean roaming;
     }
 
     private final class CellSignalCallback implements SignalCallback {
         private final CallbackInfo mInfo = new CallbackInfo();
-        @Override
-        public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
-                boolean activityIn, boolean activityOut, String description, boolean isTransient) {
-            mInfo.wifiEnabled = enabled;
-            refreshState(mInfo);
-        }
 
         @Override
-        public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-                int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-                String description, boolean isWide, int subId, boolean roaming) {
-            if (qsIcon == null) {
+        public void setMobileDataIndicators(IconState statusIcon, int statusType,
+                boolean activityIn, boolean activityOut, String typeContentDescription,
+                int subId, boolean roaming, boolean isEmergency) {
+            if (statusIcon == null) {
                 // Not data sim, don't display.
                 return;
             }
-            mInfo.enabled = qsIcon.visible;
-            mInfo.mobileSignalIconId = qsIcon.icon;
-            mInfo.signalContentDescription = qsIcon.contentDescription;
-            mInfo.dataTypeIconId = qsType;
-            mInfo.dataContentDescription = typeContentDescription;
+            mInfo.enabled = statusIcon.visible;
             mInfo.activityIn = activityIn;
             mInfo.activityOut = activityOut;
-            mInfo.enabledDesc = description;
-            mInfo.isDataTypeIconWide = qsType != 0 && isWide;
             mInfo.roaming = roaming;
             refreshState(mInfo);
         }
@@ -209,16 +189,6 @@
         @Override
         public void setNoSims(boolean show) {
             mInfo.noSim = show;
-            if (mInfo.noSim) {
-                // Make sure signal gets cleared out when no sims.
-                mInfo.mobileSignalIconId = 0;
-                mInfo.dataTypeIconId = 0;
-                // Show a No SIMs description to avoid emergency calls message.
-                mInfo.enabled = true;
-                mInfo.enabledDesc = mContext.getString(
-                        R.string.keyguard_missing_sim_message_short);
-                mInfo.signalContentDescription = mInfo.enabledDesc;
-            }
             refreshState(mInfo);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index 9cd79f8..7224ae6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -98,21 +98,21 @@
             usageColor = Utils.getColorAccent(mContext);
         }
 
-        final TextView title = (TextView) findViewById(android.R.id.title);
+        final TextView title = findViewById(android.R.id.title);
         title.setText(titleId);
-        final TextView usage = (TextView) findViewById(R.id.usage_text);
+        final TextView usage = findViewById(R.id.usage_text);
         usage.setText(formatBytes(bytes));
         usage.setTextColor(usageColor);
-        final DataUsageGraph graph = (DataUsageGraph) findViewById(R.id.usage_graph);
+        final DataUsageGraph graph = findViewById(R.id.usage_graph);
         graph.setLevels(info.limitLevel, info.warningLevel, info.usageLevel);
-        final TextView carrier = (TextView) findViewById(R.id.usage_carrier_text);
+        final TextView carrier = findViewById(R.id.usage_carrier_text);
         carrier.setText(info.carrier);
-        final TextView period = (TextView) findViewById(R.id.usage_period_text);
+        final TextView period = findViewById(R.id.usage_period_text);
         period.setText(info.period);
-        final TextView infoTop = (TextView) findViewById(R.id.usage_info_top_text);
+        final TextView infoTop = findViewById(R.id.usage_info_top_text);
         infoTop.setVisibility(top != null ? View.VISIBLE : View.GONE);
         infoTop.setText(top);
-        final TextView infoBottom = (TextView) findViewById(R.id.usage_info_bottom_text);
+        final TextView infoBottom = findViewById(R.id.usage_info_bottom_text);
         infoBottom.setVisibility(bottom != null ? View.VISIBLE : View.GONE);
         infoBottom.setText(bottom);
         boolean showLevel = info.warningLevel > 0 || info.limitLevel > 0;
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 b11b15a..6522e10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -22,7 +22,6 @@
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
@@ -32,7 +31,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
 
 /** Quick settings tile: Location **/
 public class LocationTile extends QSTileImpl<BooleanState> {
@@ -132,7 +131,7 @@
         }
     }
 
-    private final class Callback implements LocationSettingsChangeCallback,
+    private final class Callback implements LocationChangeCallback,
             KeyguardMonitor.Callback {
         @Override
         public void onLocationSettingsChanged(boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index c485a9e..1e9a618 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -117,8 +117,8 @@
 
     @Override
     protected void onFinishInflate() {
-        mAvatar = (UserAvatarView) findViewById(R.id.user_picture);
-        mName = (TextView) findViewById(R.id.user_name);
+        mAvatar = findViewById(R.id.user_picture);
+        mName = findViewById(R.id.user_name);
         if (mRegularTypeface == null) {
             mRegularTypeface = mName.getTypeface();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f0a9bc3..143d934 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -325,7 +325,7 @@
         // Set the Recents layout
         setContentView(R.layout.recents);
         takeKeyEvents(true);
-        mRecentsView = (RecentsView) findViewById(R.id.recents_view);
+        mRecentsView = findViewById(R.id.recents_view);
         mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
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 397b78d..429ace6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -65,7 +65,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.util.ArraySet;
-import android.util.LauncherIcons;
+import android.util.IconDrawableFactory;
 import android.util.Log;
 import android.util.MutableBoolean;
 import android.view.Display;
@@ -82,7 +82,6 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.R;
 import com.android.systemui.pip.tv.PipMenuActivity;
-import com.android.systemui.pip.tv.PipOnboardingActivity;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.RecentsImpl;
@@ -113,7 +112,6 @@
     final static List<String> sRecentsBlacklist;
     static {
         sRecentsBlacklist = new ArrayList<>();
-        sRecentsBlacklist.add(PipOnboardingActivity.class.getName());
         sRecentsBlacklist.add(PipMenuActivity.class.getName());
     }
 
@@ -123,6 +121,7 @@
     ActivityManager mAm;
     IActivityManager mIam;
     PackageManager mPm;
+    IconDrawableFactory mDrawableFactory;
     IPackageManager mIpm;
     AssistUtils mAssistUtils;
     WindowManager mWm;
@@ -141,7 +140,6 @@
     int mDummyThumbnailHeight;
     Paint mBgProtectionPaint;
     Canvas mBgProtectionCanvas;
-    LauncherIcons mLauncherIcons;
 
     private final Handler mHandler = new H();
 
@@ -260,6 +258,7 @@
         mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         mIam = ActivityManager.getService();
         mPm = context.getPackageManager();
+        mDrawableFactory = IconDrawableFactory.newInstance(context);
         mIpm = AppGlobals.getPackageManager();
         mAssistUtils = new AssistUtils(context);
         mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@@ -298,8 +297,6 @@
 
         Collections.addAll(sRecentsBlacklist,
                 res.getStringArray(R.array.recents_blacklist_array));
-
-        mLauncherIcons = new LauncherIcons(context);
     }
 
     /**
@@ -810,13 +807,19 @@
      * Returns the content description for a given task, badging it if necessary.  The content
      * description joins the app and activity labels.
      */
-    public String getBadgedContentDescription(ActivityInfo info, int userId, Resources res) {
+    public String getBadgedContentDescription(ActivityInfo info, int userId,
+            ActivityManager.TaskDescription td, Resources res) {
         // If we are mocking, then return a mock label
         if (RecentsDebugFlags.Static.EnableMockTasks) {
             return "Recent Task Content Description: " + userId;
         }
 
-        String activityLabel = info.loadLabel(mPm).toString();
+        String activityLabel;
+        if (td != null && td.getLabel() != null) {
+            activityLabel = td.getLabel();
+        } else {
+            activityLabel = info.loadLabel(mPm).toString();
+        }
         String applicationLabel = info.applicationInfo.loadLabel(mPm).toString();
         String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
         return applicationLabel.equals(activityLabel) ? badgedApplicationLabel
@@ -836,8 +839,7 @@
             return new ColorDrawable(0xFF666666);
         }
 
-        Drawable icon = mLauncherIcons.wrapIconDrawableWithShadow(info.loadIcon(mPm));
-        return getBadgedIcon(icon, userId);
+        return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId);
     }
 
     /**
@@ -852,8 +854,7 @@
             return new ColorDrawable(0xFF666666);
         }
 
-        Drawable icon = mLauncherIcons.wrapIconDrawableWithShadow(appInfo.loadIcon(mPm));
-        return getBadgedIcon(icon, userId);
+        return mDrawableFactory.getBadgedIcon(appInfo, userId);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 5c25bfd..78c71a11 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -182,7 +182,8 @@
             // Load the title, icon, and color
             ActivityInfo info = loader.getAndUpdateActivityInfo(taskKey);
             String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
-            String titleDescription = loader.getAndUpdateContentDescription(taskKey, res);
+            String titleDescription = loader.getAndUpdateContentDescription(taskKey,
+                    t.taskDescription, res);
             String dismissDescription = String.format(dismissDescFormat, titleDescription);
             String appInfoDescription = String.format(appInfoDescFormat, titleDescription);
             Drawable icon = isStackTask
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index e8ffb91..5e78b61 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -449,7 +449,8 @@
      * Returns the cached task content description if the task key is not expired, updating the
      * cache if it is.
      */
-    String getAndUpdateContentDescription(Task.TaskKey taskKey, Resources res) {
+    String getAndUpdateContentDescription(Task.TaskKey taskKey, ActivityManager.TaskDescription td,
+            Resources res) {
         SystemServicesProxy ssp = Recents.getSystemServices();
 
         // Return the cached content description if it exists
@@ -461,8 +462,15 @@
         // All short paths failed, load the label from the activity info and cache it
         ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey);
         if (activityInfo != null) {
-            label = ssp.getBadgedContentDescription(activityInfo, taskKey.userId, res);
-            mContentDescriptionCache.put(taskKey, label);
+            label = ssp.getBadgedContentDescription(activityInfo, taskKey.userId, td, res);
+            if (td == null) {
+                // Only add to the cache if the task description is null, otherwise, it is possible
+                // for the task description to change between calls without the last active time
+                // changing (ie. between preloading and Overview starting) which would lead to stale
+                // content descriptions
+                // TODO: Investigate improving this
+                mContentDescriptionCache.put(taskKey, label);
+            }
             return label;
         }
         // If the content description does not exist, return an empty label for now, but do not
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 b8be580..e34987b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -222,8 +222,8 @@
     @Override
     protected void onFinishInflate() {
         // Bind the views
-        mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
-        mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
+        mHeaderView = findViewById(R.id.task_view_bar);
+        mThumbnailView = findViewById(R.id.task_view_thumbnail);
         mThumbnailView.updateClipToTaskBar(mHeaderView);
         mActionButtonView = findViewById(R.id.lock_to_app_fab);
         mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
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 311f8ff..ae922fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -244,12 +244,12 @@
         SystemServicesProxy ssp = Recents.getSystemServices();
 
         // Initialize the icon and description views
-        mIconView = (ImageView) findViewById(R.id.icon);
+        mIconView = findViewById(R.id.icon);
         mIconView.setOnLongClickListener(this);
-        mTitleView = (TextView) findViewById(R.id.title);
-        mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
+        mTitleView = findViewById(R.id.title);
+        mDismissButton = findViewById(R.id.dismiss_task);
         if (ssp.hasFreeformWorkspaceSupport()) {
-            mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
+            mMoveTaskButton = findViewById(R.id.move_task);
         }
 
         onConfigurationChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 7d847a3..6918a63 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -54,8 +54,8 @@
                 R.layout.quick_settings_brightness_dialog, null);
         setContentView(v);
 
-        final ImageView icon = (ImageView) findViewById(R.id.brightness_icon);
-        final ToggleSliderView slider = (ToggleSliderView) findViewById(R.id.brightness_slider);
+        final ImageView icon = findViewById(R.id.brightness_icon);
+        final ToggleSliderView slider = findViewById(R.id.brightness_slider);
         mBrightnessController = new BrightnessController(this, icon, slider);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
index afe89ec..5b234e9 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSliderView.java
@@ -60,13 +60,13 @@
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.ToggleSliderView, defStyle, 0);
 
-        mToggle = (CompoundButton) findViewById(R.id.toggle);
+        mToggle = findViewById(R.id.toggle);
         mToggle.setOnCheckedChangeListener(mCheckListener);
 
-        mSlider = (ToggleSeekBar) findViewById(R.id.slider);
+        mSlider = findViewById(R.id.slider);
         mSlider.setOnSeekBarChangeListener(mSeekListener);
 
-        mLabel = (TextView) findViewById(R.id.label);
+        mLabel = findViewById(R.id.label);
         mLabel.setText(a.getString(R.styleable.ToggleSliderView_text));
 
         mSlider.setAccessibilityLabel(getContentDescription().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index c48ecdb..da56e62 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -269,9 +269,9 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mHandle = (DividerHandleView) findViewById(R.id.docked_divider_handle);
+        mHandle = findViewById(R.id.docked_divider_handle);
         mBackground = findViewById(R.id.docked_divider_background);
-        mMinimizedShadow = (MinimizedDockShadow) findViewById(R.id.minimized_dock_shadow);
+        mMinimizedShadow = findViewById(R.id.minimized_dock_shadow);
         mHandle.setOnTouchListener(this);
         mDividerWindowWidth = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_divider_thickness);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index d4997ea..469f3ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -203,10 +203,10 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mBackgroundNormal = (NotificationBackgroundView) findViewById(R.id.backgroundNormal);
-        mFakeShadow = (FakeShadowView) findViewById(R.id.fake_shadow);
+        mBackgroundNormal = findViewById(R.id.backgroundNormal);
+        mFakeShadow = findViewById(R.id.fake_shadow);
         mShadowHidden = mFakeShadow.getVisibility() != VISIBLE;
-        mBackgroundDimmed = (NotificationBackgroundView) findViewById(R.id.backgroundDimmed);
+        mBackgroundDimmed = findViewById(R.id.backgroundDimmed);
         mBackgroundNormal.setCustomBackground(R.drawable.notification_material_bg);
         mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
         updateBackground();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 677642e..dff09bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1115,6 +1115,10 @@
         mNotificationInflater.setInflateExceptionHandler(inflateExceptionHandler);
     }
 
+    public void setNeedsRedaction(boolean needsRedaction) {
+        mNotificationInflater.setRedactAmbient(needsRedaction);
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -1490,7 +1494,7 @@
             return getActualHeight();
         }
         if (mGuts != null && mGuts.isExposed()) {
-            return mGuts.getHeight();
+            return mGuts.getIntrinsicHeight();
         } else if ((isChildInGroup() && !isGroupExpanded())) {
             return mPrivateLayout.getMinHeight();
         } else if (mShowAmbient) {
@@ -1831,7 +1835,9 @@
 
     @Override
     public int getMinHeight() {
-        if (!mOnKeyguard && mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
+        if (mGuts != null && mGuts.isExposed()) {
+            return mGuts.getIntrinsicHeight();
+        } else if (!mOnKeyguard && mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
                 return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
         } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
             return mChildrenContainer.getMinHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutAppItemLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutAppItemLayout.java
index 507b665..5377dee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutAppItemLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutAppItemLayout.java
@@ -44,8 +44,8 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
-            ImageView shortcutIcon = (ImageView) findViewById(R.id.keyboard_shortcuts_icon);
-            TextView shortcutKeyword = (TextView) findViewById(R.id.keyboard_shortcuts_keyword);
+            ImageView shortcutIcon = findViewById(R.id.keyboard_shortcuts_icon);
+            TextView shortcutKeyword = findViewById(R.id.keyboard_shortcuts_keyword);
             int totalMeasuredWidth = MeasureSpec.getSize(widthMeasureSpec);
             int totalPadding = getPaddingLeft() + getPaddingRight();
             int availableWidth = totalMeasuredWidth - totalPadding;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 8f160dc..6098565 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -428,6 +428,9 @@
             mAmbientChild.animate().cancel();
             removeView(mAmbientChild);
         }
+        if (child == null) {
+            return;
+        }
         addView(child);
         mAmbientChild = child;
         mAmbientWrapper = NotificationViewWrapper.wrap(getContext(), child,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 2713f58..1375310 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -39,6 +39,7 @@
 import android.view.View;
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -73,7 +74,8 @@
     private Handler mHandler;
     private Runnable mFalsingCheck;
     private boolean mNeedsFalsingProtection;
-    private OnGutsClosedListener mListener;
+    private OnGutsClosedListener mClosedListener;
+    private OnHeightChangedListener mHeightListener;
 
     private GutsContent mGutsContent;
 
@@ -87,6 +89,11 @@
         public View getContentView();
 
         /**
+         * @return the actual height of the content.
+         */
+        public int getActualHeight();
+
+        /**
          * Called when the guts view have been told to close, typically after an outside
          * interaction. Returning {@code true} here will prevent the guts view to close.
          */
@@ -102,6 +109,10 @@
         public void onGutsClosed(NotificationGuts guts);
     }
 
+    public interface OnHeightChangedListener {
+        public void onHeightChanged(NotificationGuts guts);
+    }
+
     interface OnSettingsClickListener {
         void onClick(View v, int appUid);
     }
@@ -125,7 +136,6 @@
 
     public NotificationGuts(Context context) {
         this(context, null);
-
     }
 
     public void setGutsContent(GutsContent content) {
@@ -189,8 +199,8 @@
 
     public void closeControls(int x, int y, boolean save) {
         if (getWindowToken() == null) {
-            if (mListener != null) {
-                mListener.onGutsClosed(this);
+            if (mClosedListener != null) {
+                mClosedListener.onGutsClosed(this);
             }
             return;
         }
@@ -198,8 +208,8 @@
             animateClose(x, y);
         }
         setExposed(false, mNeedsFalsingProtection);
-        if (mListener != null) {
-            mListener.onGutsClosed(this);
+        if (mClosedListener != null) {
+            mClosedListener.onGutsClosed(this);
         }
     }
 
@@ -234,6 +244,10 @@
         return mActualHeight;
     }
 
+    public int getIntrinsicHeight() {
+        return mGutsContent != null && mExposed ? mGutsContent.getActualHeight() : getHeight();
+    }
+
     public void setClipTopAmount(int clipTopAmount) {
         mClipTopAmount = clipTopAmount;
         invalidate();
@@ -251,10 +265,21 @@
     }
 
     public void setClosedListener(OnGutsClosedListener listener) {
-        mListener = listener;
+        mClosedListener = listener;
+    }
+
+    public void setHeightChangedListener(OnHeightChangedListener listener) {
+        mHeightListener = listener;
+    }
+
+    protected void onHeightChanged() {
+        if (mHeightListener != null) {
+            mHeightListener.onHeightChanged(this);
+        }
     }
 
     public void setExposed(boolean exposed, boolean needsFalsingProtection) {
+        final boolean wasExposed = mExposed;
         mExposed = exposed;
         mNeedsFalsingProtection = needsFalsingProtection;
         if (mExposed && mNeedsFalsingProtection) {
@@ -262,6 +287,13 @@
         } else {
             mHandler.removeCallbacks(mFalsingCheck);
         }
+        if (wasExposed != mExposed && mGutsContent != null) {
+            final View contentView = mGutsContent.getContentView();
+            contentView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+            if (mExposed) {
+                contentView.requestAccessibilityFocus();
+            }
+        }
     }
 
     public boolean willBeRemoved() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index fab4e59..f3c7b84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -35,6 +35,7 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.Switch;
@@ -57,6 +58,7 @@
 
     private INotificationManager mINotificationManager;
     private String mPkg;
+    private String mAppName;
     private int mAppUid;
     private List<NotificationChannel> mNotificationChannels;
     private NotificationChannel mSingleNotificationChannel;
@@ -125,7 +127,7 @@
             }
         }
 
-        String appName = mPkg;
+        mAppName = mPkg;
         Drawable pkgicon = null;
         CharSequence channelNameText = "";
         ApplicationInfo info = null;
@@ -137,7 +139,7 @@
                             | PackageManager.MATCH_DIRECT_BOOT_AWARE);
             if (info != null) {
                 mAppUid = info.uid;
-                appName = String.valueOf(pm.getApplicationLabel(info));
+                mAppName = String.valueOf(pm.getApplicationLabel(info));
                 pkgicon = pm.getApplicationIcon(info);
             }
         } catch (PackageManager.NameNotFoundException e) {
@@ -151,7 +153,7 @@
                 pkg, mAppUid, false /* includeDeleted */);
 
         String channelsDescText;
-        mNumChannelsView = (TextView) (findViewById(R.id.num_channels_desc));
+        mNumChannelsView = findViewById(R.id.num_channels_desc);
         if (isSingleDefaultChannel) {
             channelsDescText = mContext.getString(R.string.notification_default_channel_desc);
         } else {
@@ -189,7 +191,7 @@
         } else {
             channelNameText = mSingleNotificationChannel.getName();
         }
-        ((TextView) findViewById(R.id.pkgname)).setText(appName);
+        ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
         ((TextView) findViewById(R.id.channel_name)).setText(channelNameText);
 
         // Set group information if this channel has an associated group.
@@ -309,6 +311,21 @@
         });
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        if (mGutsContainer != null &&
+                event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+            if (mGutsContainer.isExposed()) {
+                event.getText().add(mContext.getString(
+                        R.string.notification_channel_controls_opened_accessibility, mAppName));
+            } else {
+                event.getText().add(mContext.getString(
+                        R.string.notification_channel_controls_closed_accessibility, mAppName));
+            }
+        }
+    }
+
     private void updateSecondaryText() {
         final boolean disabled = mSingleNotificationChannel != null &&
                 getSelectedImportance() == IMPORTANCE_NONE;
@@ -386,4 +403,9 @@
         }
         return false;
     }
+
+    @Override
+    public int getActualHeight() {
+        return getHeight();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 2a1e063..7563fd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -227,6 +227,7 @@
                 if (mShouldShowMenu
                         && !NotificationStackScrollLayout.isPinnedHeadsUp(view)
                         && !mParent.areGutsExposed()
+                        && !mParent.isDark()
                         && (mCheckForDrag == null || !mHandler.hasCallbacks(mCheckForDrag))) {
                     // Only show the menu if we're not a heads up view and guts aren't exposed.
                     mCheckForDrag = new CheckForDrag();
@@ -306,12 +307,20 @@
     }
 
     private void snapBack(View animView, float velocity) {
+        if (mFadeAnimator != null) {
+            mFadeAnimator.cancel();
+        }
+        mHandler.removeCallbacks(mCheckForDrag);
         mMenuSnappedTo = false;
         mSnapping = true;
         mSwipeHelper.snap(animView, 0 /* leftTarget */, velocity);
     }
 
     private void dismiss(View animView, float velocity) {
+        if (mFadeAnimator != null) {
+            mFadeAnimator.cancel();
+        }
+        mHandler.removeCallbacks(mCheckForDrag);
         mMenuSnappedTo = false;
         mDismissing = true;
         mSwipeHelper.dismiss(animView, velocity);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 51345c2..b134fc5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -79,7 +79,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mShelfIcons = (NotificationIconContainer) findViewById(R.id.content);
+        mShelfIcons = findViewById(R.id.content);
         mShelfIcons.setClipChildren(false);
         mShelfIcons.setClipToPadding(false);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
index 0de3e02..ccc99c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
@@ -21,35 +21,47 @@
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
 
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.Resources;
-import android.graphics.Color;
+import android.graphics.Typeface;
 import android.service.notification.SnoozeCriterion;
 import android.service.notification.StatusBarNotification;
+import android.text.SpannableString;
+import android.text.style.StyleSpan;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.TypedValue;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
+
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 
 public class NotificationSnooze extends LinearLayout
         implements NotificationGuts.GutsContent, View.OnClickListener {
 
-    private static final int MAX_ASSISTANT_SUGGESTIONS = 2;
+    private static final int MAX_ASSISTANT_SUGGESTIONS = 1;
     private NotificationGuts mGutsContainer;
     private NotificationSwipeActionHelper mSnoozeListener;
     private StatusBarNotification mSbn;
 
     private TextView mSelectedOptionText;
     private TextView mUndoButton;
-    private ViewGroup mSnoozeOptionView;
+    private ImageView mExpandButton;
+    private View mDivider;
+    private ViewGroup mSnoozeOptionContainer;
     private List<SnoozeOption> mSnoozeOptions;
-    private boolean mSnoozing;
+    private int mCollapsedHeight;
 
     private SnoozeOption mSelectedOption;
+    private boolean mSnoozing;
+    private boolean mExpanded;
+    private AnimatorSet mExpandAnimation;
 
     public NotificationSnooze(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -58,16 +70,21 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.snooze_snackbar_min_height);
+        findViewById(R.id.notification_snooze).setOnClickListener(this);
+        mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
+        mUndoButton = (TextView) findViewById(R.id.undo);
+        mUndoButton.setOnClickListener(this);
+        mExpandButton = (ImageView) findViewById(R.id.expand_button);
+        mDivider = findViewById(R.id.divider);
+        mDivider.setAlpha(0f);
+        mSnoozeOptionContainer = (ViewGroup) findViewById(R.id.snooze_options);
+        mSnoozeOptionContainer.setAlpha(0f);
+
         // Create the different options based on list
         mSnoozeOptions = getDefaultSnoozeOptions();
         createOptionViews();
 
-        // Snackbar
-        mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
-        mSelectedOptionText.setOnClickListener(this);
-        mUndoButton = (TextView) findViewById(R.id.undo);
-        mUndoButton.setOnClickListener(this);
-
         // Default to first option in list
         setSelected(mSnoozeOptions.get(0));
     }
@@ -96,52 +113,68 @@
 
     private SnoozeOption createOption(int descriptionResId, int minutes) {
         Resources res = getResources();
-        String resultText = String.format(
-                res.getString(R.string.snoozed_for_time), res.getString(descriptionResId));
-        return new SnoozeOption(null, minutes, res.getString(descriptionResId), resultText);
+        final String description = res.getString(descriptionResId);
+        String resultText = String.format(res.getString(R.string.snoozed_for_time), description);
+        SpannableString string = new SpannableString(resultText);
+        string.setSpan(new StyleSpan(Typeface.BOLD),
+                resultText.length() - description.length(), resultText.length(), 0 /* flags */);
+        return new SnoozeOption(null, minutes, res.getString(descriptionResId), string);
     }
 
     private void createOptionViews() {
-        mSnoozeOptionView = (ViewGroup) findViewById(R.id.snooze_options);
-        mSnoozeOptionView.removeAllViews();
-        mSnoozeOptionView.setVisibility(View.GONE);
-        final Resources res = getResources();
-        final int textSize = res.getDimensionPixelSize(R.dimen.snooze_option_text_size);
-        final int p = res.getDimensionPixelSize(R.dimen.snooze_option_padding);
-
-        // Add all the options
+        mSnoozeOptionContainer.removeAllViews();
+        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
         for (int i = 0; i < mSnoozeOptions.size(); i++) {
             SnoozeOption option = mSnoozeOptions.get(i);
-            TextView tv = new TextView(getContext());
-            tv.setTextColor(Color.WHITE);
-            tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
-            tv.setPadding(p, p, p, p);
-            mSnoozeOptionView.addView(tv);
+            TextView tv = (TextView) inflater.inflate(R.layout.notification_snooze_option,
+                    mSnoozeOptionContainer, false);
+            mSnoozeOptionContainer.addView(tv);
             tv.setText(option.description);
             tv.setTag(option);
             tv.setOnClickListener(this);
         }
+    }
 
-        // Add the undo option as final item
-        TextView tv = new TextView(getContext());
-        tv.setTextColor(Color.WHITE);
-        tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
-        tv.setPadding(p, p, p, p);
-        mSnoozeOptionView.addView(tv);
-        tv.setText(R.string.snooze_option_dont_snooze);
-        tv.setOnClickListener(this);
+    private void hideSelectedOption() {
+        final int childCount = mSnoozeOptionContainer.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = mSnoozeOptionContainer.getChildAt(i);
+            child.setVisibility(child.getTag() == mSelectedOption ? View.GONE : View.VISIBLE);
+        }
     }
 
     private void showSnoozeOptions(boolean show) {
-        mSelectedOptionText.setVisibility(show ? View.GONE : View.VISIBLE);
-        mUndoButton.setVisibility(show ? View.GONE : View.VISIBLE);
-        mSnoozeOptionView.setVisibility(show ? View.VISIBLE : View.GONE);
+        mExpanded = show;
+        animateSnoozeOptions(show);
+        int drawableId = show ? com.android.internal.R.drawable.ic_collapse_notification
+                : com.android.internal.R.drawable.ic_expand_notification;
+        mExpandButton.setImageResource(drawableId);
+        if (mGutsContainer != null) {
+            mGutsContainer.onHeightChanged();
+        }
+    }
+
+    private void animateSnoozeOptions(boolean show) {
+        if (mExpandAnimation != null) {
+            mExpandAnimation.cancel();
+        }
+        ObjectAnimator dividerAnim = ObjectAnimator.ofFloat(mDivider, View.ALPHA,
+                mDivider.getAlpha(), show ? 1f : 0f);
+        ObjectAnimator optionAnim = ObjectAnimator.ofFloat(mSnoozeOptionContainer, View.ALPHA,
+                mSnoozeOptionContainer.getAlpha(), show ? 1f : 0f);
+        mExpandAnimation = new AnimatorSet();
+        mExpandAnimation.playTogether(dividerAnim, optionAnim);
+        mExpandAnimation.setDuration(150);
+        mExpandAnimation.setInterpolator(show ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+        mExpandAnimation.start();
     }
 
     private void setSelected(SnoozeOption option) {
         mSelectedOption = option;
         mSelectedOptionText.setText(option.confirmation);
         showSnoozeOptions(false);
+        hideSelectedOption();
     }
 
     @Override
@@ -153,17 +186,28 @@
         final SnoozeOption tag = (SnoozeOption) v.getTag();
         if (tag != null) {
             setSelected(tag);
-        } else if (id == R.id.snooze_option_default) {
-            // Show more snooze options
-            showSnoozeOptions(true);
+        } else if (id == R.id.notification_snooze) {
+            // Toggle snooze options
+            showSnoozeOptions(!mExpanded);
         } else {
-            undoSnooze();
+            // Undo snooze was selected
+            mSelectedOption = null;
+            int[] parentLoc = new int[2];
+            int[] targetLoc = new int[2];
+            mGutsContainer.getLocationOnScreen(parentLoc);
+            v.getLocationOnScreen(targetLoc);
+            final int centerX = v.getWidth() / 2;
+            final int centerY = v.getHeight() / 2;
+            final int x = targetLoc[0] - parentLoc[0] + centerX;
+            final int y = targetLoc[1] - parentLoc[1] + centerY;
+            showSnoozeOptions(false);
+            mGutsContainer.closeControls(x, y, false /* save */);
         }
     }
 
-    private void undoSnooze() {
-        mSelectedOption = null;
-        mGutsContainer.closeControls(-1 /* x */, -1 /* y */, true /* notify */);
+    @Override
+    public int getActualHeight() {
+        return mExpanded ? getHeight() : mCollapsedHeight;
     }
 
     @Override
@@ -173,6 +217,8 @@
 
     @Override
     public View getContentView() {
+        // Reset the view before use
+        setSelected(mSnoozeOptions.get(0));
         return this;
     }
 
@@ -197,11 +243,8 @@
             mSnoozing = true;
             mSnoozeListener.snooze(mSbn, mSelectedOption);
             return true;
-        } else {
-            // Reset the view once it's closed
-            setSelected(mSnoozeOptions.get(0));
-            showSnoozeOptions(false);
         }
+        // The view should be closed
         return false;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index c5e1438..b01d9cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -24,8 +24,6 @@
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.Rect;
-import android.graphics.drawable.Animatable;
-import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.telephony.SubscriptionInfo;
@@ -42,6 +40,7 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
@@ -119,6 +118,7 @@
     private boolean mBlockWifi;
     private boolean mBlockEthernet;
     private boolean mActivityEnabled;
+    private boolean mForceBlockWifi;
 
     public SignalClusterView(Context context) {
         this(context, null);
@@ -150,6 +150,16 @@
         updateActivityEnabled();
     }
 
+    public void setForceBlockWifi() {
+        mForceBlockWifi = true;
+        mBlockWifi = true;
+        if (isAttachedToWindow()) {
+            // Re-register to get new callbacks.
+            mNetworkController.removeCallback(this);
+            mNetworkController.addCallback(this);
+        }
+    }
+
     @Override
     public void onTuningChanged(String key, String newValue) {
         if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
@@ -166,7 +176,7 @@
             mBlockAirplane = blockAirplane;
             mBlockMobile = blockMobile;
             mBlockEthernet = blockEthernet;
-            mBlockWifi = blockWifi;
+            mBlockWifi = blockWifi || mForceBlockWifi;
             // Re-register to get new callbacks.
             mNetworkController.removeCallback(this);
             mNetworkController.addCallback(this);
@@ -177,22 +187,22 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mVpn            = (ImageView) findViewById(R.id.vpn);
-        mEthernetGroup  = (ViewGroup) findViewById(R.id.ethernet_combo);
-        mEthernet       = (ImageView) findViewById(R.id.ethernet);
-        mEthernetDark   = (ImageView) findViewById(R.id.ethernet_dark);
-        mWifiGroup      = (ViewGroup) findViewById(R.id.wifi_combo);
-        mWifi           = (ImageView) findViewById(R.id.wifi_signal);
-        mWifiDark       = (ImageView) findViewById(R.id.wifi_signal_dark);
-        mWifiActivityIn = (ImageView) findViewById(R.id.wifi_in);
-        mWifiActivityOut= (ImageView) findViewById(R.id.wifi_out);
-        mAirplane       = (ImageView) findViewById(R.id.airplane);
-        mNoSims         = (ImageView) findViewById(R.id.no_sims);
-        mNoSimsDark     = (ImageView) findViewById(R.id.no_sims_dark);
+        mVpn            = findViewById(R.id.vpn);
+        mEthernetGroup  = findViewById(R.id.ethernet_combo);
+        mEthernet       = findViewById(R.id.ethernet);
+        mEthernetDark   = findViewById(R.id.ethernet_dark);
+        mWifiGroup      = findViewById(R.id.wifi_combo);
+        mWifi           = findViewById(R.id.wifi_signal);
+        mWifiDark       = findViewById(R.id.wifi_signal_dark);
+        mWifiActivityIn = findViewById(R.id.wifi_in);
+        mWifiActivityOut= findViewById(R.id.wifi_out);
+        mAirplane       = findViewById(R.id.airplane);
+        mNoSims         = findViewById(R.id.no_sims);
+        mNoSimsDark     = findViewById(R.id.no_sims_dark);
         mNoSimsCombo    =             findViewById(R.id.no_sims_combo);
         mWifiAirplaneSpacer =         findViewById(R.id.wifi_airplane_spacer);
         mWifiSignalSpacer =           findViewById(R.id.wifi_signal_spacer);
-        mMobileSignalGroup = (LinearLayout) findViewById(R.id.mobile_signal_group);
+        mMobileSignalGroup =          findViewById(R.id.mobile_signal_group);
 
         maybeScaleVpnAndNoSimsIcons();
     }
@@ -287,9 +297,9 @@
     }
 
     @Override
-    public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-            int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-            String description, boolean isWide, int subId, boolean roaming) {
+    public void setMobileDataIndicators(IconState statusIcon, int statusType,
+            boolean activityIn, boolean activityOut, String typeContentDescription,
+            int subId, boolean roaming, boolean isEmergency) {
         PhoneState state = getState(subId);
         if (state == null) {
             return;
@@ -299,7 +309,6 @@
         state.mMobileTypeId = statusType;
         state.mMobileDescription = statusIcon.contentDescription;
         state.mMobileTypeDescription = typeContentDescription;
-        state.mIsMobileTypeIconWide = statusType != 0 && isWide;
         state.mRoaming = roaming;
         state.mActivityIn = activityIn && mActivityEnabled;
         state.mActivityOut = activityOut && mActivityEnabled;
@@ -327,15 +336,6 @@
         if (hasCorrectSubs(subs)) {
             return;
         }
-        // Clear out all old subIds.
-        for (PhoneState state : mPhoneStates) {
-            if (state.mMobile != null) {
-                state.maybeStopAnimatableDrawable(state.mMobile);
-            }
-            if (state.mMobileDark != null) {
-                state.maybeStopAnimatableDrawable(state.mMobileDark);
-            }
-        }
         mPhoneStates.clear();
         if (mMobileSignalGroup != null) {
             mMobileSignalGroup.removeAllViews();
@@ -428,16 +428,6 @@
         }
 
         for (PhoneState state : mPhoneStates) {
-            if (state.mMobile != null) {
-                state.maybeStopAnimatableDrawable(state.mMobile);
-                state.mMobile.setImageDrawable(null);
-                state.mLastMobileStrengthId = -1;
-            }
-            if (state.mMobileDark != null) {
-                state.maybeStopAnimatableDrawable(state.mMobileDark);
-                state.mMobileDark.setImageDrawable(null);
-                state.mLastMobileStrengthId = -1;
-            }
             if (state.mMobileType != null) {
                 state.mMobileType.setImageDrawable(null);
                 state.mLastMobileTypeId = -1;
@@ -543,7 +533,7 @@
             mWifiAirplaneSpacer.setVisibility(View.GONE);
         }
 
-        if (((anyMobileVisible && firstMobileTypeId != 0) || mNoSimsVisible) && mWifiVisible) {
+        if (((anyMobileVisible && firstMobileTypeId == 0) || mNoSimsVisible) && mWifiVisible) {
             mWifiSignalSpacer.setVisibility(View.VISIBLE);
         } else {
             mWifiSignalSpacer.setVisibility(View.GONE);
@@ -654,8 +644,6 @@
         private int mMobileStrengthId = 0, mMobileTypeId = 0;
         private int mLastMobileStrengthId = -1;
         private int mLastMobileTypeId = -1;
-        private int mLastMobileActivityId = -1;
-        private boolean mIsMobileTypeIconWide;
         private String mMobileDescription, mMobileTypeDescription;
 
         private ViewGroup mMobileGroup;
@@ -681,13 +669,18 @@
             mMobileRoaming  = root.findViewById(R.id.mobile_roaming);
             mMobileActivityIn = root.findViewById(R.id.mobile_in);
             mMobileActivityOut = root.findViewById(R.id.mobile_out);
+            // TODO: Remove the 2 instances because now the drawable can handle darkness.
+            mMobile.setImageDrawable(new SignalDrawable(mMobile.getContext()));
+            SignalDrawable drawable = new SignalDrawable(mMobileDark.getContext());
+            drawable.setDarkIntensity(1);
+            mMobileDark.setImageDrawable(drawable);
         }
 
         public boolean apply(boolean isSecondaryIcon) {
             if (mMobileVisible && !mIsAirplaneMode) {
                 if (mLastMobileStrengthId != mMobileStrengthId) {
-                    updateAnimatableIcon(mMobile, mMobileStrengthId);
-                    updateAnimatableIcon(mMobileDark, mMobileStrengthId);
+                    mMobile.getDrawable().setLevel(mMobileStrengthId);
+                    mMobileDark.getDrawable().setLevel(mMobileStrengthId);
                     mLastMobileStrengthId = mMobileStrengthId;
                 }
 
@@ -706,12 +699,8 @@
             // When this isn't next to wifi, give it some extra padding between the signals.
             mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0,
                     0, 0, 0);
-            mMobile.setPaddingRelative(
-                    mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
-                    0, 0, 0);
-            mMobileDark.setPaddingRelative(
-                    mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
-                    0, 0, 0);
+            mMobile.setPaddingRelative(mMobileDataIconStartPadding, 0, 0, 0);
+            mMobileDark.setPaddingRelative(mMobileDataIconStartPadding, 0, 0, 0);
 
             if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d",
                         (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId));
@@ -724,49 +713,6 @@
             return mMobileVisible;
         }
 
-        private void updateAnimatableIcon(ImageView view, int resId) {
-            maybeStopAnimatableDrawable(view);
-            setIconForView(view, resId);
-            maybeStartAnimatableDrawable(view);
-        }
-
-        private void maybeStopAnimatableDrawable(ImageView view) {
-            Drawable drawable = view.getDrawable();
-
-            // Check if the icon has been scaled. If it has retrieve the actual drawable out of the
-            // wrapper.
-            if (drawable instanceof ScalingDrawableWrapper) {
-                drawable = ((ScalingDrawableWrapper) drawable).getDrawable();
-            }
-
-            if (drawable instanceof Animatable) {
-                Animatable ad = (Animatable) drawable;
-                if (ad.isRunning()) {
-                    ad.stop();
-                }
-            }
-        }
-
-        private void maybeStartAnimatableDrawable(ImageView view) {
-            Drawable drawable = view.getDrawable();
-
-            // Check if the icon has been scaled. If it has retrieve the actual drawable out of the
-            // wrapper.
-            if (drawable instanceof ScalingDrawableWrapper) {
-                drawable = ((ScalingDrawableWrapper) drawable).getDrawable();
-            }
-
-            if (drawable instanceof Animatable) {
-                Animatable ad = (Animatable) drawable;
-                if (ad instanceof AnimatedVectorDrawable) {
-                    ((AnimatedVectorDrawable) ad).forceAnimationOnUI();
-                }
-                if (!ad.isRunning()) {
-                    ad.start();
-                }
-            }
-        }
-
         public void populateAccessibilityEvent(AccessibilityEvent event) {
             if (mMobileVisible && mMobileGroup != null
                     && mMobileGroup.getContentDescription() != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 92bfae9..ec15d10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -499,12 +499,18 @@
     }
 
     private void setColorInternal(int color) {
-        if (color != NO_COLOR) {
-            setImageTintList(ColorStateList.valueOf(color));
+        mCurrentSetColor = color;
+        updateIconColor();
+    }
+
+    private void updateIconColor() {
+        if (mCurrentSetColor != NO_COLOR) {
+            setImageTintList(ColorStateList.valueOf(NotificationUtils.interpolateColors(
+                    mCurrentSetColor, Color.WHITE, mDarkAmount)));
         } else {
             setImageTintList(null);
+            mDozer.updateGrayscale(this, mDarkAmount);
         }
-        mCurrentSetColor = color;
     }
 
     public void setIconColor(int iconColor, boolean animate) {
@@ -669,10 +675,10 @@
     }
 
     public void setDark(boolean dark, boolean fade, long delay) {
-        mDozer.setImageDark(this, dark, fade, delay, mIconColor == NO_COLOR);
         mDozer.setIntensityDark(f -> {
             mDarkAmount = f;
             updateDecorColor();
+            updateIconColor();
         }, dark, fade, delay);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index d530759..6cbbd6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -40,8 +40,8 @@
 
     @Override
     public void onFinishInflate() {
-        mNavButtons = (LinearLayout) findViewById(R.id.nav_buttons);
-        mLightsOutButtons = (LinearLayout) findViewById(R.id.lights_out);
+        mNavButtons = findViewById(R.id.nav_buttons);
+        mLightsOutButtons = findViewById(R.id.lights_out);
     }
 
     public void addButton(CarNavigationButton button, CarNavigationButton lightsOutButton){
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index f46fc67..2de358f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -41,13 +41,13 @@
     @Override
     public void onFinishInflate() {
         super.onFinishInflate();
-        mIcon = (AlphaOptimizedImageButton) findViewById(R.id.car_nav_button_icon);
+        mIcon = findViewById(R.id.car_nav_button_icon);
         mIcon.setScaleType(ImageView.ScaleType.CENTER);
         mIcon.setClickable(false);
         mIcon.setBackgroundColor(android.R.color.transparent);
         mIcon.setAlpha(UNSELECTED_ALPHA);
 
-        mMoreIcon = (AlphaOptimizedImageButton) findViewById(R.id.car_nav_button_more_icon);
+        mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
         mMoreIcon.setClickable(false);
         mMoreIcon.setBackgroundColor(android.R.color.transparent);
         mMoreIcon.setVisibility(INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index 67f8426..677fa81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -11,6 +11,7 @@
 import android.content.IntentFilter;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.telephony.SignalStrength;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.View;
@@ -18,6 +19,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
+import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
@@ -47,12 +49,12 @@
      * Note that the icon is the same for 0 and 1.
      */
     private static final int[] SIGNAL_STRENGTH_ICONS = {
-            R.drawable.stat_sys_signal_0_fully,
-            R.drawable.stat_sys_signal_0_fully,
-            R.drawable.stat_sys_signal_1_fully,
-            R.drawable.stat_sys_signal_2_fully,
-            R.drawable.stat_sys_signal_3_fully,
-            R.drawable.stat_sys_signal_4_fully,
+            0,
+            0,
+            1,
+            2,
+            3,
+            4,
     };
 
     private static final int INVALID_SIGNAL = -1;
@@ -65,6 +67,7 @@
     private final ImageView mNetworkSignalView;
 
     private final float mIconScaleFactor;
+    private final SignalDrawable mSignalDrawable;
 
     private BluetoothHeadsetClient mBluetoothHeadsetClient;
 
@@ -79,6 +82,9 @@
         TypedValue typedValue = new TypedValue();
         context.getResources().getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
         mIconScaleFactor = typedValue.getFloat();
+        mSignalDrawable = new SignalDrawable(mNetworkSignalView.getContext());
+        mNetworkSignalView.setImageDrawable(
+                new ScalingDrawableWrapper(mSignalDrawable, mIconScaleFactor));
 
         if (mAdapter == null) {
           return;
@@ -187,14 +193,12 @@
         }
     }
 
-    private void setNetworkSignalIcon(int iconId) {
+    private void setNetworkSignalIcon(int level) {
         // Setting the icon on a child view of mSignalView, so toggle this container visible.
         mSignalsView.setVisibility(View.VISIBLE);
 
-        // Using mNetworkSignalView's context to get the Drawable in order to preserve the theme.
-        Drawable icon = mNetworkSignalView.getContext().getDrawable(iconId);
-
-        mNetworkSignalView.setImageDrawable(new ScalingDrawableWrapper(icon, mIconScaleFactor));
+        mSignalDrawable.setLevel(SignalDrawable.getState(level,
+                SignalStrength.NUM_SIGNAL_STRENGTH_BINS, false));
         mNetworkSignalView.setVisibility(View.VISIBLE);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
index d592c5f..0b3b3cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
@@ -35,8 +35,7 @@
         startIntensityAnimation(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
-                updateGrayscaleMatrix((float) animation.getAnimatedValue());
-                target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
+                updateGrayscale(target, (float) animation.getAnimatedValue());
             }
         }, dark, delay, new AnimatorListenerAdapter() {
             @Override
@@ -49,8 +48,12 @@
     }
 
     public void updateGrayscale(ImageView target, boolean dark) {
-        if (dark) {
-            updateGrayscaleMatrix(1f);
+        updateGrayscale(target, dark ? 1 : 0);
+    }
+
+    public void updateGrayscale(ImageView target, float darkAmount) {
+        if (darkAmount > 0) {
+            updateGrayscaleMatrix(darkAmount);
             target.setColorFilter(new ColorMatrixColorFilter(mGrayscaleColorMatrix));
         } else {
             target.setColorFilter(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
index 73eecbb..2e34f24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
@@ -21,6 +21,8 @@
 import android.service.notification.StatusBarNotification;
 import android.util.Log;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
 import android.widget.RemoteViews;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -49,6 +51,7 @@
     private RemoteViews.OnClickHandler mRemoteViewClickHandler;
     private boolean mIsChildInGroup;
     private InflationExceptionHandler mInflateExceptionHandler;
+    private boolean mRedactAmbient;
 
     public NotificationInflater(ExpandableNotificationRow row) {
         mRow = row;
@@ -92,6 +95,21 @@
         mRemoteViewClickHandler = remoteViewClickHandler;
     }
 
+    public void setRedactAmbient(boolean redactAmbient) {
+        if (mRedactAmbient != redactAmbient) {
+            mRedactAmbient = redactAmbient;
+            if (mRow.getEntry() == null) {
+                return;
+            }
+            try {
+                inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW);
+            } catch (InflationException e) {
+                mInflateExceptionHandler.handleInflationException(
+                        mRow.getStatusBarNotification(), e);
+            }
+        }
+    }
+
     public void inflateNotificationViews() throws InflationException {
         inflateNotificationViews(FLAG_REINFLATE_ALL);
     }
@@ -123,6 +141,8 @@
             Notification.Builder builder, Context packageContext) {
         NotificationData.Entry entry = mRow.getEntry();
         NotificationContentView privateLayout = mRow.getPrivateLayout();
+        NotificationContentView publicLayout = mRow.getPublicLayout();
+
         boolean isLowPriority = mIsLowPriority && !mIsChildInGroup;
         if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
             final RemoteViews newContentView = createContentView(builder,
@@ -190,7 +210,6 @@
         }
 
         if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
-            NotificationContentView publicLayout = mRow.getPublicLayout();
             final RemoteViews newPublicNotification
                     = builder.makePublicContentView();
             if (!compareRemoteViews(newPublicNotification, entry.cachedPublicContentView)) {
@@ -209,18 +228,24 @@
         }
 
         if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
-            final RemoteViews newAmbientNotification
-                    = builder.makeAmbientNotification();
-            if (!compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) {
+            final RemoteViews newAmbientNotification = mRedactAmbient
+                    ? builder.makePublicAmbientNotification()
+                    : builder.makeAmbientNotification();
+            NotificationContentView newParent = mRedactAmbient ? publicLayout : privateLayout;
+            NotificationContentView otherParent = !mRedactAmbient ? publicLayout : privateLayout;
+
+            if (newParent.getAmbientChild() == null ||
+                    !compareRemoteViews(newAmbientNotification, entry.cachedAmbientContentView)) {
                 View ambientContentView = newAmbientNotification.apply(
                         packageContext,
-                        privateLayout,
+                        newParent,
                         mRemoteViewClickHandler);
                 ambientContentView.setIsRootNamespace(true);
-                privateLayout.setAmbientChild(ambientContentView);
+                newParent.setAmbientChild(ambientContentView);
+                otherParent.setAmbientChild(null);
             } else {
                 newAmbientNotification.reapply(packageContext,
-                        privateLayout.getAmbientChild(),
+                        newParent.getAmbientChild(),
                         mRemoteViewClickHandler);
             }
             entry.cachedAmbientContentView = newAmbientNotification;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index be16266..dd99749 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -23,6 +23,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.widget.LinearLayout;
 
 import com.android.systemui.Dependency;
@@ -36,6 +37,7 @@
 import com.android.systemui.statusbar.policy.EncryptionHelper;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 /**
  * Contains the collapsed status bar and handles hiding/showing based on disable flags
@@ -56,6 +58,13 @@
     private DarkIconManager mDarkIconManager;
     private SignalClusterView mSignalClusterView;
 
+    private SignalCallback mSignalCallback = new SignalCallback() {
+        @Override
+        public void setIsAirplaneMode(NetworkController.IconState icon) {
+            mStatusBarComponent.recomputeDisableFlags(true /* animate */);
+        }
+    };
+
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -84,6 +93,7 @@
         Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView);
         // Default to showing until we know otherwise.
         showSystemIconArea(false);
+        initEmergencyCryptkeeperText();
     }
 
     @Override
@@ -109,6 +119,9 @@
         super.onDestroyView();
         Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSignalClusterView);
         Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
+        if (mNetworkController.hasEmergencyCryptKeeperText()) {
+            mNetworkController.removeCallback(mSignalCallback);
+        }
     }
 
     public void initNotificationIconArea(NotificationIconAreaController
@@ -233,4 +246,17 @@
                     .start();
         }
     }
+
+    private void initEmergencyCryptkeeperText() {
+        View emergencyViewStub = mStatusBar.findViewById(R.id.emergency_cryptkeeper_text);
+        if (mNetworkController.hasEmergencyCryptKeeperText()) {
+            if (emergencyViewStub != null) {
+                ((ViewStub) emergencyViewStub).inflate();
+            }
+            mNetworkController.addCallback(mSignalCallback);
+        } else if (emergencyViewStub != null) {
+            ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
+            parent.removeView(emergencyViewStub);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index a444934..c499619 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -81,7 +81,7 @@
             }
             String location = args.getString("location");
             if (location != null) {
-                int iconId = location.equals("show") ? LocationControllerImpl.LOCATION_STATUS_ICON_ID
+                int iconId = location.equals("show") ? PhoneStatusBarPolicy.LOCATION_STATUS_ICON_ID
                         : 0;
                 updateSlot("location", null, iconId);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index bdeab21..18e1d82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -162,6 +162,10 @@
         return sPickupSubtypePerformsProxMatcher.isIn(subType);
     }
 
+    public int getPulseVisibleDurationExtended() {
+        return 2 * getPulseVisibleDuration();
+    }
+
 
     /**
      * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index b78f748..c5f23c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -30,6 +30,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
+import com.android.systemui.doze.DozeTriggers;
 
 /**
  * Controller which handles all the doze animations of the scrims.
@@ -43,8 +44,6 @@
     private final ScrimController mScrimController;
 
     private final Context mContext;
-    private final View mStackScroller;
-    private final NotificationPanelView mNotificationPanelView;
 
     private boolean mDozing;
     private DozeHost.PulseCallback mPulseCallback;
@@ -53,24 +52,22 @@
     private Animator mBehindAnimator;
     private float mInFrontTarget;
     private float mBehindTarget;
+    private boolean mDozingAborted;
 
-    public DozeScrimController(ScrimController scrimController, Context context,
-            View stackScroller, NotificationPanelView notificationPanelView) {
+    public DozeScrimController(ScrimController scrimController, Context context) {
         mContext = context;
-        mStackScroller = stackScroller;
         mScrimController = scrimController;
         mDozeParameters = new DozeParameters(context);
-        mNotificationPanelView = notificationPanelView;
     }
 
     public void setDozing(boolean dozing, boolean animate) {
         if (mDozing == dozing) return;
         mDozing = dozing;
         if (mDozing) {
+            mDozingAborted = false;
             abortAnimations();
             mScrimController.setDozeBehindAlpha(1f);
             mScrimController.setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() ? 0f : 1f);
-            mNotificationPanelView.setDark(true);
         } else {
             cancelPulsing();
             if (animate) {
@@ -85,8 +82,6 @@
                 mScrimController.setDozeBehindAlpha(0f);
                 mScrimController.setDozeInFrontAlpha(0f);
             }
-            // TODO: animate
-            mNotificationPanelView.setDark(false);
         }
     }
 
@@ -116,10 +111,19 @@
         cancelPulsing();
         if (mDozing) {
             mScrimController.setDozeBehindAlpha(1f);
-            mScrimController.setDozeInFrontAlpha(1f);
+            mScrimController.setDozeInFrontAlpha(
+                    mDozeParameters.getAlwaysOn() && !mDozingAborted ? 0f : 1f);
         }
     }
 
+    /**
+     * Aborts dozing immediately.
+     */
+    public void abortDoze() {
+        mDozingAborted = true;
+        abortPulsing();
+    }
+
     public void onScreenTurnedOn() {
         if (isPulsing()) {
             final boolean pickupOrDoubleTap = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP
@@ -139,12 +143,17 @@
         return mDozing;
     }
 
+    public void extendPulse() {
+        mHandler.removeCallbacks(mPulseOut);
+    }
+
     private void cancelPulsing() {
         if (DEBUG) Log.d(TAG, "Cancel pulsing");
 
         if (mPulseCallback != null) {
             mHandler.removeCallbacks(mPulseIn);
             mHandler.removeCallbacks(mPulseOut);
+            mHandler.removeCallbacks(mPulseOutExtended);
             pulseFinished();
         }
     }
@@ -271,12 +280,23 @@
             if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
             if (!mDozing) return;
             mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
+            mHandler.postDelayed(mPulseOutExtended,
+                    mDozeParameters.getPulseVisibleDurationExtended());
+        }
+    };
+
+    private final Runnable mPulseOutExtended = new Runnable() {
+        @Override
+        public void run() {
+            mHandler.removeCallbacks(mPulseOut);
+            mPulseOut.run();
         }
     };
 
     private final Runnable mPulseOut = new Runnable() {
         @Override
         public void run() {
+            mHandler.removeCallbacks(mPulseOutExtended);
             if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
             if (!mDozing) return;
             startScrimAnimation(true /* inFront */, mDozeParameters.getAlwaysOn() ? 0 : 1,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 2bb3cbc..9206914 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -221,7 +221,7 @@
             case MODE_WAKE_AND_UNLOCK:
                 Trace.beginSection("MODE_WAKE_AND_UNLOCK");
                 mStatusBarWindowManager.setStatusBarFocusable(false);
-                mDozeScrimController.abortPulsing();
+                mDozeScrimController.abortDoze();
                 mKeyguardViewMediator.onWakeAndUnlocking();
                 mScrimController.setWakeAndUnlocking();
                 if (mStatusBar.getNavigationBarView() != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 9a49d67..41a60e24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -227,14 +227,14 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mLockPatternUtils = new LockPatternUtils(mContext);
-        mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container);
-        mRightAffordanceView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
-        mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button);
-        mLockIcon = (LockIcon) findViewById(R.id.lock_icon);
-        mIndicationArea = (ViewGroup) findViewById(R.id.keyguard_indication_area);
-        mEnterpriseDisclosure = (TextView) findViewById(
+        mPreviewContainer = findViewById(R.id.preview_container);
+        mRightAffordanceView = findViewById(R.id.camera_button);
+        mLeftAffordanceView = findViewById(R.id.left_button);
+        mLockIcon = findViewById(R.id.lock_icon);
+        mIndicationArea = findViewById(R.id.keyguard_indication_area);
+        mEnterpriseDisclosure = findViewById(
                 R.id.keyguard_indication_enterprise_disclosure);
-        mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
+        mIndicationText = findViewById(R.id.keyguard_indication_text);
         watchForCameraPolicyChanges();
         updateCameraVisibility();
         mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index fa404b5..4bfc16b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -402,7 +402,7 @@
         ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
         accessibilityButton.setOnClickListener(this::onAccessibilityClick);
         accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
-        updateAccessibilityServicesState();
+        updateAccessibilityServicesState(mAccessibilityManager);
     }
 
     private boolean onHomeTouch(View v, MotionEvent event) {
@@ -565,7 +565,7 @@
         return true;
     }
 
-    private void updateAccessibilityServicesState() {
+    private void updateAccessibilityServicesState(AccessibilityManager accessibilityManager) {
         int requestingServices = 0;
         try {
             if (Settings.Secure.getIntForUser(mContentResolver,
@@ -579,7 +579,7 @@
         // AccessibilityManagerService resolves services for the current user since the local
         // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission
         final List<AccessibilityServiceInfo> services =
-                mAccessibilityManager.getEnabledAccessibilityServiceList(
+                accessibilityManager.getEnabledAccessibilityServiceList(
                         AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
         for (int i = services.size() - 1; i >= 0; --i) {
             AccessibilityServiceInfo info = services.get(i);
@@ -638,7 +638,7 @@
 
         @Override
         public void onChange(boolean selfChange) {
-            NavigationBarFragment.this.updateAccessibilityServicesState();
+            NavigationBarFragment.this.updateAccessibilityServicesState(mAccessibilityManager);
         }
     }
 
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 307a8c7..f1b4498 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -231,9 +231,9 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mKeyguardStatusBar = (KeyguardStatusBarView) findViewById(R.id.keyguard_header);
-        mKeyguardStatusView = (KeyguardStatusView) findViewById(R.id.keyguard_status_view);
-        mClockView = (TextView) findViewById(R.id.clock_view);
+        mKeyguardStatusBar = findViewById(R.id.keyguard_header);
+        mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
+        mClockView = findViewById(R.id.clock_view);
 
         mNotificationContainerParent = (NotificationsQuickSettingsContainer)
                 findViewById(R.id.notification_container_parent);
@@ -242,13 +242,13 @@
         mNotificationStackScroller.setOnHeightChangedListener(this);
         mNotificationStackScroller.setOverscrollTopChangedListener(this);
         mNotificationStackScroller.setOnEmptySpaceClickListener(this);
-        mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
+        mKeyguardBottomArea = findViewById(R.id.keyguard_bottom_area);
         mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
         mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext());
         mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
         mLastOrientation = getResources().getConfiguration().orientation;
 
-        mQsFrame = (FrameLayout) findViewById(R.id.qs_frame);
+        mQsFrame = findViewById(R.id.qs_frame);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 53ec8c5..5910557 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -73,6 +73,8 @@
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.RotationLockController;
 import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
@@ -86,11 +88,13 @@
  * strictly doesn't need to.
  */
 public class PhoneStatusBarPolicy implements Callback, Callbacks,
-        RotationLockControllerCallback, Listener,
+        RotationLockControllerCallback, Listener, LocationChangeCallback,
         ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
     private static final String TAG = "PhoneStatusBarPolicy";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
+    public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
+
     private final String mSlotCast;
     private final String mSlotHotspot;
     private final String mSlotBluetooth;
@@ -102,6 +106,7 @@
     private final String mSlotRotate;
     private final String mSlotHeadset;
     private final String mSlotDataSaver;
+    private final String mSlotLocation;
 
     private final Context mContext;
     private final Handler mHandler = new Handler();
@@ -117,6 +122,7 @@
     private final ZenModeController mZenController;
     private final DeviceProvisionedController mProvisionedController;
     private final KeyguardMonitor mKeyguardMonitor;
+    private final LocationController mLocationController;
     private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
@@ -147,6 +153,7 @@
         mZenController = Dependency.get(ZenModeController.class);
         mProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+        mLocationController = Dependency.get(LocationController.class);
 
         mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
         mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -160,7 +167,7 @@
         mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate);
         mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
         mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
-
+        mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
 
         // listen for broadcasts
         IntentFilter filter = new IntentFilter();
@@ -229,6 +236,7 @@
         mNextAlarm.addCallback(mNextAlarmCallback);
         mDataSaver.addCallback(this);
         mKeyguardMonitor.addCallback(this);
+        mLocationController.addCallback(this);
 
         SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
         SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskListener);
@@ -252,6 +260,7 @@
         mNextAlarm.removeCallback(mNextAlarmCallback);
         mDataSaver.removeCallback(this);
         mKeyguardMonitor.removeCallback(this);
+        mLocationController.removeCallback(this);
         SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
         mContext.unregisterReceiver(mIntentReceiver);
 
@@ -265,6 +274,21 @@
         updateVolumeZen();
     }
 
+    @Override
+    public void onLocationActiveChanged(boolean active) {
+        updateLocation();
+    }
+
+    // Updates the status view based on the current state of location requests.
+    private void updateLocation() {
+        if (mLocationController.isLocationActive()) {
+            mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
+                    mContext.getString(R.string.accessibility_location_active));
+        } else {
+            mIconController.removeIcon(mSlotLocation);
+        }
+    }
+
     private void updateAlarm() {
         final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
         final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 4dc593b8..916b603 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -75,7 +75,7 @@
     @Override
     public void onFinishInflate() {
         mBarTransitions.init();
-        mBattery = (DarkReceiver) findViewById(R.id.battery);
+        mBattery = findViewById(R.id.battery);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index dadb749..67d5b6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -57,6 +57,7 @@
     private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target;
     private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
     private static final int TAG_END_ALPHA = R.id.scrim_alpha_end;
+    private static final float NOT_INITIALIZED = -1;
 
     private final LightBarController mLightBarController;
     protected final ScrimView mScrimBehind;
@@ -87,9 +88,9 @@
     private boolean mDozing;
     private float mDozeInFrontAlpha;
     private float mDozeBehindAlpha;
-    private float mCurrentInFrontAlpha;
-    private float mCurrentBehindAlpha;
-    private float mCurrentHeadsUpAlpha = 1;
+    private float mCurrentInFrontAlpha  = NOT_INITIALIZED;
+    private float mCurrentBehindAlpha = NOT_INITIALIZED;
+    private float mCurrentHeadsUpAlpha = NOT_INITIALIZED;
     private int mPinnedHeadsUpCount;
     private float mTopHeadsUpDragAmount;
     private View mDraggedHeadsUpView;
@@ -111,6 +112,7 @@
         mScrimBehindAlpha = context.getResources().getFloat(R.dimen.scrim_behind_alpha);
 
         updateHeadsUpScrim(false);
+        updateScrims();
     }
 
     public void setKeyguardShowing(boolean showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
new file mode 100644
index 0000000..6361eb6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.ArgbEvaluator;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Path;
+import android.graphics.Path.Direction;
+import android.graphics.Path.FillType;
+import android.graphics.Path.Op;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.util.Log;
+
+import com.android.settingslib.R;
+import com.android.settingslib.Utils;
+
+public class SignalDrawable extends Drawable {
+
+    private static final String TAG = "SignalDrawable";
+
+    private static final int NUM_DOTS = 3;
+
+    private static final float VIEWPORT = 24f;
+    private static final float PAD = 2f / VIEWPORT;
+    private static final float CUT_OUT = 7.9f / VIEWPORT;
+
+    private static final float DOT_SIZE = 3f / VIEWPORT;
+    private static final float DOT_PADDING = 1f / VIEWPORT;
+    private static final float DOT_CUT_WIDTH = (DOT_SIZE * 3) + (DOT_PADDING * 5);
+    private static final float DOT_CUT_HEIGHT = (DOT_SIZE * 1) + (DOT_PADDING * 1);
+
+    private static final float[] FIT = {2.26f, -3.02f, 1.76f};
+
+    // All of these are masks to push all of the drawable state into one int for easy callbacks
+    // and flow through sysui.
+    private static final int LEVEL_MASK = 0xff;
+    private static final int NUM_LEVEL_SHIFT = 8;
+    private static final int NUM_LEVEL_MASK = 0xff << NUM_LEVEL_SHIFT;
+    public static final int STATE_SHIFT = 16;
+    public static final int STATE_MASK = 0xff << STATE_SHIFT;
+    public static final int STATE_NONE = 0;
+    public static final int STATE_EMPTY = 1;
+    public static final int STATE_CUT = 2;
+    public static final int STATE_CARRIER_CHANGE = 3;
+
+    private static final long DOT_DELAY = 1000;
+
+    private static float[][] X_PATH = new float[][]{
+            {21.9f / VIEWPORT, 17.0f / VIEWPORT},
+            {-1.1f / VIEWPORT, -1.1f / VIEWPORT},
+            {-1.9f / VIEWPORT, 1.9f / VIEWPORT},
+            {-1.9f / VIEWPORT, -1.9f / VIEWPORT},
+            {-1.1f / VIEWPORT, 1.1f / VIEWPORT},
+            {1.9f / VIEWPORT, 1.9f / VIEWPORT},
+            {-1.9f / VIEWPORT, 1.9f / VIEWPORT},
+            {1.1f / VIEWPORT, 1.1f / VIEWPORT},
+            {1.9f / VIEWPORT, -1.9f / VIEWPORT},
+            {1.9f / VIEWPORT, 1.9f / VIEWPORT},
+            {1.1f / VIEWPORT, -1.1f / VIEWPORT},
+            {-1.9f / VIEWPORT, -1.9f / VIEWPORT},
+    };
+
+    private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    private final int mDarkModeBackgroundColor;
+    private final int mDarkModeFillColor;
+    private final int mLightModeBackgroundColor;
+    private final int mLightModeFillColor;
+    private final Path mFullPath = new Path();
+    private final Path mForegroundPath = new Path();
+    private final Path mXPath = new Path();
+    private final int mIntrinsicSize;
+    private final Handler mHandler;
+    private float mOldDarkIntensity = -1;
+    private float mNumLevels = 1;
+    private int mLevel;
+    private int mState;
+    private boolean mVisible;
+    private boolean mAnimating;
+    private int mCurrentDot;
+
+    public SignalDrawable(Context context) {
+        mDarkModeBackgroundColor =
+                Utils.getDefaultColor(context, R.color.dark_mode_icon_color_dual_tone_background);
+        mDarkModeFillColor =
+                Utils.getDefaultColor(context, R.color.dark_mode_icon_color_dual_tone_fill);
+        mLightModeBackgroundColor =
+                Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_background);
+        mLightModeFillColor =
+                Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_fill);
+        mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size);
+        mHandler = new Handler();
+        setDarkIntensity(0);
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mIntrinsicSize;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mIntrinsicSize;
+    }
+
+    public void setNumLevels(int levels) {
+        if (levels == mNumLevels) return;
+        mNumLevels = levels;
+        invalidateSelf();
+    }
+
+    private void setSignalState(int state) {
+        if (state == mState) return;
+        mState = state;
+        updateAnimation();
+        invalidateSelf();
+    }
+
+    private void updateAnimation() {
+        boolean shouldAnimate = (mState == STATE_CARRIER_CHANGE) && mVisible;
+        if (shouldAnimate == mAnimating) return;
+        mAnimating = shouldAnimate;
+        if (shouldAnimate) {
+            mChangeDot.run();
+        } else {
+            mHandler.removeCallbacks(mChangeDot);
+        }
+    }
+
+    @Override
+    protected boolean onLevelChange(int state) {
+        setNumLevels(getNumLevels(state));
+        setSignalState(getState(state));
+        int level = getLevel(state);
+        if (level != mLevel) {
+            mLevel = level;
+            invalidateSelf();
+        }
+        return true;
+    }
+
+    public void setDarkIntensity(float darkIntensity) {
+        if (darkIntensity == mOldDarkIntensity) {
+            return;
+        }
+        mPaint.setColor(getBackgroundColor(darkIntensity));
+        mForegroundPaint.setColor(getFillColor(darkIntensity));
+        mOldDarkIntensity = darkIntensity;
+        invalidateSelf();
+    }
+
+    private int getFillColor(float darkIntensity) {
+        return getColorForDarkIntensity(
+                darkIntensity, mLightModeFillColor, mDarkModeFillColor);
+    }
+
+    private int getBackgroundColor(float darkIntensity) {
+        return getColorForDarkIntensity(
+                darkIntensity, mLightModeBackgroundColor, mDarkModeBackgroundColor);
+    }
+
+    private int getColorForDarkIntensity(float darkIntensity, int lightColor, int darkColor) {
+        return (int) ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor);
+    }
+
+    @Override
+    protected void onBoundsChange(Rect bounds) {
+        super.onBoundsChange(bounds);
+        invalidateSelf();
+    }
+
+    @Override
+    public void draw(@NonNull Canvas canvas) {
+        mFullPath.reset();
+        mFullPath.setFillType(FillType.WINDING);
+        float width = getBounds().width();
+        float height = getBounds().height();
+        float padding = (PAD * width);
+        mFullPath.moveTo(width - padding, height - padding);
+        mFullPath.lineTo(width - padding, padding);
+        mFullPath.lineTo(padding, height - padding);
+        mFullPath.lineTo(width - padding, height - padding);
+
+        if (mState == STATE_CARRIER_CHANGE) {
+            float cutWidth = (DOT_CUT_WIDTH * width);
+            float cutHeight = (DOT_CUT_HEIGHT * width);
+            float dotSize = (DOT_SIZE * height);
+            float dotPadding = (DOT_PADDING * height);
+
+            mFullPath.moveTo(width - padding, height - padding);
+            mFullPath.rLineTo(-cutWidth, 0);
+            mFullPath.rLineTo(0, -cutHeight);
+            mFullPath.rLineTo(cutWidth, 0);
+            mFullPath.rLineTo(0, cutHeight);
+            float dotSpacing = dotPadding * 2 + dotSize;
+            float x = width - padding - dotSize;
+            float y = height - padding - dotSize;
+            mForegroundPath.reset();
+            drawDot(mFullPath, mForegroundPath, x, y, dotSize, 2);
+            drawDot(mFullPath, mForegroundPath, x - dotSpacing, y, dotSize, 1);
+            drawDot(mFullPath, mForegroundPath, x - dotSpacing * 2, y, dotSize, 0);
+        } else if (mState == STATE_CUT) {
+            float cut = (CUT_OUT * width);
+            mFullPath.moveTo(width - padding, height - padding);
+            mFullPath.rLineTo(-cut, 0);
+            mFullPath.rLineTo(0, -cut);
+            mFullPath.rLineTo(cut, 0);
+            mFullPath.rLineTo(0, cut);
+        }
+
+        mPaint.setStyle(mState == STATE_EMPTY ? Style.STROKE : Style.FILL);
+        mForegroundPaint.setStyle(mState == STATE_EMPTY ? Style.STROKE : Style.FILL);
+
+        if (mState != STATE_CARRIER_CHANGE) {
+            mForegroundPath.reset();
+            int sigWidth = Math.round(calcFit(mLevel / (mNumLevels - 1)) * (width - 2 * padding));
+            mForegroundPath.addRect(padding, padding, padding + sigWidth, height - padding,
+                    Direction.CW);
+            mForegroundPath.op(mFullPath, Op.INTERSECT);
+        }
+
+        canvas.drawPath(mFullPath, mPaint);
+        canvas.drawPath(mForegroundPath, mForegroundPaint);
+        if (mState == STATE_CUT) {
+            mXPath.reset();
+            mXPath.moveTo(X_PATH[0][0] * width, X_PATH[0][1] * height);
+            for (int i = 1; i < X_PATH.length; i++) {
+                mXPath.rLineTo(X_PATH[i][0] * width, X_PATH[i][1] * height);
+            }
+            canvas.drawPath(mXPath, mForegroundPaint);
+        }
+    }
+
+    private void drawDot(Path fullPath, Path foregroundPath, float x, float y, float dotSize,
+            int i) {
+        Path p = (i == mCurrentDot) ? foregroundPath : fullPath;
+        p.addRect(x, y, x + dotSize, y + dotSize, Direction.CW);
+    }
+
+    // This is a fit line based on previous values of provided in assets, but if
+    // you look at the a plot of this actual fit, it makes a lot of sense, what it does
+    // is compress the areas that are very visually easy to see changes (the middle sections)
+    // and spread out the sections that are hard to see (each end of the icon).
+    // The current fit is cubic, but pretty easy to change the way the code is written (just add
+    // terms to the end of FIT).
+    private float calcFit(float v) {
+        float ret = 0;
+        float t = v;
+        for (int i = 0; i < FIT.length; i++) {
+            ret += FIT[i] * t;
+            t *= v;
+        }
+        return ret;
+    }
+
+    @Override
+    public int getAlpha() {
+        return mPaint.getAlpha();
+    }
+
+    @Override
+    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
+        mPaint.setAlpha(alpha);
+        mForegroundPaint.setAlpha(alpha);
+    }
+
+    @Override
+    public void setColorFilter(@Nullable ColorFilter colorFilter) {
+        mPaint.setColorFilter(colorFilter);
+        mForegroundPaint.setColorFilter(colorFilter);
+    }
+
+    @Override
+    public int getOpacity() {
+        return 255;
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        mVisible = visible;
+        updateAnimation();
+        return super.setVisible(visible, restart);
+    }
+
+    private final Runnable mChangeDot = new Runnable() {
+        @Override
+        public void run() {
+            if (++mCurrentDot == NUM_DOTS) {
+                mCurrentDot = 0;
+            }
+            invalidateSelf();
+            mHandler.postDelayed(mChangeDot, DOT_DELAY);
+        }
+    };
+
+    public static int getLevel(int fullState) {
+        return fullState & LEVEL_MASK;
+    }
+
+    public static int getState(int fullState) {
+        return (fullState & STATE_MASK) >> STATE_SHIFT;
+    }
+
+    public static int getNumLevels(int fullState) {
+        return (fullState & NUM_LEVEL_MASK) >> NUM_LEVEL_SHIFT;
+    }
+
+    public static int getState(int level, int numLevels, boolean cutOut) {
+        return ((cutOut ? STATE_CUT : 0) << STATE_SHIFT)
+                | (numLevels << NUM_LEVEL_SHIFT)
+                | level;
+    }
+
+    public static int getCarrierChangeState(int numLevels) {
+        return (STATE_CARRIER_CHANGE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
+    }
+
+    public static int getEmptyState(int numLevels) {
+        return (STATE_EMPTY << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 0b3cbd9..24ea76f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -31,6 +31,7 @@
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
 
+import android.R.style;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.annotation.NonNull;
@@ -48,10 +49,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
-import android.content.pm.ActivityInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -95,6 +94,7 @@
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -139,7 +139,6 @@
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.PluginFragmentListener;
 import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.pip.phone.PipManager;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
@@ -716,6 +715,7 @@
     private ConfigurationListener mConfigurationListener;
     private InflationExceptionHandler mInflationExceptionHandler = this::handleInflationException;
     private boolean mReinflateNotificationsOnUserSwitched;
+    private boolean mClearAllEnabled;
 
     private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
         final int N = array.size();
@@ -758,18 +758,20 @@
         mAssistManager = Dependency.get(AssistManager.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
 
-        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         mDisplay = mWindowManager.getDefaultDisplay();
         updateDisplaySize();
-        mScrimSrcModeEnabled = mContext.getResources().getBoolean(
-                R.bool.config_status_bar_scrim_behind_use_src);
+
+        Resources res = mContext.getResources();
+        mScrimSrcModeEnabled = res.getBoolean(R.bool.config_status_bar_scrim_behind_use_src);
+        mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
 
         DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER));
         putComponent(StatusBar.class, this);
 
         // start old BaseStatusBar.start().
         mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
-        mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
+        mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
 
         mNotificationData = new NotificationData(this);
@@ -810,7 +812,7 @@
 
         mRecents = getComponent(Recents.class);
 
-        final Configuration currentConfig = mContext.getResources().getConfiguration();
+        final Configuration currentConfig = res.getConfiguration();
         mLocale = currentConfig.locale;
         mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
 
@@ -823,7 +825,7 @@
         mCommandQueue.addCallbacks(this);
 
         int[] switches = new int[9];
-        ArrayList<IBinder> binders = new ArrayList<IBinder>();
+        ArrayList<IBinder> binders = new ArrayList<>();
         ArrayList<String> iconSlots = new ArrayList<>();
         ArrayList<StatusBarIcon> icons = new ArrayList<>();
         Rect fullscreenStackBounds = new Rect();
@@ -904,8 +906,8 @@
             Slog.e(TAG, "Failed to register VR mode state listener: " + e);
         }
 
-        mNonBlockablePkgs = new HashSet<String>();
-        Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
+        mNonBlockablePkgs = new HashSet<>();
+        Collections.addAll(mNonBlockablePkgs, res.getStringArray(
                 com.android.internal.R.array.config_nonBlockableNotificationPackages));
         // end old BaseStatusBar.start().
 
@@ -1114,14 +1116,11 @@
         }
         mHeadsUpManager.addListener(mScrimController);
         mStackScroller.setScrimController(mScrimController);
-        mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller,
-                mNotificationPanel);
+        mDozeScrimController = new DozeScrimController(mScrimController, context);
 
         // Other icons
         mVolumeComponent = getComponent(VolumeComponent.class);
 
-        initEmergencyCryptkeeperText();
-
         mKeyguardBottomArea.setStatusBar(this);
         mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
         if (UserManager.get(mContext).isUserSwitcherEnabled()) {
@@ -1231,24 +1230,6 @@
         });
     }
 
-    private void initEmergencyCryptkeeperText() {
-        View emergencyViewStub = mStatusBarWindow.findViewById(R.id.emergency_cryptkeeper_text);
-        if (mNetworkController.hasEmergencyCryptKeeperText()) {
-            if (emergencyViewStub != null) {
-                ((ViewStub) emergencyViewStub).inflate();
-            }
-            mNetworkController.addCallback(new NetworkController.SignalCallback() {
-                @Override
-                public void setIsAirplaneMode(NetworkController.IconState icon) {
-                    recomputeDisableFlags(true /* animate */);
-                }
-            });
-        } else if (emergencyViewStub != null) {
-            ViewGroup parent = (ViewGroup) emergencyViewStub.getParent();
-            parent.removeView(emergencyViewStub);
-        }
-    }
-
     /**
      * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the
      * background window of the status bar is clicked.
@@ -1358,7 +1339,14 @@
     }
 
     private void inflateDismissView() {
-        mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(
+        if (!mClearAllEnabled) {
+            return;
+        }
+
+        // Always inflate with a dark theme, since this sits on the scrim.
+        ContextThemeWrapper themedContext = new ContextThemeWrapper(mContext,
+                style.Theme_DeviceDefault);
+        mDismissView = (DismissView) LayoutInflater.from(themedContext).inflate(
                 R.layout.status_bar_notification_dismiss_all, mStackScroller, false);
         mDismissView.setOnButtonClickListener(new View.OnClickListener() {
             @Override
@@ -1830,6 +1818,7 @@
                 updatePublicContentView(ent, ent.notification);
             }
             ent.row.setSensitive(sensitive, deviceSensitive);
+            ent.row.setNeedsRedaction(needsRedaction(ent));
             if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) {
                 ExpandableNotificationRow summary = mGroupManager.getGroupSummary(
                         ent.row.getStatusBarNotification());
@@ -1918,6 +1907,21 @@
         mNotificationIconAreaController.updateNotificationIcons(mNotificationData);
     }
 
+    /** @return true if the entry needs redaction when on the lockscreen. */
+    private boolean needsRedaction(Entry ent) {
+        int userId = ent.notification.getUserId();
+
+        boolean currentUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
+        boolean notiUserWantsRedaction = !userAllowsPrivateNotificationsInPublic(userId);
+        boolean redactedLockscreen = currentUserWantsRedaction || notiUserWantsRedaction;
+
+        boolean notificationRequestsRedaction =
+                ent.notification.getNotification().visibility == Notification.VISIBILITY_PRIVATE;
+        boolean userForcesRedaction = packageHasVisibilityOverride(ent.notification.getKey());
+
+        return userForcesRedaction || notificationRequestsRedaction && redactedLockscreen;
+    }
+
     /**
      * Disable QS if device not provisioned.
      * If the user switcher is simple then disable QS during setup because
@@ -1928,6 +1932,7 @@
                 && (mUserSetup || mUserSwitcherController == null
                         || !mUserSwitcherController.isSimpleUserSwitcher())
                 && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
+                && !mDozing
                 && !ONLY_CORE_APPS);
     }
 
@@ -2023,9 +2028,11 @@
     }
 
     private void updateClearAll() {
-        boolean showDismissView =
-                mState != StatusBarState.KEYGUARD &&
-               hasActiveClearableNotifications();
+        if (!mClearAllEnabled) {
+            return;
+        }
+        boolean showDismissView = mState != StatusBarState.KEYGUARD
+                && hasActiveClearableNotifications();
         mStackScroller.updateDismissView(showDismissView);
     }
 
@@ -4336,6 +4343,8 @@
         mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation);
         mScrimController.setDozing(mDozing);
         mKeyguardIndicationController.setDozing(mDozing);
+        mNotificationPanel.setDark(mDozing);
+        updateQsExpansionEnabled();
 
         // Immediately abort the dozing from the doze scrim controller in case of wake-and-unlock
         // for pulsing so the Keyguard fade-out animation scrim can take over.
@@ -4553,7 +4562,7 @@
 
     // TODO: Figure out way to remove these.
     public NavigationBarView getNavigationBarView() {
-        return (NavigationBarView) mNavigationBar.getView();
+        return (mNavigationBar != null ? (NavigationBarView) mNavigationBar.getView() : null);
     }
 
     public KeyguardBottomAreaView getKeyguardBottomAreaView() {
@@ -4966,6 +4975,7 @@
         mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD
                 || mFingerprintUnlockController.getMode()
                         == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+        mStatusBarWindowManager.setDozing(mDozing);
         updateDozingState();
         Trace.endSection();
     }
@@ -5073,6 +5083,16 @@
             StatusBar.this.startPendingIntentDismissingKeyguard(intent);
         }
 
+        @Override
+        public void abortPulsing() {
+            mDozeScrimController.abortPulsing();
+        }
+
+        @Override
+        public void extendPulse() {
+            mDozeScrimController.extendPulse();
+        }
+
     }
 
     // Begin Extra BaseStatusBar methods.
@@ -5771,6 +5791,9 @@
             snoozeGuts.setSnoozeListener(mStackScroller.getSwipeActionHelper());
             snoozeGuts.setStatusBarNotification(sbn);
             snoozeGuts.setSnoozeOptions(row.getEntry().snoozeCriteria);
+            guts.setHeightChangedListener((NotificationGuts g) -> {
+                mStackScroller.onHeightChanged(row, row.isShown() /* needsAnimation */);
+            });
         }
 
         if (gutsView instanceof NotificationInfo) {
@@ -5872,6 +5895,9 @@
                 }
 
                 final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+                if (row.isDark()) {
+                    return false;
+                }
                 bindGuts(row, item);
                 NotificationGuts guts = row.getGuts();
 
@@ -5919,8 +5945,10 @@
                             }
                         });
                         a.start();
-                        guts.setExposed(true /* exposed */,
-                                mState == StatusBarState.KEYGUARD /* needsFalsingProtection */);
+                        final boolean needsFalsingProtection =
+                                (mState == StatusBarState.KEYGUARD &&
+                                !mAccessibilityManager.isTouchExplorationEnabled());
+                        guts.setExposed(true /* exposed */, needsFalsingProtection);
                         row.closeRemoteInput();
                         mStackScroller.onHeightChanged(row, true /* needsAnimation */);
                         mNotificationGutsExposed = guts;
@@ -6171,6 +6199,7 @@
             }
         }
 
+        row.setNeedsRedaction(needsRedaction(entry));
         boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
         row.setIsLowPriority(isLowPriority);
         // bind the click event to the content area
@@ -6535,7 +6564,6 @@
         NotificationData.Entry entry = new NotificationData.Entry(sbn);
         Dependency.get(LeakDetector.class).trackInstance(entry);
         entry.createIcons(mContext, sbn);
-
         // Construct the expanded view.
         inflateViews(entry, mStackScroller);
         return entry;
@@ -6615,9 +6643,23 @@
         }
         mNotificationPanel.setNoVisibleNotifications(visibleNotifications == 0);
 
-        mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1);
-        mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2);
-        mStackScroller.changeViewPosition(mNotificationShelf, mStackScroller.getChildCount() - 3);
+        // The following views will be moved to the end of mStackScroller. This counter represents
+        // the offset from the last child. Initialized to 1 for the very last position. It is post-
+        // incremented in the following "changeViewPosition" calls so that its value is correct for
+        // subsequent calls.
+        int offsetFromEnd = 1;
+        if (mDismissView != null) {
+            mStackScroller.changeViewPosition(mDismissView,
+                    mStackScroller.getChildCount() - offsetFromEnd++);
+        }
+
+        mStackScroller.changeViewPosition(mEmptyShadeView,
+                mStackScroller.getChildCount() - offsetFromEnd++);
+
+        // No post-increment for this call because it is the last one. Make sure to add one if
+        // another "changeViewPosition" call is ever added.
+        mStackScroller.changeViewPosition(mNotificationShelf,
+                mStackScroller.getChildCount() - offsetFromEnd);
     }
 
     public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index deb0070..0326e40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -118,7 +118,7 @@
             mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         }
 
-        if (state.keyguardShowing && !state.backdropShowing) {
+        if (state.keyguardShowing && !state.backdropShowing && !state.dozing) {
             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
         } else {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
@@ -357,6 +357,11 @@
         apply(mCurrentState);
     }
 
+    public void setDozing(boolean dozing) {
+        mCurrentState.dozing = dozing;
+        apply(mCurrentState);
+    }
+
     public void setBarHeight(int barHeight) {
         mBarHeight = barHeight;
         apply(mCurrentState);
@@ -404,6 +409,7 @@
 
         boolean remoteInputActive;
         boolean forcePluginOpen;
+        boolean dozing;
 
         private boolean isKeyguardShowingAndNotOccluded() {
             return keyguardShowing && !keyguardOccluded;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 1848d4e..1a09d75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -255,6 +255,9 @@
         if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
             mStackScrollLayout.closeControlsIfOutsideTouch(ev);
         }
+        if (mService.isDozing()) {
+            mService.mDozeScrimController.extendPulse();
+        }
 
         return super.dispatchTouchEvent(ev);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index a456786..e98dc98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -110,30 +110,24 @@
     public void setWifiIndicators(final boolean enabled, final IconState statusIcon,
             final IconState qsIcon, final boolean activityIn, final boolean activityOut,
             final String description, boolean isTransient) {
-        post(new Runnable() {
-            @Override
-            public void run() {
-                for (SignalCallback callback : mSignalCallbacks) {
-                    callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
-                            description, isTransient);
-                }
+        post(() -> {
+            for (SignalCallback callback : mSignalCallbacks) {
+                callback.setWifiIndicators(enabled, statusIcon, qsIcon, activityIn, activityOut,
+                        description, isTransient);
             }
         });
     }
 
     @Override
-    public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon,
-            final int statusType, final int qsType,final boolean activityIn,
+    public void setMobileDataIndicators(final IconState statusIcon,
+            final int statusType, final boolean activityIn,
             final boolean activityOut, final String typeContentDescription,
-            final String description, final boolean isWide, final int subId, boolean roaming) {
-        post(new Runnable() {
-            @Override
-            public void run() {
-                for (SignalCallback signalCluster : mSignalCallbacks) {
-                    signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType,
-                            activityIn, activityOut, typeContentDescription, description, isWide,
-                            subId, roaming);
-                }
+            final int subId, boolean roaming, boolean isEmergency) {
+        post(() -> {
+            for (SignalCallback signalCluster : mSignalCallbacks) {
+                signalCluster.setMobileDataIndicators(statusIcon, statusType,
+                        activityIn, activityOut, typeContentDescription,
+                        subId, roaming, isEmergency);
             }
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 9a5f1b8..8e8a285 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -16,22 +16,29 @@
 
 package com.android.systemui.statusbar.policy;
 
-import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
 
-public interface LocationController extends CallbackController<LocationSettingsChangeCallback> {
+public interface LocationController extends CallbackController<LocationChangeCallback> {
+    boolean isLocationActive();
     boolean isLocationEnabled();
     boolean setLocationEnabled(boolean enabled);
 
     /**
      * A callback for change in location settings (the user has enabled/disabled location).
      */
-    public interface LocationSettingsChangeCallback {
+    public interface LocationChangeCallback {
+        /**
+         * Called whenever location's state changes.
+         * @param active
+         */
+        default void onLocationActiveChanged(boolean active) {}
+
         /**
          * Called whenever location settings change.
          *
          * @param locationEnabled A value of true indicates that at least one type of location
          *                        is enabled in settings.
          */
-        void onLocationSettingsChanged(boolean locationEnabled);
+        default void onLocationSettingsChanged(boolean locationEnabled) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index cc61605..3f5f5a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -41,9 +41,6 @@
  * A controller to manage changes of location related states and update the views accordingly.
  */
 public class LocationControllerImpl extends BroadcastReceiver implements LocationController {
-    // The name of the placeholder corresponding to the location request status icon.
-    // This string corresponds to config_statusBarIcons in core/res/res/values/config.xml.
-    public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
 
     private static final int[] mHighPowerRequestAppOpArray
         = new int[] {AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION};
@@ -55,14 +52,12 @@
 
     private boolean mAreActiveLocationRequests;
 
-    private ArrayList<LocationSettingsChangeCallback> mSettingsChangeCallbacks =
-            new ArrayList<LocationSettingsChangeCallback>();
+    private ArrayList<LocationChangeCallback> mSettingsChangeCallbacks =
+            new ArrayList<LocationChangeCallback>();
     private final H mHandler = new H();
-    public final String mSlotLocation;
 
     public LocationControllerImpl(Context context, Looper bgLooper) {
         mContext = context;
-        mSlotLocation = mContext.getString(com.android.internal.R.string.status_bar_location);
 
         // Register to listen for changes in location settings.
         IntentFilter filter = new IntentFilter();
@@ -76,18 +71,17 @@
 
         // Examine the current location state and initialize the status view.
         updateActiveLocationRequests();
-        refreshViews();
     }
 
     /**
      * Add a callback to listen for changes in location settings.
      */
-    public void addCallback(LocationSettingsChangeCallback cb) {
+    public void addCallback(LocationChangeCallback cb) {
         mSettingsChangeCallbacks.add(cb);
         mHandler.sendEmptyMessage(H.MSG_LOCATION_SETTINGS_CHANGED);
     }
 
-    public void removeCallback(LocationSettingsChangeCallback cb) {
+    public void removeCallback(LocationChangeCallback cb) {
         mSettingsChangeCallbacks.remove(cb);
     }
 
@@ -130,6 +124,11 @@
         return mode != Settings.Secure.LOCATION_MODE_OFF;
     }
 
+    @Override
+    public boolean isLocationActive() {
+        return mAreActiveLocationRequests;
+    }
+
     /**
      * Returns true if the current user is restricted from using location.
      */
@@ -170,22 +169,12 @@
         return false;
     }
 
-    // Updates the status view based on the current state of location requests.
-    private void refreshViews() {
-        if (mAreActiveLocationRequests) {
-            mStatusBarManager.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
-                    0, mContext.getString(R.string.accessibility_location_active));
-        } else {
-            mStatusBarManager.removeIcon(mSlotLocation);
-        }
-    }
-
     // Reads the active location requests and updates the status view if necessary.
     private void updateActiveLocationRequests() {
         boolean hadActiveLocationRequests = mAreActiveLocationRequests;
         mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
         if (mAreActiveLocationRequests != hadActiveLocationRequests) {
-            refreshViews();
+            mHandler.sendEmptyMessage(H.MSG_LOCATION_ACTIVE_CHANGED);
         }
     }
 
@@ -201,6 +190,7 @@
 
     private final class H extends Handler {
         private static final int MSG_LOCATION_SETTINGS_CHANGED = 1;
+        private static final int MSG_LOCATION_ACTIVE_CHANGED = 2;
 
         @Override
         public void handleMessage(Message msg) {
@@ -208,12 +198,21 @@
                 case MSG_LOCATION_SETTINGS_CHANGED:
                     locationSettingsChanged();
                     break;
+                case MSG_LOCATION_ACTIVE_CHANGED:
+                    locationActiveChanged();
+                    break;
+            }
+        }
+
+        private void locationActiveChanged() {
+            for (LocationChangeCallback cb : mSettingsChangeCallbacks) {
+                cb.onLocationActiveChanged(mAreActiveLocationRequests);
             }
         }
 
         private void locationSettingsChanged() {
             boolean isEnabled = isLocationEnabled();
-            for (LocationSettingsChangeCallback cb : mSettingsChangeCallbacks) {
+            for (LocationChangeCallback cb : mSettingsChangeCallbacks) {
                 cb.onLocationSettingsChanged(isEnabled);
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 91acf04..4421a6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -36,6 +36,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
@@ -233,30 +234,44 @@
         mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
     }
 
+    private int getNumLevels() {
+        return SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
+    }
+
+    @Override
+    public int getCurrentIconId() {
+        if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {
+            return SignalDrawable.getCarrierChangeState(getNumLevels());
+        } else if (mCurrentState.connected) {
+            return SignalDrawable.getState(mCurrentState.level, getNumLevels(),
+                    mCurrentState.inetCondition == 0 ||
+                            (mCurrentState.dataDisabled && mCurrentState.userSetup));
+        } else if (mCurrentState.enabled) {
+            return SignalDrawable.getEmptyState(getNumLevels());
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public int getQsCurrentIconId() {
+        return getCurrentIconId();
+    }
+
     @Override
     public void notifyListeners(SignalCallback callback) {
         MobileIconGroup icons = getIcons();
 
         String contentDescription = getStringIfExists(getContentDescription());
         String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
-        final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
+        final boolean dataDisabled = mCurrentState.dataDisabled
                 && mCurrentState.userSetup;
 
         // Show icon in QS when we are connected or data is disabled.
-        boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
+        boolean showDataIcon = mCurrentState.dataConnected;
         IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
                 getCurrentIconId(), contentDescription);
 
-        int qsTypeIcon = 0;
-        IconState qsIcon = null;
-        String description = null;
-        // Only send data sim callbacks to QS.
-        if (mCurrentState.dataSim) {
-            qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
-            qsIcon = new IconState(mCurrentState.enabled
-                    && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
-            description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
-        }
         boolean activityIn = mCurrentState.dataConnected
                 && !mCurrentState.carrierNetworkChangeMode
                 && mCurrentState.activityIn;
@@ -265,9 +280,10 @@
                 && mCurrentState.activityOut;
         showDataIcon &= mCurrentState.isDefault || dataDisabled;
         int typeIcon = showDataIcon ? icons.mDataType : 0;
-        callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
-                activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
-                mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
+        callback.setMobileDataIndicators(statusIcon, typeIcon,
+                activityIn, activityOut, dataContentDescription,
+                mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming,
+                mCurrentState.isEmergency);
     }
 
     @Override
@@ -414,14 +430,14 @@
         } else {
             mCurrentState.iconGroup = mDefaultIcons;
         }
+        mCurrentState.dataDisabled = isDataDisabled();
         mCurrentState.dataConnected = mCurrentState.connected
-                && mDataState == TelephonyManager.DATA_CONNECTED;
+                && mDataState == TelephonyManager.DATA_CONNECTED
+                && !mCurrentState.dataDisabled;
 
         mCurrentState.roaming = isRoaming();
         if (isCarrierNetworkChangeActive()) {
             mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
-        } else if (isDataDisabled()) {
-            mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
         }
         if (isEmergencyOnly() != mCurrentState.isEmergency) {
             mCurrentState.isEmergency = isEmergencyOnly();
@@ -553,6 +569,7 @@
         boolean isDefault;
         boolean userSetup;
         boolean roaming;
+        boolean dataDisabled;
 
         @Override
         public void copyFrom(State s) {
@@ -568,6 +585,7 @@
             carrierNetworkChangeMode = state.carrierNetworkChangeMode;
             userSetup = state.userSetup;
             roaming = state.roaming;
+            dataDisabled = state.dataDisabled;
         }
 
         @Override
@@ -585,6 +603,7 @@
             builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
                     .append(',');
             builder.append("userSetup=").append(userSetup);
+            builder.append("dataDisabled=").append(dataDisabled);
         }
 
         @Override
@@ -599,6 +618,7 @@
                     && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
                     && ((MobileState) o).userSetup == userSetup
                     && ((MobileState) o).isDefault == isDefault
+                    && ((MobileState) o).dataDisabled == dataDisabled
                     && ((MobileState) o).roaming == roaming;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index c02ce0e..ab4a8f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -48,9 +48,9 @@
         default void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
                 boolean activityIn, boolean activityOut, String description, boolean isTransient) {}
 
-        default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-                int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-                String description, boolean isWide, int subId, boolean roaming) {}
+        default void setMobileDataIndicators(IconState statusIcon, int statusType,
+                boolean activityIn, boolean activityOut, String typeContentDescription,
+                int subId, boolean roaming, boolean isEmergency) {}
         default void setSubs(List<SubscriptionInfo> subs) {}
         default void setNoSims(boolean show) {}
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index bc3eec9..60f4ab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -32,6 +32,7 @@
 import android.os.Looper;
 import android.provider.Settings;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
@@ -866,17 +867,16 @@
                             datatype.equals("h") ? TelephonyIcons.H :
                             datatype.equals("lte") ? TelephonyIcons.LTE :
                             datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
-                            datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
                             TelephonyIcons.UNKNOWN;
                 }
                 if (args.containsKey("roam")) {
                     controller.getState().roaming = "show".equals(args.getString("roam"));
                 }
-                int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH;
                 String level = args.getString("level");
                 if (level != null) {
                     controller.getState().level = level.equals("null") ? -1
-                            : Math.min(Integer.parseInt(level), icons[0].length - 1);
+                            : Math.min(Integer.parseInt(level),
+                                    SignalStrength.NUM_SIGNAL_STRENGTH_BINS);
                     controller.getState().connected = controller.getState().level >= 0;
                 }
                 String activity = args.getString("activity");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 784f25e..37b0de4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -101,9 +101,9 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        mProgressBar = (ProgressBar) findViewById(R.id.remote_input_progress);
+        mProgressBar = findViewById(R.id.remote_input_progress);
 
-        mSendButton = (ImageButton) findViewById(R.id.remote_input_send);
+        mSendButton = findViewById(R.id.remote_input_send);
         mSendButton.setOnClickListener(this);
 
         mEditText = (RemoteEditText) getChildAt(0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
index 3f8e41a..1fb9b69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -23,16 +23,20 @@
     /** Whether the device has device owner, even if not on this user. */
     boolean isDeviceManaged();
     boolean hasProfileOwner();
+    boolean hasWorkProfile();
     String getDeviceOwnerName();
     String getProfileOwnerName();
     CharSequence getDeviceOwnerOrganizationName();
+    CharSequence getWorkProfileOrganizationName();
     boolean isNetworkLoggingEnabled();
     boolean isVpnEnabled();
     boolean isVpnRestricted();
     /** Whether the VPN app should use branded VPN iconography.  */
     boolean isVpnBranded();
     String getPrimaryVpnName();
-    String getProfileVpnName();
+    String getWorkProfileVpnName();
+    boolean hasCACertInCurrentUser();
+    boolean hasCACertInWorkProfile();
     void onUserSwitched(int newUserId);
 
     public interface SecurityControllerCallback {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 19ced23..fcb7289 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -138,6 +138,13 @@
     }
 
     @Override
+    public CharSequence getWorkProfileOrganizationName() {
+        final int profileId = getWorkProfileUserId(mCurrentUserId);
+        if (profileId == UserHandle.USER_NULL) return null;
+        return mDevicePolicyManager.getOrganizationNameForUser(profileId);
+    }
+
+    @Override
     public String getPrimaryVpnName() {
         VpnConfig cfg = mCurrentVpns.get(mVpnUserId);
         if (cfg != null) {
@@ -147,16 +154,27 @@
         }
     }
 
+    private int getWorkProfileUserId(int userId) {
+        for (final UserInfo userInfo : mUserManager.getProfiles(userId)) {
+            if (userInfo.isManagedProfile()) {
+                return userInfo.id;
+            }
+        }
+        return UserHandle.USER_NULL;
+    }
+
     @Override
-    public String getProfileVpnName() {
-        for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) {
-            if (profileId == mVpnUserId) {
-                continue;
-            }
-            VpnConfig cfg = mCurrentVpns.get(profileId);
-            if (cfg != null) {
-                return getNameForVpnConfig(cfg, UserHandle.of(profileId));
-            }
+    public boolean hasWorkProfile() {
+        return getWorkProfileUserId(mCurrentUserId) != UserHandle.USER_NULL;
+    }
+
+    @Override
+    public String getWorkProfileVpnName() {
+        final int profileId = getWorkProfileUserId(mVpnUserId);
+        if (profileId == UserHandle.USER_NULL) return null;
+        VpnConfig cfg = mCurrentVpns.get(profileId);
+        if (cfg != null) {
+            return getNameForVpnConfig(cfg, UserHandle.of(profileId));
         }
         return null;
     }
@@ -199,6 +217,18 @@
     }
 
     @Override
+    public boolean hasCACertInCurrentUser() {
+        //TODO: implement
+        return false;
+    }
+
+    @Override
+    public boolean hasCACertInWorkProfile() {
+        //TODO: implement
+        return false;
+    }
+
+    @Override
     public void removeCallback(SecurityControllerCallback callback) {
         synchronized (mCallbacks) {
             if (callback == null) return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java
index faa1a28a..9f61574 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java
@@ -59,8 +59,8 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mTimeView = (TextClock) findViewById(R.id.time_view);
-        mAmPmView = (TextClock) findViewById(R.id.am_pm_view);
+        mTimeView = findViewById(R.id.time_view);
+        mAmPmView = findViewById(R.id.am_pm_view);
         mTimeView.setShowCurrentUserTime(true);
         mAmPmView.setShowCurrentUserTime(true);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 6b2361e..ec7e557 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -20,196 +20,20 @@
 import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
 
 class TelephonyIcons {
-    //***** Signal strength icons
-
-    static final int TELEPHONY_NUM_LEVELS = 5;
-
-    //GSM/UMTS
-    static final int TELEPHONY_NO_NETWORK = R.drawable.stat_sys_signal_null;
-
-    static final int[][] TELEPHONY_SIGNAL_STRENGTH = {
-        { R.drawable.stat_sys_signal_0,
-          R.drawable.stat_sys_signal_1,
-          R.drawable.stat_sys_signal_2,
-          R.drawable.stat_sys_signal_3,
-          R.drawable.stat_sys_signal_4 },
-        { R.drawable.stat_sys_signal_0_fully,
-          R.drawable.stat_sys_signal_1_fully,
-          R.drawable.stat_sys_signal_2_fully,
-          R.drawable.stat_sys_signal_3_fully,
-          R.drawable.stat_sys_signal_4_fully }
-    };
-
-    static final int QS_TELEPHONY_NO_NETWORK = R.drawable.ic_qs_signal_no_signal;
-
-    static final int[][] QS_TELEPHONY_SIGNAL_STRENGTH = {
-        { R.drawable.ic_qs_signal_0,
-          R.drawable.ic_qs_signal_1,
-          R.drawable.ic_qs_signal_2,
-          R.drawable.ic_qs_signal_3,
-          R.drawable.ic_qs_signal_4 },
-        { R.drawable.ic_qs_signal_full_0,
-          R.drawable.ic_qs_signal_full_1,
-          R.drawable.ic_qs_signal_full_2,
-          R.drawable.ic_qs_signal_full_3,
-          R.drawable.ic_qs_signal_full_4 }
-    };
-
-    static final int[][] TELEPHONY_SIGNAL_STRENGTH_ROAMING = {
-        { R.drawable.stat_sys_signal_0,
-          R.drawable.stat_sys_signal_1,
-          R.drawable.stat_sys_signal_2,
-          R.drawable.stat_sys_signal_3,
-          R.drawable.stat_sys_signal_4 },
-        { R.drawable.stat_sys_signal_0_fully,
-          R.drawable.stat_sys_signal_1_fully,
-          R.drawable.stat_sys_signal_2_fully,
-          R.drawable.stat_sys_signal_3_fully,
-          R.drawable.stat_sys_signal_4_fully }
-    };
-
-    //CarrierNetworkChange
-    static final int[][] TELEPHONY_CARRIER_NETWORK_CHANGE = {
-            { R.drawable.stat_sys_signal_carrier_network_change_animation,
-              R.drawable.stat_sys_signal_carrier_network_change_animation,
-              R.drawable.stat_sys_signal_carrier_network_change_animation,
-              R.drawable.stat_sys_signal_carrier_network_change_animation,
-              R.drawable.stat_sys_signal_carrier_network_change_animation },
-            { R.drawable.stat_sys_signal_carrier_network_change_animation,
-              R.drawable.stat_sys_signal_carrier_network_change_animation,
-              R.drawable.stat_sys_signal_carrier_network_change_animation,
-              R.drawable.stat_sys_signal_carrier_network_change_animation,
-              R.drawable.stat_sys_signal_carrier_network_change_animation }
-        };
-
-    static final int[][] QS_TELEPHONY_CARRIER_NETWORK_CHANGE = {
-        { R.drawable.ic_qs_signal_carrier_network_change_animation,
-          R.drawable.ic_qs_signal_carrier_network_change_animation,
-          R.drawable.ic_qs_signal_carrier_network_change_animation,
-          R.drawable.ic_qs_signal_carrier_network_change_animation,
-          R.drawable.ic_qs_signal_carrier_network_change_animation },
-        { R.drawable.ic_qs_signal_carrier_network_change_animation,
-          R.drawable.ic_qs_signal_carrier_network_change_animation,
-          R.drawable.ic_qs_signal_carrier_network_change_animation,
-          R.drawable.ic_qs_signal_carrier_network_change_animation,
-          R.drawable.ic_qs_signal_carrier_network_change_animation }
-    };
-
     //***** Data connection icons
 
-    //GSM/UMTS
-    static final int[][] DATA_G = {
-            { R.drawable.stat_sys_data_fully_connected_g,
-              R.drawable.stat_sys_data_fully_connected_g,
-              R.drawable.stat_sys_data_fully_connected_g,
-              R.drawable.stat_sys_data_fully_connected_g },
-            { R.drawable.stat_sys_data_fully_connected_g,
-              R.drawable.stat_sys_data_fully_connected_g,
-              R.drawable.stat_sys_data_fully_connected_g,
-              R.drawable.stat_sys_data_fully_connected_g }
-        };
-
     static final int QS_DATA_G = R.drawable.ic_qs_signal_g;
-
-    static final int[][] DATA_3G = {
-            { R.drawable.stat_sys_data_fully_connected_3g,
-              R.drawable.stat_sys_data_fully_connected_3g,
-              R.drawable.stat_sys_data_fully_connected_3g,
-              R.drawable.stat_sys_data_fully_connected_3g },
-            { R.drawable.stat_sys_data_fully_connected_3g,
-              R.drawable.stat_sys_data_fully_connected_3g,
-              R.drawable.stat_sys_data_fully_connected_3g,
-              R.drawable.stat_sys_data_fully_connected_3g }
-        };
-
     static final int QS_DATA_3G = R.drawable.ic_qs_signal_3g;
-
-    static final int[][] DATA_E = {
-            { R.drawable.stat_sys_data_fully_connected_e,
-              R.drawable.stat_sys_data_fully_connected_e,
-              R.drawable.stat_sys_data_fully_connected_e,
-              R.drawable.stat_sys_data_fully_connected_e },
-            { R.drawable.stat_sys_data_fully_connected_e,
-              R.drawable.stat_sys_data_fully_connected_e,
-              R.drawable.stat_sys_data_fully_connected_e,
-              R.drawable.stat_sys_data_fully_connected_e }
-        };
-
     static final int QS_DATA_E = R.drawable.ic_qs_signal_e;
-
-    //3.5G
-    static final int[][] DATA_H = {
-            { R.drawable.stat_sys_data_fully_connected_h,
-              R.drawable.stat_sys_data_fully_connected_h,
-              R.drawable.stat_sys_data_fully_connected_h,
-              R.drawable.stat_sys_data_fully_connected_h },
-            { R.drawable.stat_sys_data_fully_connected_h,
-              R.drawable.stat_sys_data_fully_connected_h,
-              R.drawable.stat_sys_data_fully_connected_h,
-              R.drawable.stat_sys_data_fully_connected_h }
-    };
-
     static final int QS_DATA_H = R.drawable.ic_qs_signal_h;
-
-    //CDMA
-    // Use 3G icons for EVDO data and 1x icons for 1XRTT data
-    static final int[][] DATA_1X = {
-            { R.drawable.stat_sys_data_fully_connected_1x,
-              R.drawable.stat_sys_data_fully_connected_1x,
-              R.drawable.stat_sys_data_fully_connected_1x,
-              R.drawable.stat_sys_data_fully_connected_1x },
-            { R.drawable.stat_sys_data_fully_connected_1x,
-              R.drawable.stat_sys_data_fully_connected_1x,
-              R.drawable.stat_sys_data_fully_connected_1x,
-              R.drawable.stat_sys_data_fully_connected_1x }
-            };
-
     static final int QS_DATA_1X = R.drawable.ic_qs_signal_1x;
-
-    // LTE and eHRPD
-    static final int[][] DATA_4G = {
-            { R.drawable.stat_sys_data_fully_connected_4g,
-              R.drawable.stat_sys_data_fully_connected_4g,
-              R.drawable.stat_sys_data_fully_connected_4g,
-              R.drawable.stat_sys_data_fully_connected_4g },
-            { R.drawable.stat_sys_data_fully_connected_4g,
-              R.drawable.stat_sys_data_fully_connected_4g,
-              R.drawable.stat_sys_data_fully_connected_4g,
-              R.drawable.stat_sys_data_fully_connected_4g }
-        };
-
     static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g;
-
-    static final int[][] DATA_4G_PLUS = {
-            { R.drawable.stat_sys_data_fully_connected_4g_plus,
-              R.drawable.stat_sys_data_fully_connected_4g_plus,
-              R.drawable.stat_sys_data_fully_connected_4g_plus,
-              R.drawable.stat_sys_data_fully_connected_4g_plus },
-            { R.drawable.stat_sys_data_fully_connected_4g_plus,
-              R.drawable.stat_sys_data_fully_connected_4g_plus,
-              R.drawable.stat_sys_data_fully_connected_4g_plus,
-              R.drawable.stat_sys_data_fully_connected_4g_plus }
-    };
-
     static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
-
-    // LTE branded "LTE"
-    static final int[][] DATA_LTE = {
-            { R.drawable.stat_sys_data_fully_connected_lte,
-                    R.drawable.stat_sys_data_fully_connected_lte,
-                    R.drawable.stat_sys_data_fully_connected_lte,
-                    R.drawable.stat_sys_data_fully_connected_lte },
-            { R.drawable.stat_sys_data_fully_connected_lte,
-                    R.drawable.stat_sys_data_fully_connected_lte,
-                    R.drawable.stat_sys_data_fully_connected_lte,
-                    R.drawable.stat_sys_data_fully_connected_lte }
-    };
-
     static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte;
     static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus;
 
     static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
-    static final int ROAMING_ICON = R.drawable.stat_sys_roaming;
+
     static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
     static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus;
     static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
@@ -219,29 +43,15 @@
     static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
     static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus;
     static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
-    static final int ICON_CARRIER_NETWORK_CHANGE =
-            R.drawable.stat_sys_signal_carrier_network_change_animation;
-
-    static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
-
-    static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte;
-    static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
-    static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g;
-    static final int QS_ICON_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
-    static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x;
-    static final int QS_ICON_CARRIER_NETWORK_CHANGE =
-            R.drawable.ic_qs_signal_carrier_network_change_animation;
-
-    static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled;
 
     static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
             "CARRIER_NETWORK_CHANGE",
-            TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE,
-            TelephonyIcons.QS_TELEPHONY_CARRIER_NETWORK_CHANGE,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.ICON_CARRIER_NETWORK_CHANGE,
-            TelephonyIcons.QS_ICON_CARRIER_NETWORK_CHANGE,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_carrier_network_change_mode,
             0,
@@ -251,12 +61,12 @@
 
     static final MobileIconGroup THREE_G = new MobileIconGroup(
             "3G",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_3g,
             TelephonyIcons.ICON_3G,
@@ -266,36 +76,36 @@
 
     static final MobileIconGroup WFC = new MobileIconGroup(
             "WFC",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             0, 0, false, 0
             );
 
     static final MobileIconGroup UNKNOWN = new MobileIconGroup(
             "Unknown",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             0, 0, false, 0
             );
 
     static final MobileIconGroup E = new MobileIconGroup(
             "E",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_edge,
             TelephonyIcons.ICON_E,
@@ -305,12 +115,12 @@
 
     static final MobileIconGroup ONE_X = new MobileIconGroup(
             "1X",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_cdma,
             TelephonyIcons.ICON_1X,
@@ -320,12 +130,12 @@
 
     static final MobileIconGroup G = new MobileIconGroup(
             "G",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_gprs,
             TelephonyIcons.ICON_G,
@@ -335,12 +145,12 @@
 
     static final MobileIconGroup H = new MobileIconGroup(
             "H",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_3_5g,
             TelephonyIcons.ICON_H,
@@ -350,12 +160,12 @@
 
     static final MobileIconGroup FOUR_G = new MobileIconGroup(
             "4G",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_4g,
             TelephonyIcons.ICON_4G,
@@ -365,12 +175,12 @@
 
     static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
             "4G+",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0,0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_4g_plus,
             TelephonyIcons.ICON_4G_PLUS,
@@ -380,12 +190,12 @@
 
     static final MobileIconGroup LTE = new MobileIconGroup(
             "LTE",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_lte,
             TelephonyIcons.ICON_LTE,
@@ -395,32 +205,17 @@
 
     static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
             "LTE+",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            null,
+            null,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
             0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            0,
+            0,
             AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
             R.string.accessibility_data_connection_lte_plus,
             TelephonyIcons.ICON_LTE_PLUS,
             true,
             TelephonyIcons.QS_DATA_LTE_PLUS
             );
-
-    static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
-            "DataDisabled",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.accessibility_cell_data_off,
-            TelephonyIcons.ICON_DATA_DISABLED,
-            false,
-            TelephonyIcons.QS_ICON_DATA_DISABLED
-            );
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
index 374408d..dfc3591 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
@@ -47,6 +47,7 @@
 
     static final int QS_WIFI_NO_NETWORK = R.drawable.ic_qs_wifi_no_network;
     static final int WIFI_NO_NETWORK = R.drawable.stat_sys_wifi_signal_null;
+    static final int WIFI_DISCONNECTED = R.drawable.stat_sys_wifi_signal_disconnected;
 
     static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 2104cb1..a773acf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -80,7 +80,7 @@
                 AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
                 WifiIcons.WIFI_NO_NETWORK,
                 WifiIcons.QS_WIFI_NO_NETWORK,
-                WifiIcons.WIFI_NO_NETWORK,
+                WifiIcons.WIFI_DISCONNECTED,
                 WifiIcons.QS_WIFI_NO_NETWORK,
                 AccessibilityContentDescriptions.WIFI_NO_CONNECTION
                 );
@@ -133,8 +133,7 @@
     @Override
     public void notifyListeners(SignalCallback callback) {
         // only show wifi in the cluster if connected or if wifi-only
-        boolean wifiVisible = mCurrentState.enabled
-                && (mCurrentState.connected || !mHasMobileData);
+        boolean wifiVisible = true;
         String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
         boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
         String contentDescription = getStringIfExists(getContentDescription());
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 15fcb38..1fcc40c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -38,6 +38,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.service.notification.StatusBarNotification;
+import android.support.annotation.NonNull;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.Log;
@@ -3574,7 +3575,9 @@
     }
 
     public void goToFullShade(long delay) {
-        mDismissView.setInvisible();
+        if (mDismissView != null) {
+            mDismissView.setInvisible();
+        }
         mEmptyShadeView.setInvisible();
         mGoToFullShadeNeedsAnimation = true;
         mGoToFullShadeDelay = delay;
@@ -3701,7 +3704,7 @@
         return -1;
     }
 
-    public void setDismissView(DismissView dismissView) {
+    public void setDismissView(@NonNull DismissView dismissView) {
         int index = -1;
         if (mDismissView != null) {
             index = indexOfChild(mDismissView);
@@ -3757,6 +3760,10 @@
     }
 
     public void updateDismissView(boolean visible) {
+        if (mDismissView == null) {
+            return;
+        }
+
         int oldVisibility = mDismissView.willBeGone() ? GONE : mDismissView.getVisibility();
         int newVisibility = visible ? VISIBLE : GONE;
         if (oldVisibility != newVisibility) {
@@ -3814,15 +3821,17 @@
     }
 
     public boolean isDismissViewNotGone() {
-        return mDismissView.getVisibility() != View.GONE && !mDismissView.willBeGone();
+        return mDismissView != null
+                && mDismissView.getVisibility() != View.GONE
+                && !mDismissView.willBeGone();
     }
 
     public boolean isDismissViewVisible() {
-        return mDismissView.isVisible();
+        return mDismissView != null && mDismissView.isVisible();
     }
 
     public int getDismissViewHeight() {
-        return mDismissView.getHeight() + mPaddingBetweenElements;
+        return mDismissView == null ? 0 : mDismissView.getHeight() + mPaddingBetweenElements;
     }
 
     public int getEmptyShadeViewHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index ba91ffd..b5db78d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -495,12 +495,12 @@
         int childCount = algorithmState.visibleChildren.size();
         float childrenOnTop = 0.0f;
         for (int i = childCount - 1; i >= 0; i--) {
-            updateChildZValue(i, childrenOnTop,
+            childrenOnTop = updateChildZValue(i, childrenOnTop,
                     resultState, algorithmState, ambientState);
         }
     }
 
-    protected void updateChildZValue(int i, float childrenOnTop,
+    protected float updateChildZValue(int i, float childrenOnTop,
             StackScrollState resultState, StackScrollAlgorithmState algorithmState,
             AmbientState ambientState) {
         ExpandableView child = algorithmState.visibleChildren.get(i);
@@ -538,6 +538,7 @@
         } else {
             childViewState.zTranslation = baseZ;
         }
+        return childrenOnTop;
     }
 
     public void setIsExpanded(boolean isExpanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 697cac9..b8b046b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -433,7 +433,7 @@
                 return false;
             }
         });
-        row.icon = (ImageButton) row.view.findViewById(R.id.volume_row_icon);
+        row.icon = row.view.findViewById(R.id.volume_row_icon);
         row.icon.setImageResource(iconRes);
         if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
             row.icon.setOnClickListener(new OnClickListener() {
@@ -465,6 +465,8 @@
                     row.userAttempt = 0;  // reset the grace period, slider updates immediately
                 }
             });
+        } else {
+            row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index 4e4832c..10b6ff5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -60,10 +60,10 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mIcon = (ImageView) findViewById(R.id.volume_zen_icon);
-        mSummaryLine1 = (TextView) findViewById(R.id.volume_zen_summary_line_1);
-        mSummaryLine2 = (TextView) findViewById(R.id.volume_zen_summary_line_2);
-        mEndNowButton = (TextView) findViewById(R.id.volume_zen_end_now);
+        mIcon = findViewById(R.id.volume_zen_icon);
+        mSummaryLine1 = findViewById(R.id.volume_zen_summary_line_1);
+        mSummaryLine2 = findViewById(R.id.volume_zen_summary_line_2);
+        mEndNowButton = findViewById(R.id.volume_zen_end_now);
         mConfigurableTexts.add(mSummaryLine1);
         mConfigurableTexts.add(mSummaryLine2);
         mConfigurableTexts.add(mEndNowButton, R.string.volume_zen_end_now);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
index 6b47ada..e1f56a47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java
@@ -53,7 +53,7 @@
     @Test
     public void testDrawImageButNoTextIfPluggedIn() {
         mBatteryMeter.setBatteryLevel(0);
-        mBatteryMeter.setPluggedIn(true);
+        mBatteryMeter.setCharging(true);
         final Canvas canvas = mock(Canvas.class);
         mBatteryMeter.draw(canvas);
         verify(canvas, atLeastOnce()).drawPath(any(), any());
@@ -63,7 +63,7 @@
     @Test
     public void testDrawTextIfNotPluggedIn() {
         mBatteryMeter.setBatteryLevel(0);
-        mBatteryMeter.setPluggedIn(false);
+        mBatteryMeter.setCharging(false);
         final Canvas canvas = mock(Canvas.class);
         mBatteryMeter.draw(canvas);
         verify(canvas, times(1)).drawText(anyString(), anyFloat(), anyFloat(), any());
@@ -72,7 +72,7 @@
     @Test
     public void testDrawNoTextIfPowerSaveEnabled() {
         mBatteryMeter.setBatteryLevel(0);
-        mBatteryMeter.setPluggedIn(false);
+        mBatteryMeter.setCharging(false);
         mBatteryMeter.setPowerSave(true);
         final Canvas canvas = mock(Canvas.class);
         mBatteryMeter.draw(canvas);
@@ -84,7 +84,7 @@
         int criticalLevel = mResources.getInteger(
                 com.android.internal.R.integer.config_criticalBatteryWarningLevel);
         mBatteryMeter.setBatteryLevel(criticalLevel);
-        mBatteryMeter.setPluggedIn(false);
+        mBatteryMeter.setCharging(false);
         final Canvas canvas = mock(Canvas.class);
         mBatteryMeter.draw(canvas);
         String warningString = mResources.getString(R.string.battery_meter_very_low_overlay_symbol);
@@ -96,7 +96,7 @@
         int criticalLevel = mResources.getInteger(
                 com.android.internal.R.integer.config_criticalBatteryWarningLevel);
         mBatteryMeter.setBatteryLevel(criticalLevel + 1);
-        mBatteryMeter.setPluggedIn(false);
+        mBatteryMeter.setCharging(false);
         final Canvas canvas = mock(Canvas.class);
         mBatteryMeter.draw(canvas);
         String warningString = mResources.getString(R.string.battery_meter_very_low_overlay_symbol);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
new file mode 100644
index 0000000..1b5d4a4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ExpandHelperTest extends SysuiTestCase {
+
+    private ExpandableNotificationRow mRow;
+    private ExpandHelper mExpandHelper;
+    private ExpandHelper.Callback mCallback;
+
+    @Before
+    @UiThreadTest
+    public void setUp() {
+        Context context = getContext();
+        mRow = new NotificationTestHelper(context).createRow();
+        mCallback = mock(ExpandHelper.Callback.class);
+        mExpandHelper = new ExpandHelper(context, mCallback, 10, 100);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testAnimationDoesntClearViewIfNewExpansionStarted() {
+        when(mCallback.getMaxExpandHeight(any())).thenReturn(100);
+        mExpandHelper.startExpanding(mRow, 0);
+        mExpandHelper.finishExpanding(false, 0);
+        mExpandHelper.startExpanding(mRow, 0);
+        ObjectAnimator scaleAnimation = mExpandHelper.getScaleAnimation();
+        scaleAnimation.end();
+        mExpandHelper.updateExpansion();
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index 1ff373c..ff644d8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -40,6 +40,15 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+/*
+ * Compile and run the whole SystemUI test suite:
+   runtest --path frameworks/base/packages/SystemUI/tests
+ *
+ * Compile and run just this class:
+   runtest --path \
+   frameworks/base/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+*/
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class QSSecurityFooterTest extends SysuiTestCase {
@@ -47,11 +56,11 @@
     private final String MANAGING_ORGANIZATION = "organization";
     private final String DEVICE_OWNER_PACKAGE = "TestDPC";
     private final String VPN_PACKAGE = "TestVPN";
+    private final String VPN_PACKAGE_2 = "TestVPN 2";
 
     private ViewGroup mRootView;
     private TextView mFooterText;
     private TestableImageView mFooterIcon;
-    private TestableImageView mFooterIcon2;
     private QSSecurityFooter mFooter;
     private SecurityController mSecurityController = mock(SecurityController.class);
 
@@ -69,15 +78,12 @@
         mRootView = (ViewGroup) mFooter.getView();
         mFooterText = (TextView) mRootView.findViewById(R.id.footer_text);
         mFooterIcon = (TestableImageView) mRootView.findViewById(R.id.footer_icon);
-        mFooterIcon2 = (TestableImageView) mRootView.findViewById(R.id.footer_icon2);
         mFooter.setHostEnvironment(null);
     }
 
     @Test
     public void testUnmanaged() {
         when(mSecurityController.isDeviceManaged()).thenReturn(false);
-        when(mSecurityController.isVpnEnabled()).thenReturn(false);
-        when(mSecurityController.isVpnBranded()).thenReturn(false);
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
@@ -91,8 +97,12 @@
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
-        assertEquals(mContext.getString(R.string.do_disclosure_generic), mFooterText.getText());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management),
+                     mFooterText.getText());
         assertEquals(View.VISIBLE, mRootView.getVisibility());
+        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
+        // -1 == never set.
+        assertEquals(-1, mFooterIcon.getLastImageResource());
     }
 
     @Test
@@ -103,37 +113,100 @@
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
-        assertEquals(mContext.getString(R.string.do_disclosure_with_name, MANAGING_ORGANIZATION),
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management,
+                                        MANAGING_ORGANIZATION),
                 mFooterText.getText());
         assertEquals(View.VISIBLE, mRootView.getVisibility());
+        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
+        // -1 == never set.
+        assertEquals(-1, mFooterIcon.getLastImageResource());
     }
 
     @Test
     public void testNetworkLoggingEnabled() {
         when(mSecurityController.isDeviceManaged()).thenReturn(true);
         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
-        when(mSecurityController.isVpnEnabled()).thenReturn(false);
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
-        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
-        assertEquals(R.drawable.ic_qs_network_logging, mFooterIcon.getLastImageResource());
-        assertEquals(View.INVISIBLE, mFooterIcon2.getVisibility());
-    }
-
-    @Test
-    public void testVpnEnabled() {
-        when(mSecurityController.isDeviceManaged()).thenReturn(true);
-        when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(false);
-        when(mSecurityController.isVpnEnabled()).thenReturn(true);
-        when(mSecurityController.isVpnBranded()).thenReturn(false);
-        mFooter.refreshState();
-
-        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
+                mFooterText.getText());
         assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
         // -1 == never set.
         assertEquals(-1, mFooterIcon.getLastImageResource());
-        assertEquals(View.INVISIBLE, mFooterIcon2.getVisibility());
+
+        // Same situation, but with organization name set
+        when(mSecurityController.getDeviceOwnerOrganizationName())
+                .thenReturn(MANAGING_ORGANIZATION);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_named_management_monitoring,
+                             MANAGING_ORGANIZATION),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testManagedCACertsInstalled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(true);
+        when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
+                mFooterText.getText());
+    }
+
+    @Test
+    public void testManagedOneVpnEnabled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(true);
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_named_vpn,
+                                        VPN_PACKAGE),
+                     mFooterText.getText());
+        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+
+        // Same situation, but with organization name set
+        when(mSecurityController.getDeviceOwnerOrganizationName())
+                .thenReturn(MANAGING_ORGANIZATION);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(
+                              R.string.quick_settings_disclosure_named_management_named_vpn,
+                              MANAGING_ORGANIZATION, VPN_PACKAGE),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testManagedTwoVpnsEnabled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(true);
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
+        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_vpns),
+                     mFooterText.getText());
+        assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+
+        // Same situation, but with organization name set
+        when(mSecurityController.getDeviceOwnerOrganizationName())
+                .thenReturn(MANAGING_ORGANIZATION);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_management_vpns,
+                                        MANAGING_ORGANIZATION),
+                     mFooterText.getText());
     }
 
     @Test
@@ -141,15 +214,101 @@
         when(mSecurityController.isDeviceManaged()).thenReturn(true);
         when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
         when(mSecurityController.isVpnEnabled()).thenReturn(true);
-        when(mSecurityController.isVpnBranded()).thenReturn(false);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn("VPN Test App");
         mFooter.refreshState();
 
         waitForIdleSync(mFooter.mHandler);
         assertEquals(View.VISIBLE, mFooterIcon.getVisibility());
-        assertEquals(View.VISIBLE, mFooterIcon2.getVisibility());
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_management_monitoring),
+                mFooterText.getText());
+    }
+
+    @Test
+    public void testWorkProfileCACertsInstalled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(false);
+        when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
         // -1 == never set.
         assertEquals(-1, mFooterIcon.getLastImageResource());
-        assertEquals(-1, mFooterIcon2.getLastImageResource());
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_managed_profile_monitoring),
+                     mFooterText.getText());
+
+        // Same situation, but with organization name set
+        when(mSecurityController.getWorkProfileOrganizationName())
+                .thenReturn(MANAGING_ORGANIZATION);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_named_managed_profile_monitoring,
+                             MANAGING_ORGANIZATION),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testCACertsInstalled() {
+        when(mSecurityController.isDeviceManaged()).thenReturn(false);
+        when(mSecurityController.hasCACertInCurrentUser()).thenReturn(true);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        // -1 == never set.
+        assertEquals(-1, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_monitoring),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testTwoVpnsEnabled() {
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
+        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_vpns),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testWorkProfileVpnEnabled() {
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_managed_profile_named_vpn,
+                             VPN_PACKAGE_2),
+                     mFooterText.getText());
+    }
+
+    @Test
+    public void testVpnEnabled() {
+        when(mSecurityController.isVpnEnabled()).thenReturn(true);
+        when(mSecurityController.getPrimaryVpnName()).thenReturn(VPN_PACKAGE);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(R.drawable.ic_qs_vpn, mFooterIcon.getLastImageResource());
+        assertEquals(mContext.getString(R.string.quick_settings_disclosure_named_vpn,
+                                        VPN_PACKAGE),
+                     mFooterText.getText());
+
+        when(mSecurityController.hasWorkProfile()).thenReturn(true);
+        mFooter.refreshState();
+
+        waitForIdleSync(mFooter.mHandler);
+        assertEquals(mContext.getString(
+                             R.string.quick_settings_disclosure_personal_profile_named_vpn,
+                             VPN_PACKAGE),
+                     mFooterText.getText());
     }
 
     @Test
@@ -160,8 +319,7 @@
                         null /* primaryVpn */,
                         null /* profileVpn */,
                         null /* deviceOwnerOrganization */,
-                        false /* hasProfileOwner */,
-                        false /* isBranded */));
+                        false /* hasProfileOwner */));
     }
 
     @Test
@@ -172,8 +330,7 @@
                         VPN_PACKAGE,
                         null /* profileVpn */,
                         null /* deviceOwnerOrganization */,
-                        false /* hasProfileOwner */,
-                        false /* isBranded */));
+                        false /* hasProfileOwner */));
     }
 
     @Test
@@ -184,8 +341,7 @@
                         null /* primaryVpn */,
                         null /* profileVpn */,
                         MANAGING_ORGANIZATION,
-                        false /* hasProfileOwner */,
-                        false /* isBranded */));
+                        false /* hasProfileOwner */));
     }
 
     @Test
@@ -196,8 +352,7 @@
                         VPN_PACKAGE,
                         null /* profileVpn */,
                         MANAGING_ORGANIZATION,
-                        false /* hasProfileOwner */,
-                        false /* isBranded */));
+                        false /* hasProfileOwner */));
     }
 
     private CharSequence getExpectedMessage(boolean hasDeviceOwnerOrganization, boolean hasVPN) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 3ed1681..f6c75a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -114,33 +114,26 @@
         boolean wide = true;
         int subId = 5;
         boolean roaming = true;
-        mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription,
-                description, wide, subId, roaming);
+        boolean isEmergency = true;
+        mHandler.setMobileDataIndicators(status, type, in, out, typeDescription,
+                subId, roaming, isEmergency);
         waitForCallbacks();
 
         ArgumentCaptor<IconState> statusArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<IconState> qsArg = ArgumentCaptor.forClass(IconState.class);
         ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
-        ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class);
         ArgumentCaptor<Boolean> inArg = ArgumentCaptor.forClass(Boolean.class);
         ArgumentCaptor<Boolean> outArg = ArgumentCaptor.forClass(Boolean.class);
         ArgumentCaptor<String> typeContentArg = ArgumentCaptor.forClass(String.class);
-        ArgumentCaptor<String> descArg = ArgumentCaptor.forClass(String.class);
-        ArgumentCaptor<Boolean> wideArg = ArgumentCaptor.forClass(Boolean.class);
         ArgumentCaptor<Integer> subIdArg = ArgumentCaptor.forClass(Integer.class);
         Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(),
-                qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(),
-                outArg.capture(), typeContentArg.capture(), descArg.capture(), wideArg.capture(),
-                subIdArg.capture(), eq(roaming));
+                typeIconArg.capture(), inArg.capture(),
+                outArg.capture(), typeContentArg.capture(),
+                subIdArg.capture(), eq(roaming), eq(isEmergency));
         assertEquals(status, statusArg.getValue());
-        assertEquals(qs, qsArg.getValue());
         assertEquals(type, (int) typeIconArg.getValue());
-        assertEquals(qsType, (int) qsTypeIconArg.getValue());
         assertEquals(in, (boolean) inArg.getValue());
         assertEquals(out, (boolean) outArg.getValue());
         assertEquals(typeDescription, typeContentArg.getValue());
-        assertEquals(description, descArg.getValue());
-        assertEquals(wide, (boolean) wideArg.getValue());
         assertEquals(subId, (int) subIdArg.getValue());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 19b4b17..b39171e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -29,8 +29,10 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
+
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.settingslib.net.DataUsageController;
+import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
@@ -44,8 +46,6 @@
 import org.junit.runner.Description;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -66,12 +66,10 @@
 public class NetworkControllerBaseTest extends SysuiTestCase {
     private static final String TAG = "NetworkControllerBaseTest";
     protected static final int DEFAULT_LEVEL = 2;
-    protected static final int DEFAULT_SIGNAL_STRENGTH =
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL];
-    protected static final int DEFAULT_QS_SIGNAL_STRENGTH =
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL];
+    protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL;
+    protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL;
     protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G;
-    protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_ICON_3G;
+    protected static final int DEFAULT_QS_ICON = DEFAULT_ICON;
 
     protected NetworkControllerImpl mNetworkController;
     protected MobileSignalController mMobileSignalController;
@@ -118,7 +116,7 @@
 
         when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true);
         when(mMockCm.getDefaultNetworkCapabilitiesForUser(0)).thenReturn(
-                new NetworkCapabilities[] { mNetCapabilities });
+                new NetworkCapabilities[]{mNetCapabilities});
 
         mSignalStrength = mock(SignalStrength.class);
         mServiceState = mock(ServiceState.class);
@@ -176,17 +174,17 @@
     }
 
     protected NetworkControllerImpl setUpNoMobileData() {
-      when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
-      NetworkControllerImpl networkControllerNoMobile
-              = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager, mMockTm,
-                        mMockWm, mMockSm, mConfig, mContext.getMainLooper(), mCallbackHandler,
-                        mock(AccessPointControllerImpl.class),
-                        mock(DataUsageController.class), mMockSubDefaults,
-                        mock(DeviceProvisionedController.class));
+        when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
+        NetworkControllerImpl networkControllerNoMobile
+                = new NetworkControllerImpl(mContext, mMockCm, mMockNetworkScoreManager, mMockTm,
+                mMockWm, mMockSm, mConfig, mContext.getMainLooper(), mCallbackHandler,
+                mock(AccessPointControllerImpl.class),
+                mock(DataUsageController.class), mMockSubDefaults,
+                mock(DeviceProvisionedController.class));
 
-      setupNetworkController();
+        setupNetworkController();
 
-      return networkControllerNoMobile;
+        return networkControllerNoMobile;
 
     }
 
@@ -309,14 +307,15 @@
         ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class);
 
         Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
-                    any(),
-                    iconArg.capture(),
-                    anyInt(),
-                    typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(),
-                    anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean());
+                iconArg.capture(),
+                typeIconArg.capture(),
+                dataInArg.capture(), dataOutArg.capture(),
+                anyString(), anyInt(), anyBoolean(), anyBoolean());
         IconState iconState = iconArg.getValue();
+        int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
+                false);
         assertEquals("Visibility in, quick settings", visible, iconState.visible);
-        assertEquals("Signal icon in, quick settings", icon, iconState.icon);
+        assertEquals("Signal icon in, quick settings", state, iconState.icon);
         assertEquals("Data icon in, quick settings", typeIcon, (int) typeIconArg.getValue());
         assertEquals("Data direction in, in quick settings", dataIn,
                 (boolean) dataInArg.getValue());
@@ -330,58 +329,60 @@
 
     protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
             boolean roaming) {
+        verifyLastMobileDataIndicators(visible, icon, typeIcon, roaming, true);
+    }
+
+    protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
+            boolean roaming, boolean inet) {
         ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
         ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
 
         // TODO: Verify all fields.
         Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
                 iconArg.capture(),
-                any(),
                 typeIconArg.capture(),
-                anyInt(), anyBoolean(), anyBoolean(), anyString(), anyString(), anyBoolean(),
-                anyInt(), eq(roaming));
+                anyBoolean(), anyBoolean(), anyString(),
+                anyInt(), eq(roaming), anyBoolean());
         IconState iconState = iconArg.getValue();
 
-        assertEquals("Signal icon in status bar", icon, iconState.icon);
+        int state = icon == -1 ? 0
+                : SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS, !inet);
+        assertEquals("Signal icon in status bar", state, iconState.icon);
         assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
         assertEquals("Visibility in status bar", visible, iconState.visible);
     }
 
     protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
-            boolean qsVisible, int qsIcon, int qsTypeIcon, boolean dataIn, boolean dataOut) {
+            boolean qsVisible, boolean dataIn, boolean dataOut) {
         ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
         ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
-        ArgumentCaptor<IconState> qsIconArg = ArgumentCaptor.forClass(IconState.class);
-        ArgumentCaptor<Integer> qsTypeIconArg = ArgumentCaptor.forClass(Integer.class);
         ArgumentCaptor<Boolean> dataInArg = ArgumentCaptor.forClass(Boolean.class);
         ArgumentCaptor<Boolean> dataOutArg = ArgumentCaptor.forClass(Boolean.class);
 
         Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
                 iconArg.capture(),
-                qsIconArg.capture(),
                 typeIconArg.capture(),
-                qsTypeIconArg.capture(),
                 dataInArg.capture(),
                 dataOutArg.capture(),
-                anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean());
+                anyString(), anyInt(), anyBoolean(), anyBoolean());
 
         IconState iconState = iconArg.getValue();
 
+        int state = SignalDrawable.getState(icon, SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
+                false);
         assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
-        assertEquals("Signal icon in status bar", icon, iconState.icon);
+        assertEquals("Signal icon in status bar", state, iconState.icon);
         assertEquals("Visibility in status bar", visible, iconState.visible);
 
-        iconState = qsIconArg.getValue();
         assertEquals("Visibility in quick settings", qsVisible, iconState.visible);
-        assertEquals("Signal icon in quick settings", qsIcon, iconState.icon);
-        assertEquals("Data icon in quick settings", qsTypeIcon, (int) qsTypeIconArg.getValue());
+        assertEquals("Signal icon in quick settings", state, iconState.icon);
         assertEquals("Data direction in in quick settings", dataIn,
                 (boolean) dataInArg.getValue());
         assertEquals("Data direction out in quick settings", dataOut,
                 (boolean) dataOutArg.getValue());
     }
 
-   protected void assertNetworkNameEquals(String expected) {
-       assertEquals("Network name", expected, mMobileSignalController.getState().networkName);
-   }
+    protected void assertNetworkNameEquals(String expected) {
+        assertEquals("Network name", expected, mMobileSignalController.getState().networkName);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index e47f750..6470c11 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -1,5 +1,9 @@
 package com.android.systemui.statusbar.policy;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -11,10 +15,14 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.settingslib.net.DataUsageController;
+import com.android.systemui.statusbar.phone.SignalDrawable;
+import com.android.systemui.statusbar.policy.NetworkController.IconState;
 
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -24,7 +32,7 @@
     public void test3gDataIcon() {
         setupDefaultSignal();
 
-        verifyDataIndicators(TelephonyIcons.DATA_3G[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_3G,
                 TelephonyIcons.QS_DATA_3G);
     }
 
@@ -34,7 +42,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_GSM);
 
-        verifyDataIndicators(TelephonyIcons.DATA_G[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_G,
                 TelephonyIcons.QS_DATA_G);
     }
 
@@ -44,7 +52,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_CDMA);
 
-        verifyDataIndicators(TelephonyIcons.DATA_1X[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_1X,
                 TelephonyIcons.QS_DATA_1X);
     }
 
@@ -54,7 +62,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_EDGE);
 
-        verifyDataIndicators(TelephonyIcons.DATA_E[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_E,
                 TelephonyIcons.QS_DATA_E);
     }
 
@@ -64,7 +72,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_LTE);
 
-        verifyDataIndicators(TelephonyIcons.DATA_LTE[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_LTE,
                 TelephonyIcons.QS_DATA_LTE);
     }
 
@@ -74,7 +82,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_HSPA);
 
-        verifyDataIndicators(TelephonyIcons.DATA_H[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_H,
                 TelephonyIcons.QS_DATA_H);
     }
 
@@ -103,7 +111,7 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_LTE);
 
-        verifyDataIndicators(TelephonyIcons.DATA_4G[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_4G,
                 TelephonyIcons.QS_DATA_4G);
     }
 
@@ -116,8 +124,11 @@
         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
         setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
 
-        verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED,
-                TelephonyIcons.QS_ICON_DATA_DISABLED);
+        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
+        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
+                iconArg.capture(), anyInt(), anyBoolean(), anyBoolean(), any(), anyInt(),
+                anyBoolean(), anyBoolean());
+        assertEquals(SignalDrawable.STATE_CUT, SignalDrawable.getState(iconArg.getValue().icon));
     }
 
     @Test
@@ -129,9 +140,14 @@
         setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
         when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false);
         mUserCallback.onUserSetupChanged();
+        waitForIdleSync();
 
         // Don't show the X until the device is setup.
-        verifyDataIndicators(0, 0);
+        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
+        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setMobileDataIndicators(
+                iconArg.capture(), anyInt(), anyBoolean(), anyBoolean(), any(), anyInt(),
+                anyBoolean(), anyBoolean());
+        assertNotEquals(SignalDrawable.STATE_CUT, SignalDrawable.getState(iconArg.getValue().icon));
     }
 
     @Test
@@ -147,7 +163,7 @@
         // the after work.
         mNetworkController.handleConfigurationChanged();
 
-        verifyDataIndicators(TelephonyIcons.DATA_4G[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_4G,
                 TelephonyIcons.QS_DATA_4G);
     }
 
@@ -157,13 +173,13 @@
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
                 TelephonyManager.NETWORK_TYPE_LTE);
 
-        verifyDataIndicators(TelephonyIcons.DATA_LTE[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_LTE,
                 TelephonyIcons.QS_DATA_LTE);
 
         when(mServiceState.getDataNetworkType())
                 .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
         updateServiceState();
-        verifyDataIndicators(TelephonyIcons.DATA_H[1][0 /* No direction */],
+        verifyDataIndicators(TelephonyIcons.ICON_H,
                 TelephonyIcons.QS_DATA_H);
     }
 
@@ -181,12 +197,12 @@
         updateDataActivity(direction);
 
         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, DEFAULT_ICON, true,
-                DEFAULT_QS_SIGNAL_STRENGTH, DEFAULT_QS_ICON, in, out);
+                in, out);
     }
 
     private void verifyDataIndicators(int dataIcon, int qsDataIcon) {
         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, dataIcon,
-                true, DEFAULT_QS_SIGNAL_STRENGTH, qsDataIcon, false,
+                true, false,
                 false);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 1555856..e542c37 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -30,6 +30,7 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SignalDrawable;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -60,7 +61,7 @@
                 mMockSubDefaults, mock(DeviceProvisionedController.class));
         setupNetworkController();
 
-        verifyLastMobileDataIndicators(false, 0, 0);
+        verifyLastMobileDataIndicators(false, -1, 0);
     }
 
     @Test
@@ -132,45 +133,45 @@
 
     @Test
     public void testSignalStrength() {
-        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-                testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
+        for (int testStrength = 0;
+                testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) {
             setupDefaultSignal();
             setLevel(testStrength);
 
             verifyLastMobileDataIndicators(true,
-                    TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][testStrength], DEFAULT_ICON);
+                    testStrength, DEFAULT_ICON);
 
             // Verify low inet number indexing.
             setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, true);
             verifyLastMobileDataIndicators(true,
-                    TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[0][testStrength], DEFAULT_ICON);
+                    testStrength, DEFAULT_ICON, false, false);
         }
     }
 
     @Test
     public void testCdmaSignalStrength() {
-        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-                testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
+        for (int testStrength = 0;
+                testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) {
             setupDefaultSignal();
             setCdma();
             setLevel(testStrength);
 
             verifyLastMobileDataIndicators(true,
-                    TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][testStrength],
-                    TelephonyIcons.DATA_1X[1][0 /* No direction */]);
+                    testStrength,
+                    TelephonyIcons.ICON_1X);
         }
     }
 
     @Test
     public void testSignalRoaming() {
-        for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-                testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
+        for (int testStrength = 0;
+                testStrength < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; testStrength++) {
             setupDefaultSignal();
             setGsmRoaming(true);
             setLevel(testStrength);
 
             verifyLastMobileDataIndicators(true,
-                    TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][testStrength],
+                    testStrength,
                     DEFAULT_ICON, true);
         }
     }
@@ -185,8 +186,8 @@
             setLevel(testStrength);
 
             verifyLastMobileDataIndicators(true,
-                    TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][testStrength],
-                    TelephonyIcons.DATA_1X[1][0 /* No direction */], true);
+                    testStrength,
+                    TelephonyIcons.ICON_1X, true);
         }
     }
 
@@ -198,7 +199,7 @@
             setLevel(testStrength);
 
             verifyLastQsMobileDataIndicators(true,
-                    TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][testStrength],
+                    testStrength,
                     DEFAULT_QS_ICON, false, false);
         }
     }
@@ -212,8 +213,8 @@
             setLevel(testStrength);
 
             verifyLastQsMobileDataIndicators(true,
-                    TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][testStrength],
-                    TelephonyIcons.QS_ICON_1X, false, false);
+                    testStrength,
+                    TelephonyIcons.ICON_1X, false, false);
         }
     }
 
@@ -223,7 +224,7 @@
         setConnectivity(mMobileSignalController.mTransportType, false, false);
         setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true);
 
-        verifyLastMobileDataIndicators(true, TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][2], 0);
+        verifyLastMobileDataIndicators(true, DEFAULT_LEVEL, 0);
     }
 
     // Some tests of actual NetworkController code, just internals not display stuff
@@ -418,7 +419,7 @@
         updateDataActivity(TelephonyManager.DATA_ACTIVITY_IN);
 
         verifyLastQsMobileDataIndicators(true /* visible */,
-                TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL] /* icon */,
+                DEFAULT_LEVEL /* icon */,
                 DEFAULT_QS_ICON /* typeIcon */,
                 true /* dataIn */,
                 false /* dataOut */);
@@ -432,11 +433,10 @@
       updateDataActivity(TelephonyManager.DATA_ACTIVITY_OUT);
 
       verifyLastQsMobileDataIndicators(true /* visible */,
-              TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL] /* icon */,
-              DEFAULT_QS_ICON /* typeIcon */,
+              DEFAULT_LEVEL /* icon */,
+              DEFAULT_ICON /* typeIcon */,
               false /* dataIn */,
               true /* dataOut */);
-
     }
 
     @Test
@@ -446,7 +446,7 @@
       updateDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
 
       verifyLastQsMobileDataIndicators(true /* visible */,
-              TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL] /* icon */,
+              DEFAULT_LEVEL /* icon */,
               DEFAULT_QS_ICON /* typeIcon */,
               true /* dataIn */,
               true /* dataOut */);
@@ -460,7 +460,7 @@
       updateDataActivity(TelephonyManager.DATA_ACTIVITY_NONE);
 
       verifyLastQsMobileDataIndicators(true /* visible */,
-              TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL] /* icon */,
+              DEFAULT_LEVEL /* icon */,
               DEFAULT_QS_ICON /* typeIcon */,
               false /* dataIn */,
               false /* dataOut */);
@@ -476,7 +476,7 @@
 
       // Verify baseline
       verifyLastMobileDataIndicators(true /* visible */,
-              TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */,
+              strength /* strengthIcon */,
               DEFAULT_ICON /* typeIcon */);
 
       // API call is made
@@ -484,7 +484,7 @@
 
       // Carrier network change is true, show special indicator
       verifyLastMobileDataIndicators(true /* visible */,
-              TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE[0][0] /* strengthIcon */,
+              SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS),
               0 /* typeIcon */);
 
       // Revert back
@@ -492,7 +492,7 @@
 
       // Verify back in previous state
       verifyLastMobileDataIndicators(true /* visible */,
-              TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */,
+              strength /* strengthIcon */,
               DEFAULT_ICON /* typeIcon */);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 483a837..edfa326 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -62,7 +62,7 @@
     public void testWifiIcon() {
         String testSsid = "Test SSID";
         setWifiEnabled(true);
-        verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
+        verifyLastWifiIcon(true, WifiIcons.WIFI_DISCONNECTED);
 
         setWifiState(true, testSsid);
         verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
@@ -218,7 +218,7 @@
         setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true);
         setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
         verifyLastMobileDataIndicators(true,
-                TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][DEFAULT_LEVEL],
+                DEFAULT_LEVEL,
                 0, true);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
index 29d7f1c..838a273 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeLocationController.java
@@ -17,15 +17,20 @@
 import android.testing.LeakCheck;
 
 import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.LocationController.LocationSettingsChangeCallback;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
 
-public class FakeLocationController extends BaseLeakChecker<LocationSettingsChangeCallback>
+public class FakeLocationController extends BaseLeakChecker<LocationChangeCallback>
         implements LocationController {
     public FakeLocationController(LeakCheck test) {
         super(test, "location");
     }
 
     @Override
+    public boolean isLocationActive() {
+        return false;
+    }
+
+    @Override
     public boolean isLocationEnabled() {
         return false;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
index 157b8a0..fee5e32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeSecurityController.java
@@ -36,6 +36,11 @@
     }
 
     @Override
+    public boolean hasWorkProfile() {
+        return false;
+    }
+
+    @Override
     public String getDeviceOwnerName() {
         return null;
     }
@@ -51,6 +56,11 @@
     }
 
     @Override
+    public CharSequence getWorkProfileOrganizationName() {
+        return null;
+    }
+
+    @Override
     public boolean isNetworkLoggingEnabled() {
         return false;
     }
@@ -76,11 +86,21 @@
     }
 
     @Override
-    public String getProfileVpnName() {
+    public String getWorkProfileVpnName() {
         return null;
     }
 
     @Override
+    public boolean hasCACertInCurrentUser() {
+        return false;
+    }
+
+    @Override
+    public boolean hasCACertInWorkProfile() {
+        return false;
+    }
+
+    @Override
     public void onUserSwitched(int newUserId) {
 
     }
diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java
index 78fd174..63b6a11 100644
--- a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java
+++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java
@@ -49,21 +49,21 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
 
-        Button addpbtn = (Button) findViewById(R.id.addpkg);
-        Button procbtn = (Button) findViewById(R.id.procmsg);
-        Button delbtn = (Button) findViewById(R.id.delpkg);
+        Button addpbtn = findViewById(R.id.addpkg);
+        Button procbtn = findViewById(R.id.procmsg);
+        Button delbtn = findViewById(R.id.delpkg);
 
         Log.v(LOG_TAG, "activity created!!");
 
         addpbtn.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
-                    EditText app_id = (EditText) findViewById(R.id.app_id);
-                    EditText cont = (EditText) findViewById(R.id.cont);
-                    EditText pkg = (EditText) findViewById(R.id.pkg);
-                    EditText cls = (EditText) findViewById(R.id.cls);
-                    RadioButton act = (RadioButton) findViewById(R.id.act);
-                    CheckBox sig = (CheckBox) findViewById(R.id.sig);
-                    CheckBox ftr = (CheckBox) findViewById(R.id.ftr);
+                    EditText app_id = findViewById(R.id.app_id);
+                    EditText cont = findViewById(R.id.cont);
+                    EditText pkg = findViewById(R.id.pkg);
+                    EditText cls = findViewById(R.id.cls);
+                    RadioButton act = findViewById(R.id.act);
+                    CheckBox sig = findViewById(R.id.sig);
+                    CheckBox ftr = findViewById(R.id.ftr);
 
                     try {
                         if (!mWapPushMan.addPackage(
@@ -93,11 +93,11 @@
 
         delbtn.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
-                    EditText app_id = (EditText) findViewById(R.id.app_id);
-                    EditText cont = (EditText) findViewById(R.id.cont);
-                    EditText pkg = (EditText) findViewById(R.id.pkg);
-                    EditText cls = (EditText) findViewById(R.id.cls);
-                    // CheckBox delall = (CheckBox) findViewById(R.id.delall);
+                    EditText app_id = findViewById(R.id.app_id);
+                    EditText cont = findViewById(R.id.cont);
+                    EditText pkg = findViewById(R.id.pkg);
+                    EditText cls = findViewById(R.id.cls);
+                    // CheckBox delall = findViewById(R.id.delall);
                     // Log.d(LOG_TAG, "button clicked");
 
                     try {
@@ -115,9 +115,9 @@
 
         procbtn.setOnClickListener(new View.OnClickListener() {
                 public void onClick(View v) {
-                    EditText pdu = (EditText) findViewById(R.id.pdu);
-                    EditText app_id = (EditText) findViewById(R.id.app_id);
-                    EditText cont = (EditText) findViewById(R.id.cont);
+                    EditText pdu = findViewById(R.id.pdu);
+                    EditText app_id = findViewById(R.id.app_id);
+                    EditText cont = findViewById(R.id.cont);
 
                     // WapPushOverSms wap = new WapPushOverSms();
                     // wap.dispatchWapPdu(strToHex(pdu.getText().toString()));
diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
index a319beb..f878b4d 100644
--- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
+++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
@@ -88,7 +88,7 @@
     protected void init() {
         setContentView(R.layout.wallpaper_cropper);
 
-        mCropView = (CropView) findViewById(R.id.cropView);
+        mCropView = findViewById(R.id.cropView);
 
         Intent cropIntent = getIntent();
         final Uri imageUri = cropIntent.getData();
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 0acbb02..f6d3f48 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1324,12 +1324,10 @@
     SkBitmap bitmap;
     GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
 
-    bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
     jlong id = (jlong)(uintptr_t)rsAllocationCreateFromBitmap((RsContext)con,
                                                   (RsType)type, (RsAllocationMipmapControl)mip,
                                                   ptr, bitmap.getSize(), usage);
-    bitmap.unlockPixels();
     return id;
 }
 
@@ -1340,12 +1338,10 @@
     SkBitmap bitmap;
     GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
 
-    bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
     jlong id = (jlong)(uintptr_t)rsAllocationCreateTyped((RsContext)con,
                                             (RsType)type, (RsAllocationMipmapControl)mip,
                                             (uint32_t)usage, (uintptr_t)ptr);
-    bitmap.unlockPixels();
     return id;
 }
 
@@ -1356,12 +1352,10 @@
     SkBitmap bitmap;
     GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
 
-    bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
     jlong id = (jlong)(uintptr_t)rsAllocationCubeCreateFromBitmap((RsContext)con,
                                                       (RsType)type, (RsAllocationMipmapControl)mip,
                                                       ptr, bitmap.getSize(), usage);
-    bitmap.unlockPixels();
     return id;
 }
 
@@ -1373,12 +1367,10 @@
     int w = bitmap.width();
     int h = bitmap.height();
 
-    bitmap.lockPixels();
     const void* ptr = bitmap.getPixels();
     rsAllocation2DData((RsContext)con, (RsAllocation)alloc, 0, 0,
                        0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X,
                        w, h, ptr, bitmap.getSize(), 0);
-    bitmap.unlockPixels();
 }
 
 static void
@@ -1387,10 +1379,8 @@
     SkBitmap bitmap;
     GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap);
 
-    bitmap.lockPixels();
     void* ptr = bitmap.getPixels();
     rsAllocationCopyToBitmap((RsContext)con, (RsAllocation)alloc, ptr, bitmap.getSize());
-    bitmap.unlockPixels();
     bitmap.notifyPixelsChanged();
 }
 
diff --git a/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java b/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java
index b7ed331..27d230b 100644
--- a/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java
+++ b/samples/training/network-usage/src/com/example/android/networkusage/NetworkActivity.java
@@ -158,7 +158,7 @@
         setContentView(R.layout.main);
 
         // The specified network connection is not available. Displays error message.
-        WebView myWebView = (WebView) findViewById(R.id.webview);
+        WebView myWebView = findViewById(R.id.webview);
         myWebView.loadData(getResources().getString(R.string.connection_error),
                 "text/html", null);
     }
@@ -205,7 +205,7 @@
         protected void onPostExecute(String result) {
             setContentView(R.layout.main);
             // Displays the HTML string in the UI via a WebView
-            WebView myWebView = (WebView) findViewById(R.id.webview);
+            WebView myWebView = findViewById(R.id.webview);
             myWebView.loadData(result, "text/html", null);
         }
     }
diff --git a/services/Android.mk b/services/Android.mk
index 4452543..a4c891b 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -40,8 +40,8 @@
 
 # The convention is to name each service module 'services.$(module_name)'
 LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services)) \
-    android.hidl.base@1.0-java-static \
-    android.hardware.biometrics.fingerprint@2.1-java-static
+    android.hidl.base-V1.0-java-static \
+    android.hardware.biometrics.fingerprint-V2.1-java-static
 
 ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
 LOCAL_EMMA_INSTRUMENT := true
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index d6f5256..1b5b2c6 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -48,6 +48,7 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
+import android.service.autofill.FillEventHistory;
 import android.util.LocalLog;
 import android.util.Log;
 import android.util.Slog;
@@ -184,7 +185,7 @@
     }
 
     @Override
-    public void onStopUser(int userId) {
+    public void onCleanupUser(int userId) {
         synchronized (mLock) {
             removeCachedServiceLocked(userId);
         }
@@ -211,7 +212,7 @@
     /**
      * Peeks the service instance for a user.
      *
-     * @return service instance or null if not already present
+     * @return service instance or {@code null} if not already present
      */
     @Nullable
     AutofillManagerServiceImpl peekServiceForUserLocked(int userId) {
@@ -398,6 +399,21 @@
         }
 
         @Override
+        public FillEventHistory getFillEventHistory() throws RemoteException {
+            UserHandle user = getCallingUserHandle();
+            int uid = getCallingUid();
+
+            synchronized (mLock) {
+                AutofillManagerServiceImpl service = peekServiceForUserLocked(user.getIdentifier());
+                if (service != null) {
+                    return service.getFillEventHistory(uid);
+                }
+            }
+
+            return null;
+        }
+
+        @Override
         public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)
                 throws RemoteException {
             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 63bf373..e274e18 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -48,6 +48,9 @@
 import android.provider.Settings;
 import android.service.autofill.AutofillService;
 import android.service.autofill.AutofillServiceInfo;
+import android.service.autofill.FillEventHistory;
+import android.service.autofill.FillRequest;
+import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
 import android.text.TextUtils;
 import android.util.LocalLog;
@@ -121,6 +124,10 @@
     @GuardedBy("mLock")
     private final SparseArray<Session> mSessions = new SparseArray<>();
 
+    /** The last selection */
+    @GuardedBy("mLock")
+    private FillEventHistory mEventHistory;
+
     /**
      * Receiver of assist data from the app's {@link Activity}.
      */
@@ -169,7 +176,8 @@
             structure.sanitizeForParceling(true);
 
             // TODO(b/33197203): Need to pipe the bundle
-            session.mRemoteFillService.onFillRequest(structure, null, session.mFlags);
+            FillRequest request = new FillRequest(structure, null, session.mFlags);
+            session.mRemoteFillService.onFillRequest(request);
         }
     };
 
@@ -498,6 +506,72 @@
         return mInfo.getServiceInfo().loadLabel(mContext.getPackageManager());
     }
 
+    /**
+     * Initializes the last fill selection after an autofill service returned a new
+     * {@link FillResponse}.
+     */
+    void setLastResponse(int serviceUid, @NonNull FillResponse response) {
+        synchronized (mLock) {
+            mEventHistory = new FillEventHistory(serviceUid, response.getClientState());
+        }
+    }
+
+    /**
+     * Updates the last fill selection when an authentication was selected.
+     */
+    void setAuthenticationSelected() {
+        synchronized (mLock) {
+            mEventHistory.addEvent(
+                    new FillEventHistory.Event(FillEventHistory.Event.TYPE_AUTHENTICATION_SELECTED, null));
+        }
+    }
+
+    /**
+     * Updates the last fill selection when an dataset authentication was selected.
+     */
+    void setDatasetAuthenticationSelected(@Nullable String selectedDataset) {
+        synchronized (mLock) {
+            mEventHistory.addEvent(new FillEventHistory.Event(
+                    FillEventHistory.Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset));
+        }
+    }
+
+    /**
+     * Updates the last fill selection when an save Ui is shown.
+     */
+    void setSaveShown() {
+        synchronized (mLock) {
+            mEventHistory.addEvent(new FillEventHistory.Event(FillEventHistory.Event.TYPE_SAVE_SHOWN, null));
+        }
+    }
+
+    /**
+     * Updates the last fill response when a dataset was selected.
+     */
+    void setDatasetSelected(@Nullable String selectedDataset) {
+        synchronized (mLock) {
+            mEventHistory.addEvent(
+                    new FillEventHistory.Event(FillEventHistory.Event.TYPE_DATASET_SELECTED, selectedDataset));
+        }
+    }
+
+    /**
+     * Gets the fill event history.
+     *
+     * @param callingUid The calling uid
+     *
+     * @return The history or {@code null} if there is none.
+     */
+    FillEventHistory getFillEventHistory(int callingUid) {
+        synchronized (mLock) {
+            if (mEventHistory != null && mEventHistory.getServiceUid() == callingUid) {
+                return mEventHistory;
+            }
+        }
+
+        return null;
+    }
+
     void dumpLocked(String prefix, PrintWriter pw) {
         final String prefix2 = prefix + "  ";
 
@@ -526,6 +600,20 @@
                 mSessions.valueAt(i).dumpLocked(prefix2, pw);
             }
         }
+
+        if (mEventHistory == null || mEventHistory.getEvents().size() == 0) {
+            pw.print(prefix); pw.println("No event on last fill response");
+        } else {
+            pw.print(prefix); pw.println("Events of last fill response:");
+            pw.print(prefix);
+
+            int numEvents = mEventHistory.getEvents().size();
+            for (int i = 0; i < numEvents; i++) {
+                FillEventHistory.Event event = mEventHistory.getEvents().get(i);
+                pw.println("  " + i + ": eventType=" + event.getType() + " datasetId="
+                        + event.getDatasetId());
+            }
+        }
     }
 
     void destroySessionsLocked() {
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index dd520ac..4d0f380 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -20,12 +20,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.assist.AssistStructure;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.os.Bundle;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.ICancellationSignal;
@@ -33,10 +31,12 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.autofill.AutofillService;
+import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
 import android.service.autofill.IFillCallback;
 import android.service.autofill.ISaveCallback;
+import android.service.autofill.SaveRequest;
 import android.text.format.DateUtils;
 import android.util.Slog;
 
@@ -87,8 +87,8 @@
     private PendingRequest mPendingRequest;
 
     public interface FillServiceCallbacks {
-        void onFillRequestSuccess(@Nullable FillResponse response,
-                @NonNull String servicePackageName);
+        void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid,
+                @NonNull String servicePackageName, int requestId);
         void onFillRequestFailure(@Nullable CharSequence message,
                 @NonNull String servicePackageName);
         void onSaveRequestSuccess(@NonNull String servicePackageName);
@@ -134,17 +134,16 @@
         mCallbacks.onServiceDied(this);
     }
 
-    public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
-            int flags) {
+    public void onFillRequest(@NonNull FillRequest request) {
         cancelScheduledUnbind();
-        final PendingFillRequest request = new PendingFillRequest(structure, extras, this, flags);
-        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
+        final PendingFillRequest pendingRequest = new PendingFillRequest(request, this);
+        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, pendingRequest).sendToTarget();
     }
 
-    public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras) {
+    public void onSaveRequest(@NonNull SaveRequest request) {
         cancelScheduledUnbind();
-        final PendingSaveRequest request = new PendingSaveRequest(structure, extras, this);
-        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, request).sendToTarget();
+        final PendingSaveRequest pendingRequest = new PendingSaveRequest(request, this);
+        mHandler.obtainMessageO(MyHandler.MSG_ON_PENDING_REQUEST, pendingRequest).sendToTarget();
     }
 
     // Note: we are dumping without a lock held so this is a bit racy but
@@ -253,10 +252,11 @@
     }
 
     private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest,
-            FillResponse response) {
+            int callingUid, FillResponse response, int requestId) {
         mHandler.getHandler().post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onFillRequestSuccess(response, mComponentName.getPackageName());
+                mCallbacks.onFillRequestSuccess(response, callingUid,
+                        mComponentName.getPackageName(), requestId);
             }
         });
     }
@@ -392,18 +392,13 @@
     private static final class PendingFillRequest extends PendingRequest {
         private final Object mLock = new Object();
         private final WeakReference<RemoteFillService> mWeakService;
-        private final AssistStructure mStructure;
-        private final Bundle mExtras;
+        private final FillRequest mRequest;
         private final IFillCallback mCallback;
         private ICancellationSignal mCancellation;
         private boolean mCancelled;
-        private int mFlags;
 
-        public PendingFillRequest(AssistStructure structure,
-                Bundle extras, RemoteFillService service, int flags) {
-            mStructure = structure;
-            mExtras = extras;
-            mFlags = flags;
+        public PendingFillRequest(FillRequest request, RemoteFillService service) {
+            mRequest = request;
             mWeakService = new WeakReference<>(service);
             mCallback = new IFillCallback.Stub() {
                 @Override
@@ -425,11 +420,11 @@
                 }
 
                 @Override
-                public void onSuccess(FillResponse response) {
+                public void onSuccess(FillResponse response, int requestId) {
                     RemoteFillService remoteService = mWeakService.get();
                     if (remoteService != null) {
                         remoteService.dispatchOnFillRequestSuccess(
-                                PendingFillRequest.this, response);
+                                PendingFillRequest.this, getCallingUid(), response, requestId);
                     }
                 }
 
@@ -449,8 +444,7 @@
             RemoteFillService remoteService = mWeakService.get();
             if (remoteService != null) {
                 try {
-                    remoteService.mAutoFillService.onFillRequest(mStructure,
-                            mExtras, mCallback, mFlags);
+                    remoteService.mAutoFillService.onFillRequest(mRequest, mCallback);
                 } catch (RemoteException e) {
                     Slog.e(LOG_TAG, "Error calling on fill request", e);
                     cancel();
@@ -481,14 +475,12 @@
 
     private static final class PendingSaveRequest extends PendingRequest {
         private final WeakReference<RemoteFillService> mWeakService;
-        private final AssistStructure mStructure;
-        private final Bundle mExtras;
+        private final SaveRequest mRequest;
         private final ISaveCallback mCallback;
 
-        public PendingSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle extras,
+        public PendingSaveRequest(@NonNull SaveRequest request,
                 @NonNull RemoteFillService service) {
-            mStructure = structure;
-            mExtras = extras;
+            mRequest = request;
             mWeakService = new WeakReference<>(service);
             mCallback = new ISaveCallback.Stub() {
                 @Override
@@ -516,7 +508,7 @@
             final RemoteFillService service = mWeakService.get();
             if (service != null) {
                 try {
-                    service.mAutoFillService.onSaveRequest(mStructure, mExtras, mCallback);
+                    service.mAutoFillService.onSaveRequest(mRequest, mCallback);
                 } catch (RemoteException e) {
                     Slog.e(LOG_TAG, "Error calling on save request", e);
                 }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 4b28337..2b99614 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -44,11 +44,15 @@
 import android.os.RemoteException;
 import android.service.autofill.AutofillService;
 import android.service.autofill.Dataset;
+import android.service.autofill.FillContext;
+import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
 import android.service.autofill.SaveInfo;
+import android.service.autofill.SaveRequest;
 import android.util.ArrayMap;
 import android.util.DebugUtils;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
@@ -64,6 +68,7 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -125,7 +130,7 @@
     RemoteFillService mRemoteFillService;
 
     @GuardedBy("mLock")
-    private ArrayList<FillResponse> mResponses;
+    private SparseArray<FillResponse> mResponses;
 
     /**
      * Response that requires a service authentitcation request.
@@ -156,7 +161,7 @@
      * and used on subsequent {@code onFillRequest()} and {@code onSaveRequest()} calls.
      */
     @GuardedBy("mLock")
-    private Bundle mExtras;
+    private Bundle mClientState;
 
     /**
      * Flags used to start the session.
@@ -216,13 +221,16 @@
         synchronized (mLock) {
             mActivityToken = newActivity;
             mClient = IAutoFillManagerClient.Stub.asInterface(newClient);
+
+            // The tracked id are not persisted in the client, hence update them
+            updateTrackedIdsLocked();
         }
     }
 
     // FillServiceCallbacks
     @Override
-    public void onFillRequestSuccess(@Nullable FillResponse response,
-            @NonNull String servicePackageName) {
+    public void onFillRequestSuccess(@Nullable FillResponse response, int serviceUid,
+            @NonNull String servicePackageName, int requestId) {
         if (response == null) {
             if ((mFlags & FLAG_MANUAL_REQUEST) != 0) {
                 getUiForShowing().showError(R.string.autofill_error_cannot_autofill);
@@ -233,6 +241,8 @@
             return;
         }
 
+        mService.setLastResponse(serviceUid, response);
+
         if ((response.getDatasets() == null || response.getDatasets().isEmpty())
                         && response.getAuthentication() == null) {
             // Response is "empty" from an UI point of view, need to notify client.
@@ -243,7 +253,7 @@
                 // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
                 mResponseWaitingAuth = response;
             }
-            processResponseLocked(response);
+            processResponseLocked(response, requestId);
         }
 
         final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
@@ -306,6 +316,9 @@
         synchronized (mLock) {
             fillInIntent = createAuthFillInIntent(mStructure, extras);
         }
+
+        mService.setAuthenticationSelected();
+
         mHandlerCaller.getHandler().post(() -> startAuthentication(intent, fillInIntent));
     }
 
@@ -343,9 +356,8 @@
             if (id.equals(mCurrentViewId)) {
                 try {
                     final ViewState view = mViewStates.get(id);
-                    mClient.requestShowFillUi(mWindowToken, id, width, height,
-                            view.getVirtualBounds(),
-                            presenter);
+                    mClient.requestShowFillUi(this.id, mWindowToken, id, width, height,
+                            view.getVirtualBounds(), presenter);
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Error requesting to show fill UI", e);
                 }
@@ -363,13 +375,30 @@
     public void requestHideFillUi(AutofillId id) {
         synchronized (mLock) {
             try {
-                mClient.requestHideFillUi(mWindowToken, id);
+                mClient.requestHideFillUi(this.id, mWindowToken, id);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error requesting to hide fill UI", e);
             }
         }
     }
 
+    // AutoFillUiCallback
+    @Override
+    public void startIntentSender(IntentSender intentSender) {
+        synchronized (mLock) {
+            removeSelfLocked();
+        }
+        mHandlerCaller.getHandler().post(() -> {
+            try {
+                synchronized (mLock) {
+                    mClient.startIntentSender(intentSender);
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Error launching auth intent", e);
+            }
+        });
+    }
+
     public void setAuthenticationResultLocked(Bundle data) {
         if ((mResponseWaitingAuth == null && mDatasetWaitingAuth == null) || data == null) {
             removeSelf();
@@ -378,12 +407,18 @@
                     AutofillManager.EXTRA_AUTHENTICATION_RESULT);
             if (result instanceof FillResponse) {
                 mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName);
+                final int requestIndex = mResponses.indexOfValue(mResponseWaitingAuth);
                 mResponseWaitingAuth = null;
-                processResponseLocked((FillResponse) result);
+                if (requestIndex >= 0) {
+                    final int requestId = mResponses.keyAt(requestIndex);
+                    processResponseLocked((FillResponse) result, requestId);
+                } else {
+                    Slog.e(TAG, "Error cannot find id for auth response");
+                }
             } else if (result instanceof Dataset) {
                 final Dataset dataset = (Dataset) result;
                 for (int i = 0; i < mResponses.size(); i++) {
-                    final FillResponse response = mResponses.get(i);
+                    final FillResponse response = mResponses.valueAt(i);
                     final int index = response.getDatasets().indexOf(mDatasetWaitingAuth);
                     if (index >= 0) {
                         response.getDatasets().set(index, dataset);
@@ -412,7 +447,7 @@
      */
     public boolean showSaveLocked() {
         if (mStructure == null) {
-            Slog.wtf(TAG, "showSaveLocked(): no mStructure");
+            Slog.d(TAG, "showSaveLocked(): no mStructure");
             return true;
         }
         if (mResponses == null) {
@@ -424,12 +459,18 @@
             return true;
         }
 
-        final FillResponse response = mResponses.get(mResponses.size() - 1);
+        final int lastResponseIdx = getLastResponseIndex();
+        if (lastResponseIdx < 0) {
+            Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses
+                    + ", mViewStates=" + mViewStates);
+            return true;
+        }
 
+        final FillResponse response = mResponses.valueAt(lastResponseIdx);
         final SaveInfo saveInfo = response.getSaveInfo();
         if (DEBUG) {
-            Slog.d(TAG,
-                    "showSaveLocked(): mResponses=" + mResponses + ", mViewStates=" + mViewStates);
+            Slog.d(TAG, "showSaveLocked(): mResponses=" + mResponses
+                    + ", mViewStates=" + mViewStates);
         }
 
         /*
@@ -506,6 +547,7 @@
                 }
             }
             if (atLeastOneChanged) {
+                mService.setSaveShown();
                 getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, mPackageName);
                 return false;
             }
@@ -556,7 +598,15 @@
             mStructure.dump();
         }
 
-        mRemoteFillService.onSaveRequest(mStructure, mExtras);
+        // TODO(b/33197203): Implement partitioning properly
+        final int lastResponseIdx = getLastResponseIndex();
+        final int requestId = mResponses.keyAt(lastResponseIdx);
+        final FillContext fillContext = new FillContext(requestId, mStructure);
+        final ArrayList fillContexts = new ArrayList(1);
+        fillContexts.add(fillContext);
+
+        final SaveRequest saveRequest = new SaveRequest(fillContexts, mClientState);
+        mRemoteFillService.onSaveRequest(saveRequest);
     }
 
     void updateLocked(AutofillId id, Rect virtualBounds, AutofillValue value, int flags) {
@@ -670,7 +720,9 @@
             overlay.focused = id.equals(viewState.id);
             node.setAutofillOverlay(overlay);
         }
-        mRemoteFillService.onFillRequest(mStructure, mExtras, 0);
+
+        FillRequest request = new FillRequest(mStructure, mClientState, 0);
+        mRemoteFillService.onFillRequest(request);
 
         return newViewState;
     }
@@ -699,7 +751,7 @@
             }
             if (!mHasCallback) return;
             try {
-                mClient.notifyNoFillUi(mWindowToken, mCurrentViewId);
+                mClient.notifyNoFillUi(id, mWindowToken, mCurrentViewId);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error notifying client no fill UI: windowToken=" + mWindowToken
                         + " id=" + mCurrentViewId, e);
@@ -707,20 +759,54 @@
         }
     }
 
-    private void processResponseLocked(FillResponse response) {
+    private void updateTrackedIdsLocked() {
+        if (mResponses == null || mResponses.size() == 0) {
+            return;
+        }
+
+        // Only track the views of the last response as only those are reported back to the
+        // service, see #showSaveLocked
+        ArrayList<AutofillId> trackedViews = new ArrayList<>();
+        boolean saveOnAllViewsInvisible = false;
+        SaveInfo saveInfo = mResponses.valueAt(getLastResponseIndex()).getSaveInfo();
+        if (saveInfo != null) {
+            saveOnAllViewsInvisible =
+                    (saveInfo.getFlags() & SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE) != 0;
+
+            // We only need to track views if we want to save once they become invisible.
+            if (saveOnAllViewsInvisible) {
+                if (saveInfo.getRequiredIds() != null) {
+                    Collections.addAll(trackedViews, saveInfo.getRequiredIds());
+                }
+
+                if (saveInfo.getOptionalIds() != null) {
+                    Collections.addAll(trackedViews, saveInfo.getOptionalIds());
+                }
+            }
+        }
+
+        try {
+            mClient.setTrackedViews(id, trackedViews, saveOnAllViewsInvisible);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Cannot set tracked ids", e);
+        }
+    }
+
+    private void processResponseLocked(FillResponse response, int requestId) {
         if (DEBUG) {
             Slog.d(TAG, "processResponseLocked(mCurrentViewId=" + mCurrentViewId + "):" + response);
         }
 
         if (mResponses == null) {
-            mResponses = new ArrayList<>(4);
+            mResponses = new SparseArray<>(4);
         }
-        mResponses.add(response);
+        mResponses.put(requestId, response);
         if (response != null) {
-            mExtras = response.getExtras();
+            mClientState = response.getClientState();
         }
 
         setViewStatesLocked(response, ViewState.STATE_FILLABLE);
+        updateTrackedIdsLocked();
 
         if (mCurrentViewId == null) {
             return;
@@ -802,12 +888,15 @@
         synchronized (mLock) {
             // Autofill it directly...
             if (dataset.getAuthentication() == null) {
+                mService.setDatasetSelected(dataset.getId());
+
                 autoFillApp(dataset);
                 return;
             }
 
             // ...or handle authentication.
             // TODO(b/33197203 , b/35707731): make sure it's ignored if there is one already
+            mService.setDatasetAuthenticationSelected(dataset.getId());
             mDatasetWaitingAuth = dataset;
             setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH);
             final Intent fillInIntent = createAuthFillInIntent(mStructure, null);
@@ -835,7 +924,7 @@
     private void startAuthentication(IntentSender intent, Intent fillInIntent) {
         try {
             synchronized (mLock) {
-                mClient.authenticate(intent, fillInIntent);
+                mClient.authenticate(id, intent, fillInIntent);
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "Error launching auth intent", e);
@@ -868,7 +957,8 @@
             }
         }
         pw.print(prefix); pw.print("mHasCallback: "); pw.println(mHasCallback);
-        pw.print(prefix); pw.print("mExtras: "); pw.println(Helper.bundleToString(mExtras));
+        pw.print(prefix); pw.print("mClientState: "); pw.println(
+                Helper.bundleToString(mClientState));
         mRemoteFillService.dump(prefix, pw);
     }
 
@@ -878,7 +968,7 @@
                 if (DEBUG) {
                     Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
                 }
-                mClient.autofill(mWindowToken, dataset.getFieldIds(), dataset.getFieldValues());
+                mClient.autofill(id, mWindowToken, dataset.getFieldIds(), dataset.getFieldValues());
                 setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Error autofilling activity: " + e);
@@ -945,4 +1035,20 @@
         destroyLocked();
         mService.removeSessionLocked(id);
     }
+
+    private int getLastResponseIndex() {
+        // The response ids are monotonically increasing so
+        // we just find the largest id which is the last. We
+        // do not rely on the internal ordering in sparse
+        // array to avoid - wow this stopped working!?
+        int lastResponseIdx = -1;
+        int lastResponseId = -1;
+        final int responseCount = mResponses.size();
+        for (int i = 0; i < responseCount; i++) {
+            if (mResponses.keyAt(i) > lastResponseId) {
+                lastResponseIdx = i;
+            }
+        }
+        return lastResponseIdx;
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 0f18c87..ab6a3a7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -67,6 +67,7 @@
         void requestShowFillUi(AutofillId id, int width, int height,
                 IAutofillWindowPresenter presenter);
         void requestHideFillUi(AutofillId id);
+        void startIntentSender(IntentSender intentSender);
     }
 
     public AutoFillUI(@NonNull Context context) {
@@ -160,7 +161,8 @@
                     log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
                     hideFillUiUiThread();
                     if (mCallback != null) {
-                        mCallback.authenticate(response.getAuthentication(), response.getExtras());
+                        mCallback.authenticate(response.getAuthentication(),
+                                response.getClientState());
                     }
                 }
 
@@ -201,6 +203,13 @@
                         mCallback.requestHideFillUi(focusedId);
                     }
                 }
+
+                @Override
+                public void startIntentSender(IntentSender intentSender) {
+                    if (mCallback != null) {
+                        mCallback.startIntentSender(intentSender);
+                    }
+                }
             });
         });
     }
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index a89df92..b68e3b1 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -17,7 +17,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.PendingIntent;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
 import android.graphics.Rect;
 import android.service.autofill.Dataset;
 import android.service.autofill.FillResponse;
@@ -55,6 +58,7 @@
         void requestShowFillUi(int width, int height,
                 IAutofillWindowPresenter windowPresenter);
         void requestHideFillUi();
+        void startIntentSender(IntentSender intentSender);
     }
 
     private final @NonNull AutofillWindowPresenter mWindowPresenter =
@@ -84,13 +88,24 @@
         final ViewGroup decor = (ViewGroup) inflater.inflate(
                 R.layout.autofill_dataset_picker, null);
 
+        final RemoteViews.OnClickHandler interceptionHandler = new RemoteViews.OnClickHandler() {
+            @Override
+            public boolean onClickHandler(View view, PendingIntent pendingIntent,
+                    Intent fillInIntent) {
+                if (pendingIntent != null) {
+                    mCallback.startIntentSender(pendingIntent.getIntentSender());
+                }
+                return true;
+            }
+        };
+
         if (response.getAuthentication() != null) {
             mListView = null;
             mAdapter = null;
 
             final View content;
             try {
-                content = response.getPresentation().apply(context, decor);
+                content = response.getPresentation().apply(context, decor, interceptionHandler);
                 decor.addView(content);
             } catch (RuntimeException e) {
                 callback.onCanceled();
@@ -101,7 +116,7 @@
             final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
             final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
             content.measure(widthMeasureSpec, heightMeasureSpec);
-            content.setOnClickListener(v -> mCallback.onResponsePicked(response));
+            decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
             // TODO(b/33197203 , b/36660292): temporary limiting maximum height and minimum width
             mContentWidth = Math.max(content.getMeasuredWidth(), 1000);
             mContentHeight = Math.min(content.getMeasuredHeight(), 500);
@@ -118,7 +133,7 @@
                     final RemoteViews presentation = dataset.getFieldPresentation(index);
                     final View view;
                     try {
-                        view = presentation.apply(context, null);
+                        view = presentation.apply(context, null, interceptionHandler);
                     } catch (RuntimeException e) {
                         Slog.e(TAG, "Error inflating remote views", e);
                         continue;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index ef63bde..73442ab 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -800,6 +800,19 @@
         return ((app.flags & ApplicationInfo.FLAG_STOPPED) != 0);
     }
 
+    // We also avoid backups of 'disabled' apps
+    private static boolean appIsDisabled(ApplicationInfo app, PackageManager pm) {
+        switch (pm.getApplicationEnabledSetting(app.packageName)) {
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
     /* does *not* check overall backup eligibility policy! */
     private static boolean appGetsFullBackup(PackageInfo pkg) {
         if (pkg.applicationInfo.backupAgentName != null) {
@@ -10777,7 +10790,8 @@
             PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
                     PackageManager.GET_SIGNATURES);
             if (!appIsEligibleForBackup(packageInfo.applicationInfo) ||
-                    appIsStopped(packageInfo.applicationInfo)) {
+                    appIsStopped(packageInfo.applicationInfo) ||
+                    appIsDisabled(packageInfo.applicationInfo, mPackageManager)) {
                 return false;
             }
             IBackupTransport transport = mTransportManager.getCurrentTransportBinder();
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index 3e1f8ee..02dc062 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -77,6 +77,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.StringBuilderPrinter;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.backup.IBackupTransport;
 import com.android.internal.util.DumpUtils;
@@ -103,6 +104,9 @@
 import com.android.server.backup.restore.ActiveRestoreSession;
 import com.android.server.backup.restore.PerformUnifiedRestoreTask;
 import com.android.server.power.BatterySaverPolicy.ServiceType;
+
+import libcore.io.IoUtils;
+
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
@@ -136,10 +140,10 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
+
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
-import libcore.io.IoUtils;
 
 public class RefactoredBackupManagerService implements BackupManagerServiceInterface {
 
@@ -320,6 +324,7 @@
     // implementation object on the fly without disturbing binders that have been
     // cached elsewhere in the system.
     static Trampoline sInstance;
+
     static Trampoline getInstance() {
         // Always constructed during system bringup, so no need to lazy-init
         return sInstance;
@@ -397,7 +402,8 @@
      *
      * A BackupRestore task gets notified of ack/timeout for the operation via
      * BackupRestoreTask#handleCancel, BackupRestoreTask#operationComplete and notifyAll called
-     * on the mCurrentOpLock. {@link RefactoredBackupManagerService#waitUntilOperationComplete(int)} is
+     * on the mCurrentOpLock.
+     * {@link RefactoredBackupManagerService#waitUntilOperationComplete(int)} is
      * used in various places to 'wait' for notifyAll and detect change of pending state of an
      * operation. So typically, an operation will be removed from this array by:
      *   - BackupRestoreTask#handleCancel and
@@ -446,7 +452,8 @@
     private File mEverStored;
     private HashSet<String> mEverStoredApps = new HashSet<>();
 
-    private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1;  // increment when the schema changes
+    private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1;
+            // increment when the schema changes
     private File mTokenFile;
     public Set<String> mAncestralPackages = null;
     public long mAncestralToken = 0;
@@ -483,7 +490,7 @@
     // High level policy: apps are generally ineligible for backup if certain conditions apply
     public static boolean appIsEligibleForBackup(ApplicationInfo app) {
         // 1. their manifest states android:allowBackup="false"
-        if ((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) {
+        if ((app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) {
             return false;
         }
 
@@ -767,8 +774,14 @@
             } catch (IOException e) {
                 Slog.e(TAG, "Error in processed file", e);
             } finally {
-                try { if (temp != null) temp.close(); } catch (IOException e) {}
-                try { if (in != null) in.close(); } catch (IOException e) {}
+                try {
+                    if (temp != null) temp.close();
+                } catch (IOException e) {
+                }
+                try {
+                    if (in != null) in.close();
+                } catch (IOException e) {
+                }
             }
         }
 
@@ -889,7 +902,8 @@
     }
 
     private Runnable mFullBackupScheduleWriter = new Runnable() {
-        @Override public void run() {
+        @Override
+        public void run() {
             synchronized (mQueueLock) {
                 try {
                     ByteArrayOutputStream bufStream = new ByteArrayOutputStream(4096);
@@ -954,7 +968,10 @@
                     Slog.e(TAG, "Can't read " + f, e);
                 } finally {
                     // close/delete the file
-                    try { if (in != null) in.close(); } catch (IOException e) {}
+                    try {
+                        if (in != null) in.close();
+                    } catch (IOException e) {
+                    }
                     f.delete();
                 }
             }
@@ -996,13 +1013,13 @@
 
     public byte[] hexToByteArray(String digits) {
         final int bytes = digits.length() / 2;
-        if (2*bytes != digits.length()) {
+        if (2 * bytes != digits.length()) {
             throw new IllegalArgumentException("Hex string must have an even number of digits");
         }
 
         byte[] result = new byte[bytes];
         for (int i = 0; i < digits.length(); i += 2) {
-            result[i/2] = (byte) Integer.parseInt(digits.substring(i, i+2), 16);
+            result[i / 2] = (byte) Integer.parseInt(digits.substring(i, i + 2), 16);
         }
         return result;
     }
@@ -1033,7 +1050,8 @@
         } else {
             // hash the stated current pw and compare to the stored one
             if (candidatePw != null && candidatePw.length() > 0) {
-                String currentPwHash = buildPasswordHash(algorithm, candidatePw, mPasswordSalt, rounds);
+                String currentPwHash = buildPasswordHash(algorithm, candidatePw, mPasswordSalt,
+                        rounds);
                 if (mPasswordHash.equalsIgnoreCase(currentPwHash)) {
                     // candidate hash matches the stored hash -- the password matches
                     return true;
@@ -1055,7 +1073,7 @@
         // might be caught in the legacy crypto mismatch; verify that too.
         if (!passwordMatchesSaved(PBKDF_CURRENT, currentPw, PBKDF2_HASH_ROUNDS)
                 && !(pbkdf2Fallback && passwordMatchesSaved(PBKDF_FALLBACK,
-                        currentPw, PBKDF2_HASH_ROUNDS))) {
+                currentPw, PBKDF2_HASH_ROUNDS))) {
             return false;
         }
 
@@ -1137,7 +1155,7 @@
             final boolean pbkdf2Fallback = (mPasswordVersion < BACKUP_PW_FILE_VERSION);
             if (!passwordMatchesSaved(PBKDF_CURRENT, currentPw, PBKDF2_HASH_ROUNDS)
                     && !(pbkdf2Fallback && passwordMatchesSaved(PBKDF_FALLBACK,
-                            currentPw, PBKDF2_HASH_ROUNDS))) {
+                    currentPw, PBKDF2_HASH_ROUNDS))) {
                 if (DEBUG) Slog.w(TAG, "Backup password mismatch; aborting");
                 return false;
             }
@@ -1148,8 +1166,10 @@
     // Maintain persistent state around whether need to do an initialize operation.
     // Must be called with the queue lock held.
     public void recordInitPendingLocked(boolean isPending, String transportName) {
-        if (MORE_DEBUG) Slog.i(TAG, "recordInitPendingLocked: " + isPending
-                + " on transport " + transportName);
+        if (MORE_DEBUG) {
+            Slog.i(TAG, "recordInitPendingLocked: " + isPending
+                    + " on transport " + transportName);
+        }
         mBackupHandler.removeMessages(MSG_RETRY_INIT);
 
         try {
@@ -1220,7 +1240,7 @@
         // Enqueue a new backup of every participant
         synchronized (mBackupParticipants) {
             final int N = mBackupParticipants.size();
-            for (int i=0; i<N; i++) {
+            for (int i = 0; i < N; i++) {
                 HashSet<String> participants = mBackupParticipants.valueAt(i);
                 if (participants != null) {
                     for (String packageName : participants) {
@@ -1233,37 +1253,37 @@
 
     private TransportManager.TransportBoundListener mTransportBoundListener =
             new TransportManager.TransportBoundListener() {
-        @Override
-        public boolean onTransportBound(IBackupTransport transport) {
-            // If the init sentinel file exists, we need to be sure to perform the init
-            // as soon as practical.  We also create the state directory at registration
-            // time to ensure it's present from the outset.
-            String name = null;
-            try {
-                name = transport.name();
-                String transportDirName = transport.transportDirName();
-                File stateDir = new File(mBaseStateDir, transportDirName);
-                stateDir.mkdirs();
+                @Override
+                public boolean onTransportBound(IBackupTransport transport) {
+                    // If the init sentinel file exists, we need to be sure to perform the init
+                    // as soon as practical.  We also create the state directory at registration
+                    // time to ensure it's present from the outset.
+                    String name = null;
+                    try {
+                        name = transport.name();
+                        String transportDirName = transport.transportDirName();
+                        File stateDir = new File(mBaseStateDir, transportDirName);
+                        stateDir.mkdirs();
 
-                File initSentinel = new File(stateDir, INIT_SENTINEL_FILE_NAME);
-                if (initSentinel.exists()) {
-                    synchronized (mQueueLock) {
-                        mPendingInits.add(name);
+                        File initSentinel = new File(stateDir, INIT_SENTINEL_FILE_NAME);
+                        if (initSentinel.exists()) {
+                            synchronized (mQueueLock) {
+                                mPendingInits.add(name);
 
-                        // TODO: pick a better starting time than now + 1 minute
-                        long delay = 1000 * 60; // one minute, in milliseconds
-                        mAlarmManager.set(AlarmManager.RTC_WAKEUP,
-                                System.currentTimeMillis() + delay, mRunInitIntent);
+                                // TODO: pick a better starting time than now + 1 minute
+                                long delay = 1000 * 60; // one minute, in milliseconds
+                                mAlarmManager.set(AlarmManager.RTC_WAKEUP,
+                                        System.currentTimeMillis() + delay, mRunInitIntent);
+                            }
+                        }
+                        return true;
+                    } catch (Exception e) {
+                        // the transport threw when asked its file naming prefs; declare it invalid
+                        Slog.w(TAG, "Failed to regiser transport: " + name);
+                        return false;
                     }
                 }
-                return true;
-            } catch (Exception e) {
-                // the transport threw when asked its file naming prefs; declare it invalid
-                Slog.w(TAG, "Failed to regiser transport: " + name);
-                return false;
-            }
-        }
-    };
+            };
 
     // ----- Track installation/removal of packages -----
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -1285,7 +1305,7 @@
                 }
                 String pkgName = uri.getSchemeSpecificPart();
                 if (pkgName != null) {
-                    pkgList = new String[] { pkgName };
+                    pkgList = new String[]{pkgName};
                 }
                 changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
 
@@ -1429,8 +1449,10 @@
             return;
         }
 
-        if (MORE_DEBUG) Slog.v(TAG, "removePackageParticipantsLocked: uid=" + oldUid
-                + " #" + packageNames.length);
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "removePackageParticipantsLocked: uid=" + oldUid
+                    + " #" + packageNames.length);
+        }
         for (String pkg : packageNames) {
             // Known previous UID, so we know which package set to check
             HashSet<String> set = mBackupParticipants.get(oldUid);
@@ -1465,16 +1487,15 @@
         int flags = PackageManager.GET_SIGNATURES;
         List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags);
         int N = packages.size();
-        for (int a = N-1; a >= 0; a--) {
+        for (int a = N - 1; a >= 0; a--) {
             PackageInfo pkg = packages.get(a);
             try {
                 ApplicationInfo app = pkg.applicationInfo;
-                if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
+                if (((app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
                         || app.backupAgentName == null
-                        || (app.flags&ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0) {
+                        || (app.flags & ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0) {
                     packages.remove(a);
-                }
-                else {
+                } else {
                     // we will need the shared library path, so look that up and store it here.
                     // This is used implicitly when we pass the PackageInfo object off to
                     // the Activity Manager to launch the app for backup/restore purposes.
@@ -1506,7 +1527,10 @@
             } catch (IOException e) {
                 Slog.e(TAG, "Can't log backup of " + packageName + " to " + mEverStored);
             } finally {
-                try { if (out != null) out.close(); } catch (IOException e) {}
+                try {
+                    if (out != null) out.close();
+                } catch (IOException e) {
+                }
             }
         }
     }
@@ -1544,7 +1568,10 @@
                 tempKnownFile.delete();
                 mEverStored.delete();
             } finally {
-                try { if (known != null) known.close(); } catch (IOException e) {}
+                try {
+                    if (known != null) known.close();
+                } catch (IOException e) {
+                }
             }
         }
     }
@@ -1592,7 +1619,7 @@
     @Override
     public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode) {
         IBackupAgent agent = null;
-        synchronized(mAgentConnectLock) {
+        synchronized (mAgentConnectLock) {
             mConnecting = true;
             mConnectedAgent = null;
             try {
@@ -1643,8 +1670,10 @@
         try {
             PackageInfo info = mPackageManager.getPackageInfo(packageName, 0);
             if ((info.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) {
-                if (MORE_DEBUG) Slog.i(TAG, "allowClearUserData=false so not wiping "
-                        + packageName);
+                if (MORE_DEBUG) {
+                    Slog.i(TAG, "allowClearUserData=false so not wiping "
+                            + packageName);
+                }
                 return;
             }
         } catch (NameNotFoundException e) {
@@ -1654,7 +1683,7 @@
 
         ClearDataObserver observer = new ClearDataObserver(this);
 
-        synchronized(mClearDataLock) {
+        synchronized (mClearDataLock) {
             mClearingData = true;
             try {
                 mActivityManager.clearApplicationUserData(packageName, observer, 0);
@@ -1750,7 +1779,8 @@
                 fullBackupList.size());
         if (MORE_DEBUG) {
             Slog.i(TAG, "Backup requested for " + packages.length + " packages, of them: " +
-                fullBackupList.size() + " full backups, " + kvBackupList.size() + " k/v backups");
+                    fullBackupList.size() + " full backups, " + kvBackupList.size()
+                    + " k/v backups");
         }
 
         String dirName;
@@ -1773,7 +1803,7 @@
 
     // Cancel all running backups.
     @Override
-    public void cancelBackups(){
+    public void cancelBackups() {
         mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "cancelBackups");
         if (MORE_DEBUG) {
             Slog.i(TAG, "cancelBackups() called.");
@@ -1804,14 +1834,16 @@
 
     @Override
     public void prepareOperationTimeout(int token, long interval, BackupRestoreTask callback,
-        int operationType) {
+            int operationType) {
         if (operationType != OP_TYPE_BACKUP_WAIT && operationType != OP_TYPE_RESTORE_WAIT) {
             Slog.wtf(TAG, "prepareOperationTimeout() doesn't support operation " +
                     Integer.toHexString(token) + " of type " + operationType);
             return;
         }
-        if (MORE_DEBUG) Slog.v(TAG, "starting timeout: token=" + Integer.toHexString(token)
-                + " interval=" + interval + " callback=" + callback);
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "starting timeout: token=" + Integer.toHexString(token)
+                    + " interval=" + interval + " callback=" + callback);
+        }
 
         synchronized (mCurrentOpLock) {
             mCurrentOperations.put(token, new Operation(OP_PENDING, callback, operationType));
@@ -1850,8 +1882,10 @@
     // synchronous waiter case
     @Override
     public boolean waitUntilOperationComplete(int token) {
-        if (MORE_DEBUG) Slog.i(TAG, "Blocking until operation complete for "
-                + Integer.toHexString(token));
+        if (MORE_DEBUG) {
+            Slog.i(TAG, "Blocking until operation complete for "
+                    + Integer.toHexString(token));
+        }
         int finalState = OP_PENDING;
         Operation op = null;
         synchronized (mCurrentOpLock) {
@@ -1884,8 +1918,10 @@
         if (op != null) {
             mBackupHandler.removeMessages(getMessageIdForOperationType(op.type));
         }
-        if (MORE_DEBUG) Slog.v(TAG, "operation " + Integer.toHexString(token)
-                + " complete: finalState=" + finalState);
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "operation " + Integer.toHexString(token)
+                    + " complete: finalState=" + finalState);
+        }
         return finalState == OP_ACKNOWLEDGED;
     }
 
@@ -1895,8 +1931,10 @@
         synchronized (mCurrentOpLock) {
             op = mCurrentOperations.get(token);
             if (MORE_DEBUG) {
-                if (op == null) Slog.w(TAG, "Cancel of token " + Integer.toHexString(token)
-                        + " but no op found");
+                if (op == null) {
+                    Slog.w(TAG, "Cancel of token " + Integer.toHexString(token)
+                            + " but no op found");
+                }
             }
             int state = (op != null) ? op.state : OP_TIMEOUT;
             if (state == OP_ACKNOWLEDGED) {
@@ -1999,7 +2037,7 @@
     // application and emitting it to the designated OutputStream.
 
     public static void writeAppManifest(PackageInfo pkg, PackageManager packageManager,
-        File manifestFile, boolean withApk, boolean withWidgets) throws IOException {
+            File manifestFile, boolean withApk, boolean withWidgets) throws IOException {
         // Manifest format. All data are strings ending in LF:
         //     BACKUP_MANIFEST_VERSION, currently 1
         //
@@ -2047,9 +2085,9 @@
     public boolean deviceIsEncrypted() {
         try {
             return mStorageManager.getEncryptionState()
-                     != StorageManager.ENCRYPTION_STATE_NONE
-                && mStorageManager.getPasswordType()
-                     != StorageManager.CRYPT_TYPE_DEFAULT;
+                    != StorageManager.ENCRYPTION_STATE_NONE
+                    && mStorageManager.getPasswordType()
+                    != StorageManager.CRYPT_TYPE_DEFAULT;
         } catch (Exception e) {
             // If we can't talk to the storagemanager service we have a serious problem; fail
             // "secure" i.e. assuming that the device is encrypted.
@@ -2075,7 +2113,8 @@
                         ? (MIN_FULL_BACKUP_INTERVAL - timeSinceLast) : 0;
                 final long latency = Math.max(transportMinLatency, appLatency);
                 Runnable r = new Runnable() {
-                    @Override public void run() {
+                    @Override
+                    public void run() {
                         FullBackupJob.schedule(mContext, latency);
                     }
                 };
@@ -2093,7 +2132,7 @@
      */
     private void dequeueFullBackupLocked(String packageName) {
         final int N = mFullBackupQueue.size();
-        for (int i = N-1; i >= 0; i--) {
+        for (int i = N - 1; i >= 0; i--) {
             final FullBackupEntry e = mFullBackupQueue.get(i);
             if (packageName.equals(e.packageName)) {
                 mFullBackupQueue.remove(i);
@@ -2305,7 +2344,8 @@
                 }
                 final long deferTime = latency;     // pin for the closure
                 mBackupHandler.post(new Runnable() {
-                    @Override public void run() {
+                    @Override
+                    public void run() {
                         FullBackupJob.schedule(mContext, deferTime);
                     }
                 });
@@ -2315,7 +2355,7 @@
             // Okay, the top thing is ready for backup now.  Do it.
             mFullBackupQueue.remove(0);
             CountDownLatch latch = new CountDownLatch(1);
-            String[] pkg = new String[] {entry.packageName};
+            String[] pkg = new String[]{entry.packageName};
             mRunningFullBackupTask = new PerformFullTransportBackupTask(this, null, pkg, true,
                     scheduledJob, latch, null, null, false /* userInitiated */);
             // Acquiring wakelock for PerformFullTransportBackupTask before its start.
@@ -2354,15 +2394,20 @@
         // partition will be signed with the device's platform certificate, so on
         // different phones the same system app will have different signatures.)
         if ((target.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
-            if (MORE_DEBUG) Slog.v(TAG, "System app " + target.packageName + " - skipping sig check");
+            if (MORE_DEBUG) {
+                Slog.v(TAG,
+                        "System app " + target.packageName + " - skipping sig check");
+            }
             return true;
         }
 
         // Allow unsigned apps, but not signed on one device and unsigned on the other
         // !!! TODO: is this the right policy?
         Signature[] deviceSigs = target.signatures;
-        if (MORE_DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs
-                + " device=" + deviceSigs);
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs
+                    + " device=" + deviceSigs);
+        }
         if ((storedSigs == null || storedSigs.length == 0)
                 && (deviceSigs == null || deviceSigs.length == 0)) {
             return true;
@@ -2377,9 +2422,9 @@
         int nStored = storedSigs.length;
         int nDevice = deviceSigs.length;
 
-        for (int i=0; i < nStored; i++) {
+        for (int i = 0; i < nStored; i++) {
             boolean match = false;
-            for (int j=0; j < nDevice; j++) {
+            for (int j = 0; j < nDevice; j++) {
                 if (storedSigs[i].equals(deviceSigs[j])) {
                     match = true;
                     break;
@@ -2417,7 +2462,7 @@
         // a backup pass for each of them.
         if (targets == null) {
             Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
-                   + " uid=" + Binder.getCallingUid());
+                    + " uid=" + Binder.getCallingUid());
             return;
         }
 
@@ -2482,7 +2527,10 @@
             Slog.e(TAG, "Can't write " + str + " to backup journal", e);
             mJournal = null;
         } finally {
-            try { if (out != null) out.close(); } catch (IOException e) {}
+            try {
+                if (out != null) out.close();
+            } catch (IOException e) {
+            }
         }
     }
 
@@ -2507,15 +2555,15 @@
         final HashSet<String> targets = dataChangedTargets(packageName);
         if (targets == null) {
             Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
-                   + " uid=" + Binder.getCallingUid());
+                    + " uid=" + Binder.getCallingUid());
             return;
         }
 
         mBackupHandler.post(new Runnable() {
-                public void run() {
-                    dataChangedImpl(packageName, targets);
-                }
-            });
+            public void run() {
+                dataChangedImpl(packageName, targets);
+            }
+        });
     }
 
     // Clear the given package's backup data from the current transport
@@ -2647,9 +2695,11 @@
                 return;
             }
 
-            if (DEBUG) Slog.v(TAG, "Requesting backup: apks=" + includeApks + " obb=" + includeObbs
-                    + " shared=" + includeShared + " all=" + doAllApps + " system="
-                    + includeSystem + " includekeyvalue=" + doKeyValue + " pkgs=" + pkgList);
+            if (DEBUG) {
+                Slog.v(TAG, "Requesting backup: apks=" + includeApks + " obb=" + includeObbs
+                        + " shared=" + includeShared + " all=" + doAllApps + " system="
+                        + includeSystem + " includekeyvalue=" + doKeyValue + " pkgs=" + pkgList);
+            }
             Slog.i(TAG, "Beginning adb backup...");
 
             AdbBackupParams params = new AdbBackupParams(fd, includeApks, includeObbs,
@@ -2813,8 +2863,10 @@
     }
 
     private void startConfirmationTimeout(int token, AdbParams params) {
-        if (MORE_DEBUG) Slog.d(TAG, "Posting conf timeout msg after "
-                + TIMEOUT_FULL_CONFIRMATION + " millis");
+        if (MORE_DEBUG) {
+            Slog.d(TAG, "Posting conf timeout msg after "
+                    + TIMEOUT_FULL_CONFIRMATION + " millis");
+        }
         Message msg = mBackupHandler.obtainMessage(MSG_FULL_CONFIRMATION_TIMEOUT,
                 token, 0, params);
         mBackupHandler.sendMessageDelayed(msg, TIMEOUT_FULL_CONFIRMATION);
@@ -2842,12 +2894,15 @@
     @Override
     public void acknowledgeAdbBackupOrRestore(int token, boolean allow,
             String curPassword, String encPpassword, IFullBackupRestoreObserver observer) {
-        if (DEBUG) Slog.d(TAG, "acknowledgeAdbBackupOrRestore : token=" + token
-                + " allow=" + allow);
+        if (DEBUG) {
+            Slog.d(TAG, "acknowledgeAdbBackupOrRestore : token=" + token
+                    + " allow=" + allow);
+        }
 
         // TODO: possibly require not just this signature-only permission, but even
         // require that the specific designated confirmation-UI app uid is the caller?
-        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "acknowledgeAdbBackupOrRestore");
+        mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+                "acknowledgeAdbBackupOrRestore");
 
         long oldId = Binder.clearCallingIdentity();
         try {
@@ -2923,7 +2978,7 @@
             fout.close();
             stage.renameTo(enableFile);
             // will be synced immediately by the try-with-resources call to close()
-        } catch (IOException|RuntimeException e) {
+        } catch (IOException | RuntimeException e) {
             // Whoops; looks like we're doomed.  Roll everything out, disabled,
             // including the legacy state.
             Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
@@ -3020,7 +3075,8 @@
     // Report whether the backup mechanism is currently enabled
     @Override
     public boolean isBackupEnabled() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "isBackupEnabled");
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+                "isBackupEnabled");
         return mEnabled;    // no need to synchronize just to read it
     }
 
@@ -3037,7 +3093,8 @@
     // Report all known, available backup transports
     @Override
     public String[] listAllTransports() {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "listAllTransports");
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+                "listAllTransports");
 
         return mTransportManager.getBoundTransportNames();
     }
@@ -3133,8 +3190,10 @@
         if (transport != null) {
             try {
                 final Intent intent = transport.configurationIntent();
-                if (MORE_DEBUG) Slog.d(TAG, "getConfigurationIntent() returning config intent "
-                        + intent);
+                if (MORE_DEBUG) {
+                    Slog.d(TAG, "getConfigurationIntent() returning config intent "
+                            + intent);
+                }
                 return intent;
             } catch (Exception e) {
                 /* fall through to return null */
@@ -3180,8 +3239,10 @@
         if (transport != null) {
             try {
                 final Intent intent = transport.dataManagementIntent();
-                if (MORE_DEBUG) Slog.d(TAG, "getDataManagementIntent() returning intent "
-                        + intent);
+                if (MORE_DEBUG) {
+                    Slog.d(TAG, "getDataManagementIntent() returning intent "
+                            + intent);
+                }
                 return intent;
             } catch (Exception e) {
                 /* fall through to return null */
@@ -3218,7 +3279,7 @@
     // be called from the Activity Manager.
     @Override
     public void agentConnected(String packageName, IBinder agentBinder) {
-        synchronized(mAgentConnectLock) {
+        synchronized (mAgentConnectLock) {
             if (Binder.getCallingUid() == Process.SYSTEM_UID) {
                 Slog.d(TAG, "agentConnected pkg=" + packageName + " agent=" + agentBinder);
                 IBackupAgent agent = IBackupAgent.Stub.asInterface(agentBinder);
@@ -3238,7 +3299,7 @@
     @Override
     public void agentDisconnected(String packageName) {
         // TODO: handle backup being interrupted
-        synchronized(mAgentConnectLock) {
+        synchronized (mAgentConnectLock) {
             if (Binder.getCallingUid() == Process.SYSTEM_UID) {
                 mConnectedAgent = null;
                 mConnecting = false;
@@ -3263,9 +3324,11 @@
         boolean skip = false;
 
         long restoreSet = getAvailableRestoreToken(packageName);
-        if (DEBUG) Slog.v(TAG, "restoreAtInstall pkg=" + packageName
-                + " token=" + Integer.toHexString(token)
-                + " restoreSet=" + Long.toHexString(restoreSet));
+        if (DEBUG) {
+            Slog.v(TAG, "restoreAtInstall pkg=" + packageName
+                    + " token=" + Integer.toHexString(token)
+                    + " restoreSet=" + Long.toHexString(restoreSet));
+        }
         if (restoreSet == 0) {
             if (MORE_DEBUG) Slog.i(TAG, "No restore set");
             skip = true;
@@ -3322,8 +3385,10 @@
     // Hand off a restore session
     @Override
     public IRestoreSession beginRestoreSession(String packageName, String transport) {
-        if (DEBUG) Slog.v(TAG, "beginRestoreSession: pkg=" + packageName
-                + " transport=" + transport);
+        if (DEBUG) {
+            Slog.v(TAG, "beginRestoreSession: pkg=" + packageName
+                    + " transport=" + transport);
+        }
 
         boolean needPermission = true;
         if (transport == null) {
@@ -3354,7 +3419,7 @@
             if (DEBUG) Slog.d(TAG, "restoring self on current transport; no permission needed");
         }
 
-        synchronized(this) {
+        synchronized (this) {
             if (mActiveRestoreSession != null) {
                 Slog.i(TAG, "Restore session requested but one already active");
                 return null;
@@ -3371,7 +3436,7 @@
     }
 
     public void clearRestoreSession(ActiveRestoreSession currentSession) {
-        synchronized(this) {
+        synchronized (this) {
             if (currentSession != mActiveRestoreSession) {
                 Slog.e(TAG, "ending non-current restore session");
             } else {
@@ -3422,6 +3487,19 @@
         }
     }
 
+    // We also avoid backups of 'disabled' apps
+    private static boolean appIsDisabled(ApplicationInfo app, PackageManager pm) {
+        switch (pm.getApplicationEnabledSetting(app.packageName)) {
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
+            case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
     @Override
     public boolean isAppEligibleForBackup(String packageName) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
@@ -3430,14 +3508,15 @@
             PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
                     PackageManager.GET_SIGNATURES);
             if (!appIsEligibleForBackup(packageInfo.applicationInfo) ||
-                    appIsStopped(packageInfo.applicationInfo)) {
+                    appIsStopped(packageInfo.applicationInfo) ||
+                    appIsDisabled(packageInfo.applicationInfo, mPackageManager)) {
                 return false;
             }
             IBackupTransport transport = mTransportManager.getCurrentTransportBinder();
             if (transport != null) {
                 try {
                     return transport.isAppEligibleForBackup(packageInfo,
-                        appGetsFullBackup(packageInfo));
+                            appGetsFullBackup(packageInfo));
                 } catch (Exception e) {
                     Slog.e(TAG, "Unable to ask about eligibility: " + e.getMessage());
                 }
@@ -3479,8 +3558,10 @@
         pw.println("Defined backup agents:");
         for (PackageInfo pkg : agentPackages) {
             pw.print("  ");
-            pw.print(pkg.packageName); pw.println(':');
-            pw.print("      "); pw.println(pkg.applicationInfo.backupAgentName);
+            pw.print(pkg.packageName);
+            pw.println(':');
+            pw.print("      ");
+            pw.println(pkg.applicationInfo.backupAgentName);
         }
     }
 
@@ -3505,14 +3586,16 @@
             final String[] transports = listAllTransports();
             if (transports != null) {
                 for (String t : listAllTransports()) {
-                    pw.println((t.equals(mTransportManager.getCurrentTransportName()) ? "  * " : "    ") + t);
+                    pw.println((t.equals(mTransportManager.getCurrentTransportName()) ? "  * "
+                            : "    ") + t);
                     try {
                         IBackupTransport transport = mTransportManager.getTransportBinder(t);
                         File dir = new File(mBaseStateDir, transport.transportDirName());
                         pw.println("       destination: " + transport.currentDestinationString());
                         pw.println("       intent: " + transport.configurationIntent());
                         for (File f : dir.listFiles()) {
-                            pw.println("       " + f.getName() + " - " + f.length() + " state bytes");
+                            pw.println(
+                                    "       " + f.getName() + " - " + f.length() + " state bytes");
                         }
                     } catch (Exception e) {
                         Slog.e(TAG, "Error in transport", e);
@@ -3537,17 +3620,19 @@
                 }
             }
 
-            pw.print("Ancestral: "); pw.println(Long.toHexString(mAncestralToken));
-            pw.print("Current:   "); pw.println(Long.toHexString(mCurrentToken));
+            pw.print("Ancestral: ");
+            pw.println(Long.toHexString(mAncestralToken));
+            pw.print("Current:   ");
+            pw.println(Long.toHexString(mCurrentToken));
 
             int N = mBackupParticipants.size();
             pw.println("Participants:");
-            for (int i=0; i<N; i++) {
+            for (int i = 0; i < N; i++) {
                 int uid = mBackupParticipants.keyAt(i);
                 pw.print("  uid: ");
                 pw.println(uid);
                 HashSet<String> participants = mBackupParticipants.valueAt(i);
-                for (String app: participants) {
+                for (String app : participants) {
                     pw.println("    " + app);
                 }
             }
@@ -3572,14 +3657,16 @@
 
             pw.println("Full backup queue:" + mFullBackupQueue.size());
             for (FullBackupEntry entry : mFullBackupQueue) {
-                pw.print("    "); pw.print(entry.lastBackup);
-                pw.print(" : "); pw.println(entry.packageName);
+                pw.print("    ");
+                pw.print(entry.lastBackup);
+                pw.print(" : ");
+                pw.println(entry.packageName);
             }
         }
     }
 
     public static void sendBackupOnUpdate(IBackupObserver observer, String packageName,
-        BackupProgress progress) {
+            BackupProgress progress) {
         if (observer != null) {
             try {
                 observer.onUpdate(packageName, progress);
@@ -3592,7 +3679,7 @@
     }
 
     public static void sendBackupOnPackageResult(IBackupObserver observer, String packageName,
-        int status) {
+            int status) {
         if (observer != null) {
             try {
                 observer.onResult(packageName, status);
@@ -3650,7 +3737,7 @@
     }
 
     public static IBackupManagerMonitor monitorEvent(IBackupManagerMonitor monitor, int id,
-        PackageInfo pkg, int category, Bundle extras) {
+            PackageInfo pkg, int category, Bundle extras) {
         if (monitor != null) {
             try {
                 Bundle bundle = new Bundle();
@@ -3667,7 +3754,7 @@
                 }
                 monitor.onEvent(bundle);
                 return monitor;
-            } catch(RemoteException e) {
+            } catch (RemoteException e) {
                 if (DEBUG) {
                     Slog.w(TAG, "backup manager monitor went away");
                 }
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index 0f7644c..57cbbd0 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -30,9 +30,11 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.StringBuilderPrinter;
+
 import com.android.server.AppWidgetBackupBridge;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.RefactoredBackupManagerService;
+
 import java.io.BufferedOutputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -57,7 +59,7 @@
 
     class FullBackupRunner implements Runnable {
 
-      PackageInfo mPackage;
+        PackageInfo mPackage;
         byte[] mWidgetData;
         IBackupAgent mAgent;
         ParcelFileDescriptor mPipe;
@@ -66,8 +68,8 @@
         boolean mWriteManifest;
 
         FullBackupRunner(PackageInfo pack, IBackupAgent agent, ParcelFileDescriptor pipe,
-            int token, boolean sendApk, boolean writeManifest, byte[] widgetData)
-            throws IOException {
+                int token, boolean sendApk, boolean writeManifest, byte[] widgetData)
+                throws IOException {
             mPackage = pack;
             mWidgetData = widgetData;
             mAgent = agent;
@@ -85,24 +87,26 @@
                 if (mWriteManifest) {
                     final boolean writeWidgetData = mWidgetData != null;
                     if (RefactoredBackupManagerService.MORE_DEBUG) {
-                      Slog.d(RefactoredBackupManagerService.TAG, "Writing manifest for " + mPackage.packageName);
+                        Slog.d(RefactoredBackupManagerService.TAG,
+                                "Writing manifest for " + mPackage.packageName);
                     }
                     RefactoredBackupManagerService
-                        .writeAppManifest(mPackage, backupManagerService.mPackageManager, mManifestFile, mSendApk,
-                            writeWidgetData);
+                            .writeAppManifest(mPackage, backupManagerService.mPackageManager,
+                                    mManifestFile, mSendApk,
+                                    writeWidgetData);
                     FullBackup.backupToTar(mPackage.packageName, null, null,
-                        mFilesDir.getAbsolutePath(),
-                        mManifestFile.getAbsolutePath(),
-                        output);
+                            mFilesDir.getAbsolutePath(),
+                            mManifestFile.getAbsolutePath(),
+                            output);
                     mManifestFile.delete();
 
                     // We only need to write a metadata file if we have widget data to stash
                     if (writeWidgetData) {
                         writeMetadata(mPackage, mMetadataFile, mWidgetData);
                         FullBackup.backupToTar(mPackage.packageName, null, null,
-                            mFilesDir.getAbsolutePath(),
-                            mMetadataFile.getAbsolutePath(),
-                            output);
+                                mFilesDir.getAbsolutePath(),
+                                mMetadataFile.getAbsolutePath(),
+                                output);
                         mMetadataFile.delete();
                     }
                 }
@@ -112,17 +116,23 @@
                 }
 
                 if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.d(RefactoredBackupManagerService.TAG, "Calling doFullBackup() on " + mPackage.packageName);
+                    Slog.d(RefactoredBackupManagerService.TAG,
+                            "Calling doFullBackup() on " + mPackage.packageName);
                 }
                 backupManagerService
-                    .prepareOperationTimeout(mToken, RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
-                        mTimeoutMonitor /* in parent class */, RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
-                mAgent.doFullBackup(mPipe, mQuota, mToken, backupManagerService.mBackupManagerBinder);
+                        .prepareOperationTimeout(mToken,
+                                RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                                mTimeoutMonitor /* in parent class */,
+                                RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
+                mAgent.doFullBackup(mPipe, mQuota, mToken,
+                        backupManagerService.mBackupManagerBinder);
             } catch (IOException e) {
-                Slog.e(RefactoredBackupManagerService.TAG, "Error running full backup for " + mPackage.packageName);
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Error running full backup for " + mPackage.packageName);
             } catch (RemoteException e) {
-                Slog.e(RefactoredBackupManagerService.TAG, "Remote agent vanished during full backup of "
-                    + mPackage.packageName);
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Remote agent vanished during full backup of "
+                                + mPackage.packageName);
             } finally {
                 try {
                     mPipe.close();
@@ -133,9 +143,9 @@
     }
 
     public FullBackupEngine(RefactoredBackupManagerService backupManagerService,
-        OutputStream output,
-        FullBackupPreflight preflightHook, PackageInfo pkg,
-        boolean alsoApks, BackupRestoreTask timeoutMonitor, long quota, int opToken) {
+            OutputStream output,
+            FullBackupPreflight preflightHook, PackageInfo pkg,
+            boolean alsoApks, BackupRestoreTask timeoutMonitor, long quota, int opToken) {
         this.backupManagerService = backupManagerService;
         mOutput = output;
         mPreflightHook = preflightHook;
@@ -143,8 +153,10 @@
         mIncludeApks = alsoApks;
         mTimeoutMonitor = timeoutMonitor;
         mFilesDir = new File("/data/system");
-        mManifestFile = new File(mFilesDir, RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME);
-        mMetadataFile = new File(mFilesDir, RefactoredBackupManagerService.BACKUP_METADATA_FILENAME);
+        mManifestFile = new File(mFilesDir,
+                RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME);
+        mMetadataFile = new File(mFilesDir,
+                RefactoredBackupManagerService.BACKUP_METADATA_FILENAME);
         mQuota = quota;
         mOpToken = opToken;
     }
@@ -163,7 +175,8 @@
             }
             return result;
         } else {
-            Slog.w(RefactoredBackupManagerService.TAG, "Unable to bind to full agent for " + mPkg.packageName);
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Unable to bind to full agent for " + mPkg.packageName);
             return BackupTransport.AGENT_ERROR;
         }
     }
@@ -178,20 +191,20 @@
 
                 ApplicationInfo app = mPkg.applicationInfo;
                 final boolean isSharedStorage =
-                    mPkg.packageName.equals(
-                        RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE);
+                        mPkg.packageName.equals(
+                                RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE);
                 final boolean sendApk = mIncludeApks
-                    && !isSharedStorage
-                    && ((app.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) == 0)
-                    && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
-                    (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
+                        && !isSharedStorage
+                        && ((app.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) == 0)
+                        && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
+                        (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
 
                 // TODO: http://b/22388012
                 byte[] widgetBlob = AppWidgetBackupBridge.getWidgetState(mPkg.packageName,
-                    UserHandle.USER_SYSTEM);
+                        UserHandle.USER_SYSTEM);
 
                 FullBackupRunner runner = new FullBackupRunner(mPkg, mAgent, pipes[1],
-                    mOpToken, sendApk, !isSharedStorage, widgetBlob);
+                        mOpToken, sendApk, !isSharedStorage, widgetBlob);
                 pipes[1].close();   // the runner has dup'd it
                 pipes[1] = null;
                 Thread t = new Thread(runner, "app-data-runner");
@@ -201,15 +214,18 @@
                 RefactoredBackupManagerService.routeSocketDataToOutput(pipes[0], mOutput);
 
                 if (!backupManagerService.waitUntilOperationComplete(mOpToken)) {
-                    Slog.e(RefactoredBackupManagerService.TAG, "Full backup failed on package " + mPkg.packageName);
+                    Slog.e(RefactoredBackupManagerService.TAG,
+                            "Full backup failed on package " + mPkg.packageName);
                 } else {
                     if (RefactoredBackupManagerService.MORE_DEBUG) {
-                        Slog.d(RefactoredBackupManagerService.TAG, "Full package backup success: " + mPkg.packageName);
+                        Slog.d(RefactoredBackupManagerService.TAG,
+                                "Full package backup success: " + mPkg.packageName);
                     }
                     result = BackupTransport.TRANSPORT_OK;
                 }
             } catch (IOException e) {
-                Slog.e(RefactoredBackupManagerService.TAG, "Error backing up " + mPkg.packageName + ": " + e.getMessage());
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Error backing up " + mPkg.packageName + ": " + e.getMessage());
                 result = BackupTransport.AGENT_ERROR;
             } finally {
                 try {
@@ -217,10 +233,10 @@
                     mOutput.flush();
                     if (pipes != null) {
                         if (pipes[0] != null) {
-                          pipes[0].close();
+                            pipes[0].close();
                         }
                         if (pipes[1] != null) {
-                          pipes[1].close();
+                            pipes[1].close();
                         }
                     }
                 } catch (IOException e) {
@@ -229,7 +245,8 @@
                 }
             }
         } else {
-            Slog.w(RefactoredBackupManagerService.TAG, "Unable to bind to full agent for " + mPkg.packageName);
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Unable to bind to full agent for " + mPkg.packageName);
         }
         tearDown();
         return result;
@@ -240,7 +257,8 @@
             try {
                 mAgent.doQuotaExceeded(backupDataBytes, quotaBytes);
             } catch (RemoteException e) {
-                Slog.e(RefactoredBackupManagerService.TAG, "Remote exception while telling agent about quota exceeded");
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Remote exception while telling agent about quota exceeded");
             }
         }
     }
@@ -248,10 +266,11 @@
     private boolean initializeAgent() {
         if (mAgent == null) {
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-                Slog.d(RefactoredBackupManagerService.TAG, "Binding to full backup agent : " + mPkg.packageName);
+                Slog.d(RefactoredBackupManagerService.TAG,
+                        "Binding to full backup agent : " + mPkg.packageName);
             }
             mAgent = backupManagerService.bindToAgentSynchronous(mPkg.applicationInfo,
-                ApplicationThreadConstants.BACKUP_MODE_FULL);
+                    ApplicationThreadConstants.BACKUP_MODE_FULL);
         }
         return mAgent != null;
     }
@@ -262,7 +281,7 @@
         final String appSourceDir = pkg.applicationInfo.getBaseCodePath();
         final String apkDir = new File(appSourceDir).getParent();
         FullBackup.backupToTar(pkg.packageName, FullBackup.APK_TREE_TOKEN, null,
-            apkDir, appSourceDir, output);
+                apkDir, appSourceDir, output);
 
         // TODO: migrate this to SharedStorageBackup, since AID_SYSTEM
         // doesn't have access to external storage.
@@ -274,14 +293,14 @@
         final File obbDir = userEnv.buildExternalStorageAppObbDirs(pkg.packageName)[0];
         if (obbDir != null) {
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Log.i(RefactoredBackupManagerService.TAG, "obb dir: " + obbDir.getAbsolutePath());
+                Log.i(RefactoredBackupManagerService.TAG, "obb dir: " + obbDir.getAbsolutePath());
             }
             File[] obbFiles = obbDir.listFiles();
             if (obbFiles != null) {
                 final String obbDirName = obbDir.getAbsolutePath();
                 for (File obb : obbFiles) {
                     FullBackup.backupToTar(pkg.packageName, FullBackup.OBB_TREE_TOKEN, null,
-                        obbDirName, obb.getAbsolutePath(), output);
+                            obbDirName, obb.getAbsolutePath(), output);
                 }
             }
         }
@@ -304,7 +323,7 @@
     //
     // Unrecognized blobs are *ignored*, not errors.
     private void writeMetadata(PackageInfo pkg, File destination, byte[] widgetData)
-        throws IOException {
+            throws IOException {
         StringBuilder b = new StringBuilder(512);
         StringBuilderPrinter printer = new StringBuilderPrinter(b);
         printer.println(Integer.toString(RefactoredBackupManagerService.BACKUP_METADATA_VERSION));
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
index 8ca27b5..32b741a 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
@@ -26,8 +26,10 @@
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.util.Slog;
+
 import com.android.internal.backup.IObbBackupService;
 import com.android.server.backup.RefactoredBackupManagerService;
+
 import java.io.IOException;
 import java.io.OutputStream;
 
@@ -43,13 +45,13 @@
 
     public void establish() {
         if (RefactoredBackupManagerService.MORE_DEBUG) {
-          Slog.i(RefactoredBackupManagerService.TAG, "Initiating bind of OBB service on " + this);
+            Slog.i(RefactoredBackupManagerService.TAG, "Initiating bind of OBB service on " + this);
         }
         Intent obbIntent = new Intent().setComponent(new ComponentName(
-            "com.android.sharedstoragebackup",
-            "com.android.sharedstoragebackup.ObbBackupService"));
+                "com.android.sharedstoragebackup",
+                "com.android.sharedstoragebackup.ObbBackupService"));
         backupManagerService.mContext.bindServiceAsUser(
-            obbIntent, this, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
+                obbIntent, this, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
     }
 
     public void tearDown() {
@@ -65,9 +67,11 @@
             pipes = ParcelFileDescriptor.createPipe();
             int token = backupManagerService.generateRandomIntegerToken();
             backupManagerService
-                .prepareOperationTimeout(token, RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
-                    null, RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
-            mService.backupObbs(pkg.packageName, pipes[1], token, backupManagerService.mBackupManagerBinder);
+                    .prepareOperationTimeout(token,
+                            RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                            null, RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
+            mService.backupObbs(pkg.packageName, pipes[1], token,
+                    backupManagerService.mBackupManagerBinder);
             RefactoredBackupManagerService.routeSocketDataToOutput(pipes[0], out);
             success = backupManagerService.waitUntilOperationComplete(token);
         } catch (Exception e) {
@@ -77,10 +81,10 @@
                 out.flush();
                 if (pipes != null) {
                     if (pipes[0] != null) {
-                      pipes[0].close();
+                        pipes[0].close();
                     }
                     if (pipes[1] != null) {
-                      pipes[1].close();
+                        pipes[1].close();
                     }
                 }
             } catch (IOException e) {
@@ -91,13 +95,13 @@
     }
 
     public void restoreObbFile(String pkgName, ParcelFileDescriptor data,
-        long fileSize, int type, String path, long mode, long mtime,
-        int token, IBackupManager callbackBinder) {
+            long fileSize, int type, String path, long mode, long mtime,
+            int token, IBackupManager callbackBinder) {
         waitForConnection();
 
         try {
             mService.restoreObbFile(pkgName, data, fileSize, type, path, mode, mtime,
-                token, callbackBinder);
+                    token, callbackBinder);
         } catch (Exception e) {
             Slog.w(RefactoredBackupManagerService.TAG, "Unable to restore OBBs for " + pkgName, e);
         }
@@ -107,14 +111,15 @@
         synchronized (this) {
             while (mService == null) {
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
-                  Slog.i(RefactoredBackupManagerService.TAG, "...waiting for OBB service binding...");
+                    Slog.i(RefactoredBackupManagerService.TAG,
+                            "...waiting for OBB service binding...");
                 }
                 try {
                     this.wait();
                 } catch (InterruptedException e) { /* never interrupted */ }
             }
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Slog.i(RefactoredBackupManagerService.TAG, "Connected to OBB service; continuing");
+                Slog.i(RefactoredBackupManagerService.TAG, "Connected to OBB service; continuing");
             }
         }
     }
@@ -124,8 +129,8 @@
         synchronized (this) {
             mService = IObbBackupService.Stub.asInterface(service);
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Slog.i(RefactoredBackupManagerService.TAG, "OBB service connection " + mService
-                  + " connected on " + this);
+                Slog.i(RefactoredBackupManagerService.TAG, "OBB service connection " + mService
+                        + " connected on " + this);
             }
             this.notifyAll();
         }
@@ -136,7 +141,8 @@
         synchronized (this) {
             mService = null;
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Slog.i(RefactoredBackupManagerService.TAG, "OBB service connection disconnected on " + this);
+                Slog.i(RefactoredBackupManagerService.TAG,
+                        "OBB service connection disconnected on " + this);
             }
             this.notifyAll();
         }
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupPreflight.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupPreflight.java
index 1ed57d5..f12587f 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupPreflight.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupPreflight.java
@@ -25,14 +25,14 @@
  */
 public interface FullBackupPreflight {
 
-  /**
-   * Perform the preflight operation necessary for the given package.
-   *
-   * @param pkg The name of the package being proposed for full-data backup
-   * @param agent Live BackupAgent binding to the target app's agent
-   * @return BackupTransport.TRANSPORT_OK to proceed with the backup operation, or one of the
-   * other BackupTransport.* error codes as appropriate
-   */
+    /**
+     * Perform the preflight operation necessary for the given package.
+     *
+     * @param pkg The name of the package being proposed for full-data backup
+     * @param agent Live BackupAgent binding to the target app's agent
+     * @return BackupTransport.TRANSPORT_OK to proceed with the backup operation, or one of the
+     * other BackupTransport.* error codes as appropriate
+     */
     int preflightFullBackup(PackageInfo pkg, IBackupAgent agent);
 
     long getExpectedSizeOrErrorCode();
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
index cba838b..38ab0bf 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
@@ -19,6 +19,7 @@
 import android.app.backup.IFullBackupRestoreObserver;
 import android.os.RemoteException;
 import android.util.Slog;
+
 import com.android.server.backup.RefactoredBackupManagerService;
 
 /**
@@ -38,7 +39,8 @@
             try {
                 mObserver.onStartBackup();
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full backup observer went away: startBackup");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full backup observer went away: startBackup");
                 mObserver = null;
             }
         }
@@ -50,7 +52,8 @@
                 // TODO: use a more user-friendly name string
                 mObserver.onBackupPackage(name);
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full backup observer went away: backupPackage");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full backup observer went away: backupPackage");
                 mObserver = null;
             }
         }
@@ -61,7 +64,8 @@
             try {
                 mObserver.onEndBackup();
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full backup observer went away: endBackup");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full backup observer went away: endBackup");
                 mObserver = null;
             }
         }
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index d2c5963..9e02153 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -25,10 +25,12 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Slog;
+
 import com.android.server.AppWidgetBackupBridge;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.KeyValueAdbBackupEngine;
 import com.android.server.backup.RefactoredBackupManagerService;
+
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.FileOutputStream;
@@ -43,6 +45,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.zip.Deflater;
 import java.util.zip.DeflaterOutputStream;
+
 import javax.crypto.Cipher;
 import javax.crypto.CipherOutputStream;
 import javax.crypto.SecretKey;
@@ -74,10 +77,10 @@
     private final int mCurrentOpToken;
 
     public PerformAdbBackupTask(RefactoredBackupManagerService backupManagerService,
-        ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
-        boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets,
-        String curPassword, String encryptPassword, boolean doAllApps, boolean doSystem,
-        boolean doCompress, boolean doKeyValue, String[] packages, AtomicBoolean latch) {
+            ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
+            boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets,
+            String curPassword, String encryptPassword, boolean doAllApps, boolean doSystem,
+            boolean doCompress, boolean doKeyValue, String[] packages, AtomicBoolean latch) {
         super(observer);
         this.backupManagerService = backupManagerService;
         mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
@@ -91,8 +94,8 @@
         mAllApps = doAllApps;
         mIncludeSystem = doSystem;
         mPackages = (packages == null)
-            ? new ArrayList<String>()
-            : new ArrayList<>(Arrays.asList(packages));
+                ? new ArrayList<String>()
+                : new ArrayList<>(Arrays.asList(packages));
         mCurrentPassword = curPassword;
         // when backing up, if there is a current backup password, we require that
         // the user use a nonempty encryption password as well.  if one is supplied
@@ -104,7 +107,8 @@
             mEncryptPassword = encryptPassword;
         }
         if (RefactoredBackupManagerService.MORE_DEBUG) {
-            Slog.w(RefactoredBackupManagerService.TAG, "Encrypting backup with passphrase=" + mEncryptPassword);
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Encrypting backup with passphrase=" + mEncryptPassword);
         }
         mCompress = doCompress;
         mKeyValue = doKeyValue;
@@ -115,29 +119,31 @@
             if (!set.containsKey(pkgName)) {
                 try {
                     PackageInfo info = backupManagerService.mPackageManager.getPackageInfo(pkgName,
-                        PackageManager.GET_SIGNATURES);
+                            PackageManager.GET_SIGNATURES);
                     set.put(pkgName, info);
                 } catch (NameNotFoundException e) {
-                    Slog.w(RefactoredBackupManagerService.TAG, "Unknown package " + pkgName + ", skipping");
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "Unknown package " + pkgName + ", skipping");
                 }
             }
         }
     }
 
     private OutputStream emitAesBackupHeader(StringBuilder headerbuf,
-        OutputStream ofstream) throws Exception {
+            OutputStream ofstream) throws Exception {
         // User key will be used to encrypt the master key.
         byte[] newUserSalt = backupManagerService
-            .randomBytes(RefactoredBackupManagerService.PBKDF2_SALT_SIZE);
+                .randomBytes(RefactoredBackupManagerService.PBKDF2_SALT_SIZE);
         SecretKey userKey = backupManagerService
-            .buildPasswordKey(RefactoredBackupManagerService.PBKDF_CURRENT, mEncryptPassword, newUserSalt,
-                RefactoredBackupManagerService.PBKDF2_HASH_ROUNDS);
+                .buildPasswordKey(RefactoredBackupManagerService.PBKDF_CURRENT, mEncryptPassword,
+                        newUserSalt,
+                        RefactoredBackupManagerService.PBKDF2_HASH_ROUNDS);
 
         // the master key is random for each backup
         byte[] masterPw = new byte[256 / 8];
         backupManagerService.mRng.nextBytes(masterPw);
         byte[] checksumSalt = backupManagerService
-            .randomBytes(RefactoredBackupManagerService.PBKDF2_SALT_SIZE);
+                .randomBytes(RefactoredBackupManagerService.PBKDF2_SALT_SIZE);
 
         // primary encryption of the datastream with the random key
         Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
@@ -179,11 +185,12 @@
         IV = c.getIV();
         byte[] mk = masterKeySpec.getEncoded();
         byte[] checksum = backupManagerService
-            .makeKeyChecksum(RefactoredBackupManagerService.PBKDF_CURRENT, masterKeySpec.getEncoded(),
-                checksumSalt, RefactoredBackupManagerService.PBKDF2_HASH_ROUNDS);
+                .makeKeyChecksum(RefactoredBackupManagerService.PBKDF_CURRENT,
+                        masterKeySpec.getEncoded(),
+                        checksumSalt, RefactoredBackupManagerService.PBKDF2_HASH_ROUNDS);
 
         ByteArrayOutputStream blob = new ByteArrayOutputStream(IV.length + mk.length
-            + checksum.length + 3);
+                + checksum.length + 3);
         DataOutputStream mkOut = new DataOutputStream(blob);
         mkOut.writeByte(IV.length);
         mkOut.write(IV);
@@ -205,31 +212,34 @@
             byte[] eof = new byte[512 * 2]; // newly allocated == zero filled
             out.write(eof);
         } catch (IOException e) {
-            Slog.w(RefactoredBackupManagerService.TAG, "Error attempting to finalize backup stream");
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Error attempting to finalize backup stream");
         }
     }
 
     @Override
     public void run() {
         String includeKeyValue = mKeyValue ? ", including key-value backups" : "";
-        Slog.i(RefactoredBackupManagerService.TAG, "--- Performing adb backup" + includeKeyValue + " ---");
+        Slog.i(RefactoredBackupManagerService.TAG,
+                "--- Performing adb backup" + includeKeyValue + " ---");
 
         TreeMap<String, PackageInfo> packagesToBackup = new TreeMap<>();
         FullBackupObbConnection obbConnection = new FullBackupObbConnection(
-            backupManagerService);
+                backupManagerService);
         obbConnection.establish();  // we'll want this later
 
         sendStartBackup();
 
         // doAllApps supersedes the package set if any
         if (mAllApps) {
-            List<PackageInfo> allPackages = backupManagerService.mPackageManager.getInstalledPackages(
-                PackageManager.GET_SIGNATURES);
+            List<PackageInfo> allPackages =
+                    backupManagerService.mPackageManager.getInstalledPackages(
+                            PackageManager.GET_SIGNATURES);
             for (int i = 0; i < allPackages.size(); i++) {
                 PackageInfo pkg = allPackages.get(i);
                 // Exclude system apps if we've been asked to do so
                 if (mIncludeSystem == true
-                    || ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
+                        || ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
                     packagesToBackup.put(pkg.packageName, pkg);
                 }
             }
@@ -240,10 +250,11 @@
         if (mDoWidgets) {
             // TODO: http://b/22388012
             List<String> pkgs =
-                AppWidgetBackupBridge.getWidgetParticipants(UserHandle.USER_SYSTEM);
+                    AppWidgetBackupBridge.getWidgetParticipants(UserHandle.USER_SYSTEM);
             if (pkgs != null) {
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
-                    Slog.i(RefactoredBackupManagerService.TAG, "Adding widget participants to backup set:");
+                    Slog.i(RefactoredBackupManagerService.TAG,
+                            "Adding widget participants to backup set:");
                     StringBuilder sb = new StringBuilder(128);
                     sb.append("   ");
                     for (String s : pkgs) {
@@ -272,17 +283,17 @@
         while (iter.hasNext()) {
             PackageInfo pkg = iter.next().getValue();
             if (!RefactoredBackupManagerService.appIsEligibleForBackup(pkg.applicationInfo)
-                || RefactoredBackupManagerService.appIsStopped(pkg.applicationInfo)) {
+                    || RefactoredBackupManagerService.appIsStopped(pkg.applicationInfo)) {
                 iter.remove();
                 if (RefactoredBackupManagerService.DEBUG) {
                     Slog.i(RefactoredBackupManagerService.TAG, "Package " + pkg.packageName
-                        + " is not eligible for backup, removing.");
+                            + " is not eligible for backup, removing.");
                 }
             } else if (RefactoredBackupManagerService.appIsKeyValueOnly(pkg)) {
                 iter.remove();
                 if (RefactoredBackupManagerService.DEBUG) {
                     Slog.i(RefactoredBackupManagerService.TAG, "Package " + pkg.packageName
-                        + " is key-value.");
+                            + " is key-value.");
                 }
                 keyValueBackupQueue.add(pkg);
             }
@@ -290,7 +301,7 @@
 
         // flatten the set of packages now so we can explicitly control the ordering
         ArrayList<PackageInfo> backupQueue =
-            new ArrayList<>(packagesToBackup.values());
+                new ArrayList<>(packagesToBackup.values());
         FileOutputStream ofstream = new FileOutputStream(mOutputFile.getFileDescriptor());
         OutputStream out = null;
 
@@ -300,7 +311,8 @@
 
             // Only allow encrypted backups of encrypted devices
             if (backupManagerService.deviceIsEncrypted() && !encrypting) {
-                Slog.e(RefactoredBackupManagerService.TAG, "Unencrypted backup of encrypted device; aborting");
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Unencrypted backup of encrypted device; aborting");
                 return;
             }
 
@@ -310,7 +322,8 @@
             // backup password, if any
             if (!backupManagerService.backupPasswordMatches(mCurrentPassword)) {
                 if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.w(RefactoredBackupManagerService.TAG, "Backup password mismatch; aborting");
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "Backup password mismatch; aborting");
                 }
                 return;
             }
@@ -343,7 +356,8 @@
             StringBuilder headerbuf = new StringBuilder(1024);
 
             headerbuf.append(RefactoredBackupManagerService.BACKUP_FILE_HEADER_MAGIC);
-            headerbuf.append(RefactoredBackupManagerService.BACKUP_FILE_VERSION); // integer, no trailing \n
+            headerbuf.append(
+                    RefactoredBackupManagerService.BACKUP_FILE_VERSION); // integer, no trailing \n
             headerbuf.append(mCompress ? "\n1\n" : "\n0\n");
 
             try {
@@ -374,10 +388,11 @@
             if (mIncludeShared) {
                 try {
                     pkg = backupManagerService.mPackageManager.getPackageInfo(
-                        RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE, 0);
+                            RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE, 0);
                     backupQueue.add(pkg);
                 } catch (NameNotFoundException e) {
-                    Slog.e(RefactoredBackupManagerService.TAG, "Unable to find shared-storage backup handler");
+                    Slog.e(RefactoredBackupManagerService.TAG,
+                            "Unable to find shared-storage backup handler");
                 }
             }
 
@@ -387,15 +402,15 @@
                 pkg = backupQueue.get(i);
                 if (RefactoredBackupManagerService.DEBUG) {
                     Slog.i(RefactoredBackupManagerService.TAG,
-                        "--- Performing full backup for package " + pkg.packageName
-                            + " ---");
+                            "--- Performing full backup for package " + pkg.packageName
+                                    + " ---");
                 }
                 final boolean isSharedStorage =
-                    pkg.packageName.equals(
-                        RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE);
+                        pkg.packageName.equals(
+                                RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE);
 
                 mBackupEngine = new FullBackupEngine(backupManagerService, out,
-                    null, pkg, mIncludeApks, this, Long.MAX_VALUE, mCurrentOpToken);
+                        null, pkg, mIncludeApks, this, Long.MAX_VALUE, mCurrentOpToken);
                 sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName);
 
                 // Don't need to check preflight result as there is no preflight hook.
@@ -415,13 +430,16 @@
             if (mKeyValue) {
                 for (PackageInfo keyValuePackage : keyValueBackupQueue) {
                     if (RefactoredBackupManagerService.DEBUG) {
-                        Slog.i(RefactoredBackupManagerService.TAG, "--- Performing key-value backup for package "
-                            + keyValuePackage.packageName + " ---");
+                        Slog.i(RefactoredBackupManagerService.TAG,
+                                "--- Performing key-value backup for package "
+                                        + keyValuePackage.packageName + " ---");
                     }
                     KeyValueAdbBackupEngine kvBackupEngine =
-                        new KeyValueAdbBackupEngine(out, keyValuePackage,
-                            backupManagerService,
-                            backupManagerService.mPackageManager, backupManagerService.mBaseStateDir, backupManagerService.mDataDir);
+                            new KeyValueAdbBackupEngine(out, keyValuePackage,
+                                    backupManagerService,
+                                    backupManagerService.mPackageManager,
+                                    backupManagerService.mBaseStateDir,
+                                    backupManagerService.mDataDir);
                     sendOnBackupPackage(keyValuePackage.packageName);
                     kvBackupEngine.backupOnePackage();
                 }
@@ -450,7 +468,7 @@
             sendEndBackup();
             obbConnection.tearDown();
             if (RefactoredBackupManagerService.DEBUG) {
-              Slog.d(RefactoredBackupManagerService.TAG, "Full backup pass complete.");
+                Slog.d(RefactoredBackupManagerService.TAG, "Full backup pass complete.");
             }
             backupManagerService.mWakelock.release();
         }
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index 0849d04..97d3236 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -32,12 +32,14 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
+
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.FullBackupJob;
 import com.android.server.backup.RefactoredBackupManagerService;
 import com.android.server.backup.internal.Operation;
+
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -99,10 +101,10 @@
     private final int mCurrentOpToken;
 
     public PerformFullTransportBackupTask(RefactoredBackupManagerService backupManagerService,
-        IFullBackupRestoreObserver observer,
-        String[] whichPackages, boolean updateSchedule,
-        FullBackupJob runningJob, CountDownLatch latch, IBackupObserver backupObserver,
-        IBackupManagerMonitor monitor, boolean userInitiated) {
+            IFullBackupRestoreObserver observer,
+            String[] whichPackages, boolean updateSchedule,
+            FullBackupJob runningJob, CountDownLatch latch, IBackupObserver backupObserver,
+            IBackupManagerMonitor monitor, boolean userInitiated) {
         super(observer);
         this.backupManagerService = backupManagerService;
         mUpdateSchedule = updateSchedule;
@@ -144,7 +146,7 @@
                             BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
                             null);
                     RefactoredBackupManagerService.sendBackupOnPackageResult(mBackupObserver, pkg,
-                        BackupManager.ERROR_BACKUP_NOT_ALLOWED);
+                            BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                     continue;
                 } else if (!RefactoredBackupManagerService.appGetsFullBackup(info)) {
                     // Cull any packages that are found in the queue but now aren't supposed
@@ -193,7 +195,7 @@
         synchronized (backupManagerService.mCurrentOpLock) {
             Slog.d(TAG, "backupmanager pftbt token=" + Integer.toHexString(mCurrentOpToken));
             backupManagerService.mCurrentOperations.put(mCurrentOpToken, new Operation(
-                RefactoredBackupManagerService.OP_PENDING, this,
+                    RefactoredBackupManagerService.OP_PENDING, this,
                     RefactoredBackupManagerService.OP_TYPE_BACKUP));
         }
     }
@@ -212,7 +214,8 @@
         synchronized (mCancelLock) {
             // We only support 'cancelAll = true' case for this task. Cancelling of a single package
 
-            // due to timeout is handled by SinglePackageBackupRunner and SinglePackageBackupPreflight.
+            // due to timeout is handled by SinglePackageBackupRunner and
+            // SinglePackageBackupPreflight.
 
             if (!cancelAll) {
                 Slog.wtf(TAG, "Expected cancelAll to be true.");
@@ -267,8 +270,9 @@
                     monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED;
                 }
                 mMonitor = RefactoredBackupManagerService
-                    .monitorEvent(mMonitor, monitoringEvent, null,
-                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
+                        .monitorEvent(mMonitor, monitoringEvent, null,
+                                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                null);
                 mUpdateSchedule = false;
                 backupRunStatus = BackupManager.ERROR_BACKUP_NOT_ALLOWED;
                 return;
@@ -377,8 +381,8 @@
                                 totalRead += nRead;
                                 if (mBackupObserver != null && preflightResult > 0) {
                                     RefactoredBackupManagerService
-                                        .sendBackupOnUpdate(mBackupObserver, packageName,
-                                            new BackupProgress(preflightResult, totalRead));
+                                            .sendBackupOnUpdate(mBackupObserver, packageName,
+                                                    new BackupProgress(preflightResult, totalRead));
                                 }
                             }
                         } while (nRead > 0
@@ -466,8 +470,8 @@
 
                 if (backupPackageStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mBackupObserver, packageName,
-                            BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
+                            .sendBackupOnPackageResult(mBackupObserver, packageName,
+                                    BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
                     if (RefactoredBackupManagerService.DEBUG) {
                         Slog.i(TAG, "Transport rejected backup of " + packageName
                                 + ", skipping");
@@ -477,8 +481,8 @@
                     // Do nothing, clean up, and continue looping.
                 } else if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mBackupObserver, packageName,
-                            BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
+                            .sendBackupOnPackageResult(mBackupObserver, packageName,
+                                    BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
                     if (RefactoredBackupManagerService.DEBUG) {
                         Slog.i(TAG, "Transport quota exceeded for package: " + packageName);
                         EventLog.writeEvent(EventLogTags.FULL_BACKUP_QUOTA_EXCEEDED,
@@ -487,16 +491,16 @@
                     // Do nothing, clean up, and continue looping.
                 } else if (backupPackageStatus == BackupTransport.AGENT_ERROR) {
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mBackupObserver, packageName,
-                            BackupManager.ERROR_AGENT_FAILURE);
+                            .sendBackupOnPackageResult(mBackupObserver, packageName,
+                                    BackupManager.ERROR_AGENT_FAILURE);
                     Slog.w(TAG, "Application failure for package: " + packageName);
                     EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
                     backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
                     // Do nothing, clean up, and continue looping.
                 } else if (backupPackageStatus == BackupManager.ERROR_BACKUP_CANCELLED) {
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mBackupObserver, packageName,
-                            BackupManager.ERROR_BACKUP_CANCELLED);
+                            .sendBackupOnPackageResult(mBackupObserver, packageName,
+                                    BackupManager.ERROR_BACKUP_CANCELLED);
                     Slog.w(TAG, "Backup cancelled. package=" + packageName +
                             ", cancelAll=" + mCancelAll);
                     EventLog.writeEvent(EventLogTags.FULL_BACKUP_CANCELLED, packageName);
@@ -504,8 +508,8 @@
                     // Do nothing, clean up, and continue looping.
                 } else if (backupPackageStatus != BackupTransport.TRANSPORT_OK) {
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mBackupObserver, packageName,
-                        BackupManager.ERROR_TRANSPORT_ABORTED);
+                            .sendBackupOnPackageResult(mBackupObserver, packageName,
+                                    BackupManager.ERROR_TRANSPORT_ABORTED);
                     Slog.w(TAG, "Transport failed; aborting backup: " + backupPackageStatus);
                     EventLog.writeEvent(EventLogTags.FULL_BACKUP_TRANSPORT_FAILURE);
                     // Abort entire backup pass.
@@ -514,8 +518,8 @@
                 } else {
                     // Success!
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mBackupObserver, packageName,
-                            BackupManager.SUCCESS);
+                            .sendBackupOnPackageResult(mBackupObserver, packageName,
+                                    BackupManager.SUCCESS);
                     EventLog.writeEvent(EventLogTags.FULL_BACKUP_SUCCESS, packageName);
                     backupManagerService.logBackupComplete(packageName);
                 }
@@ -525,7 +529,8 @@
                     Slog.i(TAG, "Unbinding agent in " + packageName);
                     backupManagerService.addBackupTrace("unbinding " + packageName);
                     try {
-                        backupManagerService.mActivityManager.unbindBackupAgent(currentPackage.applicationInfo);
+                        backupManagerService.mActivityManager.unbindBackupAgent(
+                                currentPackage.applicationInfo);
                     } catch (RemoteException e) { /* can't happen; activity manager is local */ }
                 }
             }
@@ -621,20 +626,23 @@
             int result;
             try {
                 backupManagerService
-                    .prepareOperationTimeout(mCurrentOpToken, RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
-                        this, RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
+                        .prepareOperationTimeout(mCurrentOpToken,
+                                RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                                this, RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
                 backupManagerService.addBackupTrace("preflighting");
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
                     Slog.d(TAG, "Preflighting full payload of " + pkg.packageName);
                 }
-                agent.doMeasureFullBackup(mQuota, mCurrentOpToken, backupManagerService.mBackupManagerBinder);
+                agent.doMeasureFullBackup(mQuota, mCurrentOpToken,
+                        backupManagerService.mBackupManagerBinder);
 
                 // Now wait to get our result back.  If this backstop timeout is reached without
                 // the latch being thrown, flow will continue as though a result or "normal"
                 // timeout had been produced.  In case of a real backstop timeout, mResult
                 // will still contain the value it was constructed with, AGENT_ERROR, which
                 // intentionaly falls into the "just report failure" code.
-                mLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
+                mLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                        TimeUnit.MILLISECONDS);
 
                 long totalSize = mResult.get();
                 // If preflight timed out, mResult will contain error code as int.
@@ -689,7 +697,8 @@
         @Override
         public long getExpectedSizeOrErrorCode() {
             try {
-                mLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
+                mLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                        TimeUnit.MILLISECONDS);
                 return mResult.get();
             } catch (InterruptedException e) {
                 return BackupTransport.NO_MORE_DATA;
@@ -729,7 +738,7 @@
         void registerTask() {
             synchronized (backupManagerService.mCurrentOpLock) {
                 backupManagerService.mCurrentOperations.put(mCurrentOpToken, new Operation(
-                    RefactoredBackupManagerService.OP_PENDING, this,
+                        RefactoredBackupManagerService.OP_PENDING, this,
                         RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT));
             }
         }
@@ -743,7 +752,8 @@
         @Override
         public void run() {
             FileOutputStream out = new FileOutputStream(mOutput.getFileDescriptor());
-            mEngine = new FullBackupEngine(backupManagerService, out, mPreflight, mTarget, false, this, mQuota, mCurrentOpToken);
+            mEngine = new FullBackupEngine(backupManagerService, out, mPreflight, mTarget, false,
+                    this, mQuota, mCurrentOpToken);
             try {
                 try {
                     if (!mIsCancelled) {
@@ -779,7 +789,8 @@
         // otherwise return negative error code.
         long getPreflightResultBlocking() {
             try {
-                mPreflightLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
+                mPreflightLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                        TimeUnit.MILLISECONDS);
                 if (mIsCancelled) {
                     return BackupManager.ERROR_BACKUP_CANCELLED;
                 }
@@ -795,7 +806,8 @@
 
         int getBackupResultBlocking() {
             try {
-                mBackupLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
+                mBackupLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                        TimeUnit.MILLISECONDS);
                 if (mIsCancelled) {
                     return BackupManager.ERROR_BACKUP_CANCELLED;
                 }
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index f6914fc..4ab500a 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -27,6 +27,7 @@
 import android.util.EventLog;
 import android.util.Pair;
 import android.util.Slog;
+
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
 import com.android.server.backup.BackupRestoreTask;
@@ -43,6 +44,7 @@
 import com.android.server.backup.params.RestoreParams;
 import com.android.server.backup.restore.PerformAdbRestoreTask;
 import com.android.server.backup.restore.PerformUnifiedRestoreTask;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -56,7 +58,7 @@
     private RefactoredBackupManagerService backupManagerService;
 
     public BackupHandler(
-        RefactoredBackupManagerService backupManagerService, Looper looper) {
+            RefactoredBackupManagerService backupManagerService, Looper looper) {
         super(looper);
         this.backupManagerService = backupManagerService;
     }
@@ -64,323 +66,346 @@
     public void handleMessage(Message msg) {
 
         switch (msg.what) {
-          case RefactoredBackupManagerService.MSG_RUN_BACKUP: {
-            backupManagerService.mLastBackupPass = System.currentTimeMillis();
+            case RefactoredBackupManagerService.MSG_RUN_BACKUP: {
+                backupManagerService.mLastBackupPass = System.currentTimeMillis();
 
-            IBackupTransport transport = backupManagerService.mTransportManager.getCurrentTransportBinder();
-            if (transport == null) {
-              Slog.v(RefactoredBackupManagerService.TAG, "Backup requested but no transport available");
-              synchronized (backupManagerService.mQueueLock) {
-                backupManagerService.mBackupRunning = false;
-              }
-              backupManagerService.mWakelock.release();
-              break;
-            }
-
-            // snapshot the pending-backup set and work on that
-            ArrayList<BackupRequest> queue = new ArrayList<>();
-            File oldJournal = backupManagerService.mJournal;
-            synchronized (backupManagerService.mQueueLock) {
-              // Do we have any work to do?  Construct the work queue
-              // then release the synchronization lock to actually run
-              // the backup.
-              if (backupManagerService.mPendingBackups.size() > 0) {
-                for (BackupRequest b : backupManagerService.mPendingBackups.values()) {
-                  queue.add(b);
+                IBackupTransport transport =
+                        backupManagerService.mTransportManager.getCurrentTransportBinder();
+                if (transport == null) {
+                    Slog.v(RefactoredBackupManagerService.TAG,
+                            "Backup requested but no transport available");
+                    synchronized (backupManagerService.mQueueLock) {
+                        backupManagerService.mBackupRunning = false;
+                    }
+                    backupManagerService.mWakelock.release();
+                    break;
                 }
-                if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.v(RefactoredBackupManagerService.TAG, "clearing pending backups");
+
+                // snapshot the pending-backup set and work on that
+                ArrayList<BackupRequest> queue = new ArrayList<>();
+                File oldJournal = backupManagerService.mJournal;
+                synchronized (backupManagerService.mQueueLock) {
+                    // Do we have any work to do?  Construct the work queue
+                    // then release the synchronization lock to actually run
+                    // the backup.
+                    if (backupManagerService.mPendingBackups.size() > 0) {
+                        for (BackupRequest b : backupManagerService.mPendingBackups.values()) {
+                            queue.add(b);
+                        }
+                        if (RefactoredBackupManagerService.DEBUG) {
+                            Slog.v(RefactoredBackupManagerService.TAG, "clearing pending backups");
+                        }
+                        backupManagerService.mPendingBackups.clear();
+
+                        // Start a new backup-queue journal file too
+                        backupManagerService.mJournal = null;
+
+                    }
                 }
-                backupManagerService.mPendingBackups.clear();
 
-                // Start a new backup-queue journal file too
-                backupManagerService.mJournal = null;
-
-              }
-            }
-
-            // At this point, we have started a new journal file, and the old
-            // file identity is being passed to the backup processing task.
-            // When it completes successfully, that old journal file will be
-            // deleted.  If we crash prior to that, the old journal is parsed
-            // at next boot and the journaled requests fulfilled.
-            boolean staged = true;
-            if (queue.size() > 0) {
-              // Spin up a backup state sequence and set it running
-              try {
-                String dirName = transport.transportDirName();
-                PerformBackupTask pbt = new PerformBackupTask(
-                    backupManagerService, transport, dirName, queue,
-                            oldJournal, null, null, Collections.<String>emptyList(), false,
-                            false /* nonIncremental */);
-                Message pbtMessage = obtainMessage(
-                    RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, pbt);
-                sendMessage(pbtMessage);
-              } catch (Exception e) {
-                // unable to ask the transport its dir name -- transient failure, since
-                // the above check succeeded.  Try again next time.
-                Slog.e(RefactoredBackupManagerService.TAG, "Transport became unavailable attempting backup"
-                            + " or error initializing backup task", e);
-                staged = false;
-              }
-            } else {
-              Slog.v(RefactoredBackupManagerService.TAG, "Backup requested but nothing pending");
-              staged = false;
-            }
-
-            if (!staged) {
-              // if we didn't actually hand off the wakelock, rewind until next time
-              synchronized (backupManagerService.mQueueLock) {
-                backupManagerService.mBackupRunning = false;
-              }
-              backupManagerService.mWakelock.release();
-            }
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP: {
-            try {
-              BackupRestoreTask task = (BackupRestoreTask) msg.obj;
-              if (RefactoredBackupManagerService.MORE_DEBUG) {
-                Slog.v(RefactoredBackupManagerService.TAG, "Got next step for " + task + ", executing");
-              }
-              task.execute();
-            } catch (ClassCastException e) {
-              Slog.e(RefactoredBackupManagerService.TAG, "Invalid backup task in flight, obj=" + msg.obj);
-            }
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_OP_COMPLETE: {
-            try {
-              Pair<BackupRestoreTask, Long> taskWithResult =
-                        (Pair<BackupRestoreTask, Long>) msg.obj;
-              taskWithResult.first.operationComplete(taskWithResult.second);
-            } catch (ClassCastException e) {
-              Slog.e(RefactoredBackupManagerService.TAG, "Invalid completion in flight, obj=" + msg.obj);
-            }
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RUN_ADB_BACKUP: {
-            // TODO: refactor full backup to be a looper-based state machine
-            // similar to normal backup/restore.
-            AdbBackupParams params = (AdbBackupParams) msg.obj;
-            PerformAdbBackupTask task = new PerformAdbBackupTask(backupManagerService, params.fd,
-                    params.observer, params.includeApks, params.includeObbs,
-                    params.includeShared, params.doWidgets, params.curPassword,
-                    params.encryptPassword, params.allApps, params.includeSystem,
-                    params.doCompress, params.includeKeyValue, params.packages, params.latch);
-            (new Thread(task, "adb-backup")).start();
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RUN_FULL_TRANSPORT_BACKUP: {
-            PerformFullTransportBackupTask task = (PerformFullTransportBackupTask) msg.obj;
-            (new Thread(task, "transport-backup")).start();
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RUN_RESTORE: {
-            RestoreParams params = (RestoreParams) msg.obj;
-            Slog.d(RefactoredBackupManagerService.TAG, "MSG_RUN_RESTORE observer=" + params.observer);
-
-            PerformUnifiedRestoreTask task = new PerformUnifiedRestoreTask(backupManagerService, params.transport,
-                    params.observer, params.monitor, params.token, params.pkgInfo,
-                    params.pmToken, params.isSystemRestore, params.filterSet);
-
-            synchronized (backupManagerService.mPendingRestores) {
-              if (backupManagerService.mIsRestoreInProgress) {
-                if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.d(RefactoredBackupManagerService.TAG, "Restore in progress, queueing.");
+                // At this point, we have started a new journal file, and the old
+                // file identity is being passed to the backup processing task.
+                // When it completes successfully, that old journal file will be
+                // deleted.  If we crash prior to that, the old journal is parsed
+                // at next boot and the journaled requests fulfilled.
+                boolean staged = true;
+                if (queue.size() > 0) {
+                    // Spin up a backup state sequence and set it running
+                    try {
+                        String dirName = transport.transportDirName();
+                        PerformBackupTask pbt = new PerformBackupTask(
+                                backupManagerService, transport, dirName, queue,
+                                oldJournal, null, null, Collections.<String>emptyList(), false,
+                                false /* nonIncremental */);
+                        Message pbtMessage = obtainMessage(
+                                RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, pbt);
+                        sendMessage(pbtMessage);
+                    } catch (Exception e) {
+                        // unable to ask the transport its dir name -- transient failure, since
+                        // the above check succeeded.  Try again next time.
+                        Slog.e(RefactoredBackupManagerService.TAG,
+                                "Transport became unavailable attempting backup"
+                                        + " or error initializing backup task", e);
+                        staged = false;
+                    }
+                } else {
+                    Slog.v(RefactoredBackupManagerService.TAG,
+                            "Backup requested but nothing pending");
+                    staged = false;
                 }
-                backupManagerService.mPendingRestores.add(task);
-                // This task will be picked up and executed when the the currently running
-                // restore task finishes.
-              } else {
-                if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.d(RefactoredBackupManagerService.TAG, "Starting restore.");
+
+                if (!staged) {
+                    // if we didn't actually hand off the wakelock, rewind until next time
+                    synchronized (backupManagerService.mQueueLock) {
+                        backupManagerService.mBackupRunning = false;
+                    }
+                    backupManagerService.mWakelock.release();
                 }
-                backupManagerService.mIsRestoreInProgress = true;
-                Message restoreMsg = obtainMessage(
-                    RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, task);
-                sendMessage(restoreMsg);
-              }
-            }
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RUN_ADB_RESTORE: {
-            // TODO: refactor full restore to be a looper-based state machine
-            // similar to normal backup/restore.
-            AdbRestoreParams params = (AdbRestoreParams) msg.obj;
-            PerformAdbRestoreTask task = new PerformAdbRestoreTask(backupManagerService, params.fd,
-                    params.curPassword, params.encryptPassword,
-                    params.observer, params.latch);
-            (new Thread(task, "adb-restore")).start();
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RUN_CLEAR: {
-            ClearParams params = (ClearParams) msg.obj;
-            (new PerformClearTask(backupManagerService, params.transport, params.packageInfo)).run();
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RETRY_CLEAR: {
-            // reenqueues if the transport remains unavailable
-            ClearRetryParams params = (ClearRetryParams) msg.obj;
-            backupManagerService.clearBackupData(params.transportName, params.packageName);
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RUN_INITIALIZE: {
-            HashSet<String> queue;
-
-            // Snapshot the pending-init queue and work on that
-            synchronized (backupManagerService.mQueueLock) {
-              queue = new HashSet<>(backupManagerService.mPendingInits);
-              backupManagerService.mPendingInits.clear();
+                break;
             }
 
-            (new PerformInitializeTask(backupManagerService, queue)).run();
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RETRY_INIT: {
-            synchronized (backupManagerService.mQueueLock) {
-              backupManagerService.recordInitPendingLocked(msg.arg1 != 0, (String) msg.obj);
-              backupManagerService.mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
-                        backupManagerService.mRunInitIntent);
-            }
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RUN_GET_RESTORE_SETS: {
-            // Like other async operations, this is entered with the wakelock held
-            RestoreSet[] sets = null;
-            RestoreGetSetsParams params = (RestoreGetSetsParams) msg.obj;
-            try {
-              sets = params.transport.getAvailableRestoreSets();
-              // cache the result in the active session
-              synchronized (params.session) {
-                params.session.mRestoreSets = sets;
-              }
-              if (sets == null) {
-                EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
-              }
-            } catch (Exception e) {
-              Slog.e(RefactoredBackupManagerService.TAG, "Error from transport getting set list: " + e.getMessage());
-            } finally {
-              if (params.observer != null) {
+            case RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP: {
                 try {
-                  params.observer.restoreSetsAvailable(sets);
-                } catch (RemoteException re) {
-                  Slog.e(RefactoredBackupManagerService.TAG, "Unable to report listing to observer");
+                    BackupRestoreTask task = (BackupRestoreTask) msg.obj;
+                    if (RefactoredBackupManagerService.MORE_DEBUG) {
+                        Slog.v(RefactoredBackupManagerService.TAG,
+                                "Got next step for " + task + ", executing");
+                    }
+                    task.execute();
+                } catch (ClassCastException e) {
+                    Slog.e(RefactoredBackupManagerService.TAG,
+                            "Invalid backup task in flight, obj=" + msg.obj);
+                }
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_OP_COMPLETE: {
+                try {
+                    Pair<BackupRestoreTask, Long> taskWithResult =
+                            (Pair<BackupRestoreTask, Long>) msg.obj;
+                    taskWithResult.first.operationComplete(taskWithResult.second);
+                } catch (ClassCastException e) {
+                    Slog.e(RefactoredBackupManagerService.TAG,
+                            "Invalid completion in flight, obj=" + msg.obj);
+                }
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RUN_ADB_BACKUP: {
+                // TODO: refactor full backup to be a looper-based state machine
+                // similar to normal backup/restore.
+                AdbBackupParams params = (AdbBackupParams) msg.obj;
+                PerformAdbBackupTask task = new PerformAdbBackupTask(backupManagerService,
+                        params.fd,
+                        params.observer, params.includeApks, params.includeObbs,
+                        params.includeShared, params.doWidgets, params.curPassword,
+                        params.encryptPassword, params.allApps, params.includeSystem,
+                        params.doCompress, params.includeKeyValue, params.packages, params.latch);
+                (new Thread(task, "adb-backup")).start();
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RUN_FULL_TRANSPORT_BACKUP: {
+                PerformFullTransportBackupTask task = (PerformFullTransportBackupTask) msg.obj;
+                (new Thread(task, "transport-backup")).start();
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RUN_RESTORE: {
+                RestoreParams params = (RestoreParams) msg.obj;
+                Slog.d(RefactoredBackupManagerService.TAG,
+                        "MSG_RUN_RESTORE observer=" + params.observer);
+
+                PerformUnifiedRestoreTask task = new PerformUnifiedRestoreTask(backupManagerService,
+                        params.transport,
+                        params.observer, params.monitor, params.token, params.pkgInfo,
+                        params.pmToken, params.isSystemRestore, params.filterSet);
+
+                synchronized (backupManagerService.mPendingRestores) {
+                    if (backupManagerService.mIsRestoreInProgress) {
+                        if (RefactoredBackupManagerService.DEBUG) {
+                            Slog.d(RefactoredBackupManagerService.TAG,
+                                    "Restore in progress, queueing.");
+                        }
+                        backupManagerService.mPendingRestores.add(task);
+                        // This task will be picked up and executed when the the currently running
+                        // restore task finishes.
+                    } else {
+                        if (RefactoredBackupManagerService.DEBUG) {
+                            Slog.d(RefactoredBackupManagerService.TAG, "Starting restore.");
+                        }
+                        backupManagerService.mIsRestoreInProgress = true;
+                        Message restoreMsg = obtainMessage(
+                                RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, task);
+                        sendMessage(restoreMsg);
+                    }
+                }
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RUN_ADB_RESTORE: {
+                // TODO: refactor full restore to be a looper-based state machine
+                // similar to normal backup/restore.
+                AdbRestoreParams params = (AdbRestoreParams) msg.obj;
+                PerformAdbRestoreTask task = new PerformAdbRestoreTask(backupManagerService,
+                        params.fd,
+                        params.curPassword, params.encryptPassword,
+                        params.observer, params.latch);
+                (new Thread(task, "adb-restore")).start();
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RUN_CLEAR: {
+                ClearParams params = (ClearParams) msg.obj;
+                (new PerformClearTask(backupManagerService, params.transport,
+                        params.packageInfo)).run();
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RETRY_CLEAR: {
+                // reenqueues if the transport remains unavailable
+                ClearRetryParams params = (ClearRetryParams) msg.obj;
+                backupManagerService.clearBackupData(params.transportName, params.packageName);
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RUN_INITIALIZE: {
+                HashSet<String> queue;
+
+                // Snapshot the pending-init queue and work on that
+                synchronized (backupManagerService.mQueueLock) {
+                    queue = new HashSet<>(backupManagerService.mPendingInits);
+                    backupManagerService.mPendingInits.clear();
+                }
+
+                (new PerformInitializeTask(backupManagerService, queue)).run();
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RETRY_INIT: {
+                synchronized (backupManagerService.mQueueLock) {
+                    backupManagerService.recordInitPendingLocked(msg.arg1 != 0, (String) msg.obj);
+                    backupManagerService.mAlarmManager.set(AlarmManager.RTC_WAKEUP,
+                            System.currentTimeMillis(),
+                            backupManagerService.mRunInitIntent);
+                }
+                break;
+            }
+
+            case RefactoredBackupManagerService.MSG_RUN_GET_RESTORE_SETS: {
+                // Like other async operations, this is entered with the wakelock held
+                RestoreSet[] sets = null;
+                RestoreGetSetsParams params = (RestoreGetSetsParams) msg.obj;
+                try {
+                    sets = params.transport.getAvailableRestoreSets();
+                    // cache the result in the active session
+                    synchronized (params.session) {
+                        params.session.mRestoreSets = sets;
+                    }
+                    if (sets == null) {
+                        EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
+                    }
                 } catch (Exception e) {
-                  Slog.e(RefactoredBackupManagerService.TAG, "Restore observer threw: " + e.getMessage());
+                    Slog.e(RefactoredBackupManagerService.TAG,
+                            "Error from transport getting set list: " + e.getMessage());
+                } finally {
+                    if (params.observer != null) {
+                        try {
+                            params.observer.restoreSetsAvailable(sets);
+                        } catch (RemoteException re) {
+                            Slog.e(RefactoredBackupManagerService.TAG,
+                                    "Unable to report listing to observer");
+                        } catch (Exception e) {
+                            Slog.e(RefactoredBackupManagerService.TAG,
+                                    "Restore observer threw: " + e.getMessage());
+                        }
+                    }
+
+                    // Done: reset the session timeout clock
+                    removeMessages(RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+                    sendEmptyMessageDelayed(
+                            RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT,
+                            RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL);
+
+                    backupManagerService.mWakelock.release();
                 }
-              }
-
-              // Done: reset the session timeout clock
-              removeMessages(RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
-              sendEmptyMessageDelayed(RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT,
-                  RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL);
-
-              backupManagerService.mWakelock.release();
+                break;
             }
-            break;
-          }
 
-          case RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT:
-          case RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT: {
-            Slog.d(RefactoredBackupManagerService.TAG,
-                "Timeout message received for token=" + Integer.toHexString(msg.arg1));
-            backupManagerService.handleCancel(msg.arg1, false);
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT: {
-            synchronized (backupManagerService) {
-              if (backupManagerService.mActiveRestoreSession != null) {
-                // Client app left the restore session dangling.  We know that it
-                // can't be in the middle of an actual restore operation because
-                // the timeout is suspended while a restore is in progress.  Clean
-                // up now.
-                Slog.w(RefactoredBackupManagerService.TAG, "Restore session timed out; aborting");
-                backupManagerService.mActiveRestoreSession.markTimedOut();
-                post(backupManagerService.mActiveRestoreSession.new EndRestoreRunnable(
-                    backupManagerService, backupManagerService.mActiveRestoreSession));
-              }
+            case RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT:
+            case RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT: {
+                Slog.d(RefactoredBackupManagerService.TAG,
+                        "Timeout message received for token=" + Integer.toHexString(msg.arg1));
+                backupManagerService.handleCancel(msg.arg1, false);
+                break;
             }
-            break;
-          }
 
-          case RefactoredBackupManagerService.MSG_FULL_CONFIRMATION_TIMEOUT: {
-            synchronized (backupManagerService.mAdbBackupRestoreConfirmations) {
-              AdbParams params = backupManagerService.mAdbBackupRestoreConfirmations.get(msg.arg1);
-              if (params != null) {
-                Slog.i(RefactoredBackupManagerService.TAG,
-                    "Full backup/restore timed out waiting for user confirmation");
+            case RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT: {
+                synchronized (backupManagerService) {
+                    if (backupManagerService.mActiveRestoreSession != null) {
+                        // Client app left the restore session dangling.  We know that it
+                        // can't be in the middle of an actual restore operation because
+                        // the timeout is suspended while a restore is in progress.  Clean
+                        // up now.
+                        Slog.w(RefactoredBackupManagerService.TAG,
+                                "Restore session timed out; aborting");
+                        backupManagerService.mActiveRestoreSession.markTimedOut();
+                        post(backupManagerService.mActiveRestoreSession.new EndRestoreRunnable(
+                                backupManagerService, backupManagerService.mActiveRestoreSession));
+                    }
+                }
+                break;
+            }
 
-                // Release the waiter; timeout == completion
-                backupManagerService.signalAdbBackupRestoreCompletion(params);
+            case RefactoredBackupManagerService.MSG_FULL_CONFIRMATION_TIMEOUT: {
+                synchronized (backupManagerService.mAdbBackupRestoreConfirmations) {
+                    AdbParams params = backupManagerService.mAdbBackupRestoreConfirmations.get(
+                            msg.arg1);
+                    if (params != null) {
+                        Slog.i(RefactoredBackupManagerService.TAG,
+                                "Full backup/restore timed out waiting for user confirmation");
 
-                // Remove the token from the set
-                backupManagerService.mAdbBackupRestoreConfirmations.delete(msg.arg1);
+                        // Release the waiter; timeout == completion
+                        backupManagerService.signalAdbBackupRestoreCompletion(params);
 
-                // Report a timeout to the observer, if any
-                if (params.observer != null) {
-                  try {
-                    params.observer.onTimeout();
-                  } catch (RemoteException e) {
+                        // Remove the token from the set
+                        backupManagerService.mAdbBackupRestoreConfirmations.delete(msg.arg1);
+
+                        // Report a timeout to the observer, if any
+                        if (params.observer != null) {
+                            try {
+                                params.observer.onTimeout();
+                            } catch (RemoteException e) {
                             /* don't care if the app has gone away */
-                  }
+                            }
+                        }
+                    } else {
+                        Slog.d(RefactoredBackupManagerService.TAG,
+                                "couldn't find params for token " + msg.arg1);
+                    }
                 }
-              } else {
-                Slog.d(RefactoredBackupManagerService.TAG, "couldn't find params for token " + msg.arg1);
-              }
+                break;
             }
-            break;
-          }
 
-          case RefactoredBackupManagerService.MSG_WIDGET_BROADCAST: {
-            final Intent intent = (Intent) msg.obj;
-            backupManagerService.mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
-            break;
-          }
-
-          case RefactoredBackupManagerService.MSG_REQUEST_BACKUP: {
-            BackupParams params = (BackupParams) msg.obj;
-            if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Slog.d(RefactoredBackupManagerService.TAG, "MSG_REQUEST_BACKUP observer=" + params.observer);
+            case RefactoredBackupManagerService.MSG_WIDGET_BROADCAST: {
+                final Intent intent = (Intent) msg.obj;
+                backupManagerService.mContext.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+                break;
             }
-            ArrayList<BackupRequest> kvQueue = new ArrayList<>();
-            for (String packageName : params.kvPackages) {
-              kvQueue.add(new BackupRequest(packageName));
-            }
-            backupManagerService.mBackupRunning = true;
-            backupManagerService.mWakelock.acquire();
 
-            PerformBackupTask pbt = new PerformBackupTask(
-                backupManagerService,
-                params.transport, params.dirName,
-                    kvQueue, null, params.observer, params.monitor, params.fullPackages, true,
-                    params.nonIncrementalBackup);
-            Message pbtMessage = obtainMessage(
-                RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, pbt);
-            sendMessage(pbtMessage);
-            break;
-          }
+            case RefactoredBackupManagerService.MSG_REQUEST_BACKUP: {
+                BackupParams params = (BackupParams) msg.obj;
+                if (RefactoredBackupManagerService.MORE_DEBUG) {
+                    Slog.d(RefactoredBackupManagerService.TAG,
+                            "MSG_REQUEST_BACKUP observer=" + params.observer);
+                }
+                ArrayList<BackupRequest> kvQueue = new ArrayList<>();
+                for (String packageName : params.kvPackages) {
+                    kvQueue.add(new BackupRequest(packageName));
+                }
+                backupManagerService.mBackupRunning = true;
+                backupManagerService.mWakelock.acquire();
 
-          case RefactoredBackupManagerService.MSG_SCHEDULE_BACKUP_PACKAGE: {
-            String pkgName = (String) msg.obj;
-            if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Slog.d(RefactoredBackupManagerService.TAG, "MSG_SCHEDULE_BACKUP_PACKAGE " + pkgName);
+                PerformBackupTask pbt = new PerformBackupTask(
+                        backupManagerService,
+                        params.transport, params.dirName,
+                        kvQueue, null, params.observer, params.monitor, params.fullPackages, true,
+                        params.nonIncrementalBackup);
+                Message pbtMessage = obtainMessage(
+                        RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, pbt);
+                sendMessage(pbtMessage);
+                break;
             }
-            backupManagerService.dataChangedImpl(pkgName);
-            break;
-          }
+
+            case RefactoredBackupManagerService.MSG_SCHEDULE_BACKUP_PACKAGE: {
+                String pkgName = (String) msg.obj;
+                if (RefactoredBackupManagerService.MORE_DEBUG) {
+                    Slog.d(RefactoredBackupManagerService.TAG,
+                            "MSG_SCHEDULE_BACKUP_PACKAGE " + pkgName);
+                }
+                backupManagerService.dataChangedImpl(pkgName);
+                break;
+            }
         }
     }
 }
diff --git a/services/backup/java/com/android/server/backup/internal/ClearDataObserver.java b/services/backup/java/com/android/server/backup/internal/ClearDataObserver.java
index e24dab7..8aff905 100644
--- a/services/backup/java/com/android/server/backup/internal/ClearDataObserver.java
+++ b/services/backup/java/com/android/server/backup/internal/ClearDataObserver.java
@@ -17,6 +17,7 @@
 package com.android.server.backup.internal;
 
 import android.content.pm.IPackageDataObserver;
+
 import com.android.server.backup.RefactoredBackupManagerService;
 
 public class ClearDataObserver extends IPackageDataObserver.Stub {
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index f3576e6..b9ce90b 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -39,6 +39,7 @@
 import android.system.Os;
 import android.util.EventLog;
 import android.util.Slog;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.AppWidgetBackupBridge;
@@ -49,6 +50,7 @@
 import com.android.server.backup.RefactoredBackupManagerService;
 import com.android.server.backup.RefactoredBackupManagerService.BackupState;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
+
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -125,10 +127,10 @@
     private volatile boolean mCancelAll;
 
     public PerformBackupTask(RefactoredBackupManagerService backupManagerService,
-        IBackupTransport transport, String dirName,
-        ArrayList<BackupRequest> queue, File journal, IBackupObserver observer,
-        IBackupManagerMonitor monitor, List<String> pendingFullBackups,
-        boolean userInitiated, boolean nonIncremental) {
+            IBackupTransport transport, String dirName,
+            ArrayList<BackupRequest> queue, File journal, IBackupObserver observer,
+            IBackupManagerMonitor monitor, List<String> pendingFullBackups,
+            boolean userInitiated, boolean nonIncremental) {
         this.backupManagerService = backupManagerService;
         mTransport = transport;
         mOriginalQueue = queue;
@@ -160,7 +162,9 @@
                 String[] fullBackups =
                         mPendingFullBackups.toArray(new String[mPendingFullBackups.size()]);
                 mFullBackupTask =
-                        new PerformFullTransportBackupTask(backupManagerService, /*fullBackupRestoreObserver*/ null,
+                        new PerformFullTransportBackupTask(backupManagerService,
+                                /*fullBackupRestoreObserver*/
+                                null,
                                 fullBackups, /*updateSchedule*/ false, /*runningJob*/ null,
                                 latch,
                                 mObserver, mMonitor, mUserInitiated);
@@ -177,7 +181,7 @@
     private void registerTask() {
         synchronized (backupManagerService.mCurrentOpLock) {
             backupManagerService.mCurrentOperations.put(mCurrentOpToken, new Operation(
-                RefactoredBackupManagerService.OP_PENDING, this,
+                    RefactoredBackupManagerService.OP_PENDING, this,
                     RefactoredBackupManagerService.OP_TYPE_BACKUP));
         }
     }
@@ -205,8 +209,9 @@
                     break;
 
                 case FINAL:
-                    if (!mFinished) finalizeBackup();
-                    else {
+                    if (!mFinished) {
+                        finalizeBackup();
+                    } else {
                         Slog.e(TAG, "Duplicate finish");
                     }
                     mFinished = true;
@@ -256,7 +261,8 @@
         // we performed a backup.  Drop it from the working queue now that
         // we're committed to evaluating it for backup regardless.
         for (int i = 0; i < mQueue.size(); i++) {
-            if (RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL.equals(mQueue.get(i).packageName)) {
+            if (RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL.equals(
+                    mQueue.get(i).packageName)) {
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
                     Slog.i(TAG, "Metadata in queue; eliding");
                 }
@@ -266,7 +272,10 @@
             }
         }
 
-        if (RefactoredBackupManagerService.DEBUG) Slog.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
+        if (RefactoredBackupManagerService.DEBUG) {
+            Slog.v(TAG,
+                    "Beginning backup of " + mQueue.size() + " targets");
+        }
 
         File pmState = new File(mStateDir, RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL);
         try {
@@ -302,7 +311,7 @@
                     PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
                             backupManagerService.mPackageManager);
                     mStatus = invokeAgentForBackup(
-                        RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL,
+                            RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL,
                             IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport);
                     backupManagerService.addBackupTrace("PMBA invoke: " + mStatus);
 
@@ -310,7 +319,7 @@
                     // backup callback and returned.  Blow away the lingering (spurious)
                     // pending timeout message for it.
                     backupManagerService.mBackupHandler.removeMessages(
-                        RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT);
+                            RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT);
                 }
             }
 
@@ -334,7 +343,8 @@
                 // restage everything and try again later.
                 backupManagerService.resetBackupState(mStateDir);  // Just to make sure.
                 // In case of any other error, it's backup transport error.
-                RefactoredBackupManagerService.sendBackupFinished(mObserver, BackupManager.ERROR_TRANSPORT_ABORTED);
+                RefactoredBackupManagerService.sendBackupFinished(mObserver,
+                        BackupManager.ERROR_TRANSPORT_ABORTED);
                 executeNextState(BackupState.FINAL);
             }
         }
@@ -367,9 +377,11 @@
         // to sanity-check here.  This also gives us the classname of the
         // package's backup agent.
         try {
-            mCurrentPackage = backupManagerService.mPackageManager.getPackageInfo(request.packageName,
+            mCurrentPackage = backupManagerService.mPackageManager.getPackageInfo(
+                    request.packageName,
                     PackageManager.GET_SIGNATURES);
-            if (!RefactoredBackupManagerService.appIsEligibleForBackup(mCurrentPackage.applicationInfo)) {
+            if (!RefactoredBackupManagerService.appIsEligibleForBackup(
+                    mCurrentPackage.applicationInfo)) {
                 // The manifest has changed but we had a stale backup request pending.
                 // This won't happen again because the app won't be requesting further
                 // backups.
@@ -378,7 +390,8 @@
                 backupManagerService.addBackupTrace("skipping - not eligible, completion is noop");
                 // Shouldn't happen in case of requested backup, as pre-check was done in
                 // #requestBackup(), except to app update done concurrently
-                RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
+                RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver,
+                        mCurrentPackage.packageName,
                         BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                 executeNextState(BackupState.RUNNING_QUEUE);
                 return;
@@ -390,10 +403,12 @@
                 // Don't proceed with a key/value backup for it in this case.
                 Slog.i(TAG, "Package " + request.packageName
                         + " requests full-data rather than key/value; skipping");
-                backupManagerService.addBackupTrace("skipping - fullBackupOnly, completion is noop");
+                backupManagerService.addBackupTrace(
+                        "skipping - fullBackupOnly, completion is noop");
                 // Shouldn't happen in case of requested backup, as pre-check was done in
                 // #requestBackup()
-                RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
+                RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver,
+                        mCurrentPackage.packageName,
                         BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                 executeNextState(BackupState.RUNNING_QUEUE);
                 return;
@@ -404,7 +419,8 @@
                 // and not yet launched out of that state, so just as it won't
                 // receive broadcasts, we won't run it for backup.
                 backupManagerService.addBackupTrace("skipping - stopped");
-                RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
+                RefactoredBackupManagerService.sendBackupOnPackageResult(mObserver,
+                        mCurrentPackage.packageName,
                         BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                 executeNextState(BackupState.RUNNING_QUEUE);
                 return;
@@ -412,7 +428,8 @@
 
             IBackupAgent agent = null;
             try {
-                backupManagerService.mWakelock.setWorkSource(new WorkSource(mCurrentPackage.applicationInfo.uid));
+                backupManagerService.mWakelock.setWorkSource(
+                        new WorkSource(mCurrentPackage.applicationInfo.uid));
                 agent = backupManagerService.bindToAgentSynchronous(mCurrentPackage.applicationInfo,
                         ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
                 backupManagerService.addBackupTrace("agent bound; a? = " + (agent != null));
@@ -430,7 +447,7 @@
                 // Try for the next one.
                 Slog.d(TAG, "error in bind/backup", ex);
                 mStatus = BackupTransport.AGENT_ERROR;
-                        backupManagerService.addBackupTrace("agent SE");
+                backupManagerService.addBackupTrace("agent SE");
             }
         } catch (NameNotFoundException e) {
             Slog.d(TAG, "Package does not exist; skipping");
@@ -448,21 +465,24 @@
                 // An agent-level failure means we reenqueue this one agent for
                 // a later retry, but otherwise proceed normally.
                 if (mStatus == BackupTransport.AGENT_ERROR) {
-                    if (RefactoredBackupManagerService.MORE_DEBUG) Slog.i(TAG, "Agent failure for " + request.packageName
-                            + " - restaging");
+                    if (RefactoredBackupManagerService.MORE_DEBUG) {
+                        Slog.i(TAG,
+                                "Agent failure for " + request.packageName
+                                        + " - restaging");
+                    }
                     backupManagerService.dataChangedImpl(request.packageName);
                     mStatus = BackupTransport.TRANSPORT_OK;
                     if (mQueue.isEmpty()) nextState = BackupState.FINAL;
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
-                            BackupManager.ERROR_AGENT_FAILURE);
+                            .sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
+                                    BackupManager.ERROR_AGENT_FAILURE);
                 } else if (mStatus == BackupTransport.AGENT_UNKNOWN) {
                     // Failed lookup of the app, so we couldn't bring up an agent, but
                     // we're otherwise fine.  Just drop it and go on to the next as usual.
                     mStatus = BackupTransport.TRANSPORT_OK;
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
-                            BackupManager.ERROR_PACKAGE_NOT_FOUND);
+                            .sendBackupOnPackageResult(mObserver, mCurrentPackage.packageName,
+                                    BackupManager.ERROR_PACKAGE_NOT_FOUND);
                 } else {
                     // Transport-level failure means we reenqueue everything
                     revertAndEndBackup();
@@ -497,7 +517,8 @@
         // If everything actually went through and this is the first time we've
         // done a backup, we can now record what the current backup dataset token
         // is.
-        if ((backupManagerService.mCurrentToken == 0) && (mStatus == BackupTransport.TRANSPORT_OK)) {
+        if ((backupManagerService.mCurrentToken == 0) && (mStatus
+                == BackupTransport.TRANSPORT_OK)) {
             backupManagerService.addBackupTrace("success; recording token");
             try {
                 backupManagerService.mCurrentToken = mTransport.getCurrentRestoreSet();
@@ -517,10 +538,14 @@
             backupManagerService.mBackupRunning = false;
             if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
                 // Make sure we back up everything and perform the one-time init
-                if (RefactoredBackupManagerService.MORE_DEBUG) Slog.d(TAG, "Server requires init; rerunning");
+                if (RefactoredBackupManagerService.MORE_DEBUG) {
+                    Slog.d(TAG,
+                            "Server requires init; rerunning");
+                }
                 backupManagerService.addBackupTrace("init required; rerunning");
                 try {
-                    final String name = backupManagerService.mTransportManager.getTransportName(mTransport);
+                    final String name = backupManagerService.mTransportManager.getTransportName(
+                            mTransport);
                     if (name != null) {
                         backupManagerService.mPendingInits.add(name);
                     } else {
@@ -552,19 +577,23 @@
             if (mFullBackupTask != null) {
                 mFullBackupTask.unregisterTask();
             }
-            RefactoredBackupManagerService.sendBackupFinished(mObserver, BackupManager.ERROR_BACKUP_CANCELLED);
+            RefactoredBackupManagerService.sendBackupFinished(mObserver,
+                    BackupManager.ERROR_BACKUP_CANCELLED);
         } else {
             mFullBackupTask.unregisterTask();
             switch (mStatus) {
                 case BackupTransport.TRANSPORT_OK:
-                    RefactoredBackupManagerService.sendBackupFinished(mObserver, BackupManager.SUCCESS);
+                    RefactoredBackupManagerService.sendBackupFinished(mObserver,
+                            BackupManager.SUCCESS);
                     break;
                 case BackupTransport.TRANSPORT_NOT_INITIALIZED:
-                    RefactoredBackupManagerService.sendBackupFinished(mObserver, BackupManager.ERROR_TRANSPORT_ABORTED);
+                    RefactoredBackupManagerService.sendBackupFinished(mObserver,
+                            BackupManager.ERROR_TRANSPORT_ABORTED);
                     break;
                 case BackupTransport.TRANSPORT_ERROR:
                 default:
-                    RefactoredBackupManagerService.sendBackupFinished(mObserver, BackupManager.ERROR_TRANSPORT_ABORTED);
+                    RefactoredBackupManagerService.sendBackupFinished(mObserver,
+                            BackupManager.ERROR_TRANSPORT_ABORTED);
                     break;
             }
         }
@@ -575,7 +604,8 @@
 
     // Remove the PM metadata state. This will generate an init on the next pass.
     void clearMetadata() {
-        final File pmState = new File(mStateDir, RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL);
+        final File pmState = new File(mStateDir,
+                RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL);
         if (pmState.exists()) pmState.delete();
     }
 
@@ -583,7 +613,10 @@
     // handler in case it doesn't get back to us.
     int invokeAgentForBackup(String packageName, IBackupAgent agent,
             IBackupTransport transport) {
-        if (RefactoredBackupManagerService.DEBUG) Slog.d(TAG, "invokeAgentForBackup on " + packageName);
+        if (RefactoredBackupManagerService.DEBUG) {
+            Slog.d(TAG,
+                    "invokeAgentForBackup on " + packageName);
+        }
         backupManagerService.addBackupTrace("invoking " + packageName);
 
         File blankStateName = new File(mStateDir, "blank_state");
@@ -615,12 +648,12 @@
             mSavedState = ParcelFileDescriptor.open(
                     mNonIncremental ? blankStateName : mSavedStateName,
                     ParcelFileDescriptor.MODE_READ_ONLY |
-                    ParcelFileDescriptor.MODE_CREATE);  // Make an empty file if necessary
+                            ParcelFileDescriptor.MODE_CREATE);  // Make an empty file if necessary
 
             mBackupData = ParcelFileDescriptor.open(mBackupDataName,
                     ParcelFileDescriptor.MODE_READ_WRITE |
-                    ParcelFileDescriptor.MODE_CREATE |
-                    ParcelFileDescriptor.MODE_TRUNCATE);
+                            ParcelFileDescriptor.MODE_CREATE |
+                            ParcelFileDescriptor.MODE_TRUNCATE);
 
             if (!SELinux.restorecon(mBackupDataName)) {
                 Slog.e(TAG, "SELinux restorecon failed on " + mBackupDataName);
@@ -628,8 +661,8 @@
 
             mNewState = ParcelFileDescriptor.open(mNewStateName,
                     ParcelFileDescriptor.MODE_READ_WRITE |
-                    ParcelFileDescriptor.MODE_CREATE |
-                    ParcelFileDescriptor.MODE_TRUNCATE);
+                            ParcelFileDescriptor.MODE_CREATE |
+                            ParcelFileDescriptor.MODE_TRUNCATE);
 
             final long quota = mTransport.getBackupQuota(packageName, false /* isFullBackup */);
             callingAgent = true;
@@ -637,8 +670,9 @@
             // Initiate the target's backup pass
             backupManagerService.addBackupTrace("setting timeout");
             backupManagerService
-                .prepareOperationTimeout(mEphemeralOpToken, RefactoredBackupManagerService.TIMEOUT_BACKUP_INTERVAL, this,
-                    RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
+                    .prepareOperationTimeout(mEphemeralOpToken,
+                            RefactoredBackupManagerService.TIMEOUT_BACKUP_INTERVAL, this,
+                            RefactoredBackupManagerService.OP_TYPE_BACKUP_WAIT);
             backupManagerService.addBackupTrace("calling agent doBackup()");
 
             agent.doBackup(mSavedState, mBackupData, mNewState, quota, mEphemeralOpToken,
@@ -722,8 +756,8 @@
             if (priorStateExists) {
                 final String priorChecksum;
                 try (
-                    FileInputStream fin = new FileInputStream(widgetFile);
-                    DataInputStream in = new DataInputStream(fin)
+                        FileInputStream fin = new FileInputStream(widgetFile);
+                        DataInputStream in = new DataInputStream(fin)
                 ) {
                     priorChecksum = in.readUTF();
                 }
@@ -737,13 +771,14 @@
         BackupDataOutput out = new BackupDataOutput(fd);
         if (widgetState != null) {
             try (
-                FileOutputStream fout = new FileOutputStream(widgetFile);
-                DataOutputStream stateOut = new DataOutputStream(fout)
+                    FileOutputStream fout = new FileOutputStream(widgetFile);
+                    DataOutputStream stateOut = new DataOutputStream(fout)
             ) {
                 stateOut.writeUTF(newChecksum);
             }
 
-            out.writeEntityHeader(RefactoredBackupManagerService.KEY_WIDGET_STATE, widgetState.length);
+            out.writeEntityHeader(RefactoredBackupManagerService.KEY_WIDGET_STATE,
+                    widgetState.length);
             out.writeEntityData(widgetState, widgetState.length);
         } else {
             // Widget state for this app has been removed; commit a deletion
@@ -796,7 +831,7 @@
                                 // Not okay: crash them and bail.
                                 failAgent(mAgentBinder, "Illegal backup key: " + key);
                                 backupManagerService
-                                    .addBackupTrace("illegal key " + key + " from " + pkgName);
+                                        .addBackupTrace("illegal key " + key + " from " + pkgName);
                                 EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
                                         "bad key");
                                 mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
@@ -808,10 +843,11 @@
                                                 BackupManagerMonitor.EXTRA_LOG_ILLEGAL_KEY,
                                                 key));
                                 backupManagerService.mBackupHandler.removeMessages(
-                                    RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT);
+                                        RefactoredBackupManagerService
+                                                .MSG_BACKUP_OPERATION_TIMEOUT);
                                 RefactoredBackupManagerService
-                                    .sendBackupOnPackageResult(mObserver, pkgName,
-                                        BackupManager.ERROR_AGENT_FAILURE);
+                                        .sendBackupOnPackageResult(mObserver, pkgName,
+                                                BackupManager.ERROR_AGENT_FAILURE);
                                 errorCleanup();
                                 // agentErrorCleanup() implicitly executes next state properly
                                 return;
@@ -841,10 +877,13 @@
             }
 
             // Spin the data off to the transport and proceed with the next stage.
-            if (RefactoredBackupManagerService.MORE_DEBUG) Slog.v(TAG, "operationComplete(): sending data to transport for "
-                    + pkgName);
+            if (RefactoredBackupManagerService.MORE_DEBUG) {
+                Slog.v(TAG,
+                        "operationComplete(): sending data to transport for "
+                                + pkgName);
+            }
             backupManagerService.mBackupHandler.removeMessages(
-                RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT);
+                    RefactoredBackupManagerService.MSG_BACKUP_OPERATION_TIMEOUT);
             clearAgentState();
             backupManagerService.addBackupTrace("operation complete");
 
@@ -876,8 +915,10 @@
                         backupManagerService.addBackupTrace("transport rejected package");
                     }
                 } else {
-                    if (RefactoredBackupManagerService.MORE_DEBUG) Slog.i(TAG,
-                            "no backup data written; not calling transport");
+                    if (RefactoredBackupManagerService.MORE_DEBUG) {
+                        Slog.i(TAG,
+                                "no backup data written; not calling transport");
+                    }
                     backupManagerService.addBackupTrace("no data to send");
                     mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
                             BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND,
@@ -893,7 +934,7 @@
                     mBackupDataName.delete();
                     mNewStateName.renameTo(mSavedStateName);
                     RefactoredBackupManagerService
-                        .sendBackupOnPackageResult(mObserver, pkgName, BackupManager.SUCCESS);
+                            .sendBackupOnPackageResult(mObserver, pkgName, BackupManager.SUCCESS);
                     EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size);
                     backupManagerService.logBackupComplete(pkgName);
                 } else if (mStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
@@ -978,11 +1019,13 @@
                     : "no_package_yet";
             Slog.i(TAG, "Cancel backing up " + logPackageName);
             EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, logPackageName);
-            backupManagerService.addBackupTrace("cancel of " + logPackageName + ", cancelAll=" + cancelAll);
+            backupManagerService.addBackupTrace(
+                    "cancel of " + logPackageName + ", cancelAll=" + cancelAll);
             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
                     BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL,
                     mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT,
-                    backupManagerService.putMonitoringExtra(null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL,
+                    backupManagerService.putMonitoringExtra(null,
+                            BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL,
                             mCancelAll));
             errorCleanup();
             if (!cancelAll) {
@@ -1000,7 +1043,10 @@
     }
 
     void revertAndEndBackup() {
-        if (RefactoredBackupManagerService.MORE_DEBUG) Slog.i(TAG, "Reverting backup queue - restaging everything");
+        if (RefactoredBackupManagerService.MORE_DEBUG) {
+            Slog.i(TAG,
+                    "Reverting backup queue - restaging everything");
+        }
         backupManagerService.addBackupTrace("transport error; reverting");
 
         // We want to reset the backup schedule based on whatever the transport suggests
@@ -1028,9 +1074,18 @@
 
     // Cleanup common to both success and failure cases
     void clearAgentState() {
-        try { if (mSavedState != null) mSavedState.close(); } catch (IOException e) {}
-        try { if (mBackupData != null) mBackupData.close(); } catch (IOException e) {}
-        try { if (mNewState != null) mNewState.close(); } catch (IOException e) {}
+        try {
+            if (mSavedState != null) mSavedState.close();
+        } catch (IOException e) {
+        }
+        try {
+            if (mBackupData != null) mBackupData.close();
+        } catch (IOException e) {
+        }
+        try {
+            if (mNewState != null) mNewState.close();
+        } catch (IOException e) {
+        }
         synchronized (backupManagerService.mCurrentOpLock) {
             // Current-operation callback handling requires the validity of these various
             // bits of internal state as an invariant of the operation still being live.
@@ -1043,18 +1098,21 @@
         if (mCurrentPackage.applicationInfo != null) {
             backupManagerService.addBackupTrace("unbinding " + mCurrentPackage.packageName);
             try {  // unbind even on timeout, just in case
-                backupManagerService.mActivityManager.unbindBackupAgent(mCurrentPackage.applicationInfo);
+                backupManagerService.mActivityManager.unbindBackupAgent(
+                        mCurrentPackage.applicationInfo);
             } catch (RemoteException e) { /* can't happen; activity manager is local */ }
         }
     }
 
     void executeNextState(BackupState nextState) {
-        if (RefactoredBackupManagerService.MORE_DEBUG) Slog.i(TAG, " => executing next step on "
-                + this + " nextState=" + nextState);
+        if (RefactoredBackupManagerService.MORE_DEBUG) {
+            Slog.i(TAG, " => executing next step on "
+                    + this + " nextState=" + nextState);
+        }
         backupManagerService.addBackupTrace("executeNextState => " + nextState);
         mCurrentState = nextState;
         Message msg = backupManagerService.mBackupHandler.obtainMessage(
-            RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
+                RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
         backupManagerService.mBackupHandler.sendMessage(msg);
     }
 }
diff --git a/services/backup/java/com/android/server/backup/internal/PerformClearTask.java b/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
index 8575227..3c14819 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
@@ -18,8 +18,10 @@
 
 import android.content.pm.PackageInfo;
 import android.util.Slog;
+
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.RefactoredBackupManagerService;
+
 import java.io.File;
 
 public class PerformClearTask implements Runnable {
@@ -29,7 +31,7 @@
     PackageInfo mPackage;
 
     PerformClearTask(RefactoredBackupManagerService backupManagerService,
-        IBackupTransport transport, PackageInfo packageInfo) {
+            IBackupTransport transport, PackageInfo packageInfo) {
         this.backupManagerService = backupManagerService;
         mTransport = transport;
         mPackage = packageInfo;
@@ -38,7 +40,8 @@
     public void run() {
         try {
             // Clear the on-device backup state to ensure a full backup next time
-            File stateDir = new File(backupManagerService.mBaseStateDir, mTransport.transportDirName());
+            File stateDir = new File(backupManagerService.mBaseStateDir,
+                    mTransport.transportDirName());
             File stateFile = new File(stateDir, mPackage.packageName);
             stateFile.delete();
 
@@ -47,14 +50,15 @@
             mTransport.clearBackupData(mPackage);
         } catch (Exception e) {
             Slog.e(RefactoredBackupManagerService.TAG,
-                "Transport threw clearing data for " + mPackage + ": " + e.getMessage());
+                    "Transport threw clearing data for " + mPackage + ": " + e.getMessage());
         } finally {
             try {
                 // TODO - need to handle failures
                 mTransport.finishBackup();
             } catch (Exception e) {
                 // Nothing we can do here, alas
-                Slog.e(RefactoredBackupManagerService.TAG, "Unable to mark clear operation finished: " + e.getMessage());
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Unable to mark clear operation finished: " + e.getMessage());
             }
 
             // Last but not least, release the cpu
diff --git a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
index 003794f..43f7f43 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
@@ -21,9 +21,11 @@
 import android.os.SystemClock;
 import android.util.EventLog;
 import android.util.Slog;
+
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
 import com.android.server.backup.RefactoredBackupManagerService;
+
 import java.io.File;
 import java.util.HashSet;
 
@@ -33,7 +35,7 @@
     HashSet<String> mQueue;
 
     PerformInitializeTask(RefactoredBackupManagerService backupManagerService,
-        HashSet<String> transportNames) {
+            HashSet<String> transportNames) {
         this.backupManagerService = backupManagerService;
         mQueue = transportNames;
     }
@@ -42,14 +44,16 @@
         try {
             for (String transportName : mQueue) {
                 IBackupTransport transport =
-                    backupManagerService.mTransportManager.getTransportBinder(transportName);
+                        backupManagerService.mTransportManager.getTransportBinder(transportName);
                 if (transport == null) {
                     Slog.e(
-                        RefactoredBackupManagerService.TAG, "Requested init for " + transportName + " but not found");
+                            RefactoredBackupManagerService.TAG,
+                            "Requested init for " + transportName + " but not found");
                     continue;
                 }
 
-                Slog.i(RefactoredBackupManagerService.TAG, "Initializing (wiping) backup transport storage: " + transportName);
+                Slog.i(RefactoredBackupManagerService.TAG,
+                        "Initializing (wiping) backup transport storage: " + transportName);
                 EventLog.writeEvent(EventLogTags.BACKUP_START, transport.transportDirName());
                 long startRealtime = SystemClock.elapsedRealtime();
                 int status = transport.initializeDevice();
@@ -64,7 +68,8 @@
                     int millis = (int) (SystemClock.elapsedRealtime() - startRealtime);
                     EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
                     backupManagerService
-                        .resetBackupState(new File(backupManagerService.mBaseStateDir, transport.transportDirName()));
+                            .resetBackupState(new File(backupManagerService.mBaseStateDir,
+                                    transport.transportDirName()));
                     EventLog.writeEvent(EventLogTags.BACKUP_SUCCESS, 0, millis);
                     synchronized (backupManagerService.mQueueLock) {
                         backupManagerService.recordInitPendingLocked(false, transportName);
@@ -72,16 +77,19 @@
                 } else {
                     // If this didn't work, requeue this one and try again
                     // after a suitable interval
-                    Slog.e(RefactoredBackupManagerService.TAG, "Transport error in initializeDevice()");
+                    Slog.e(RefactoredBackupManagerService.TAG,
+                            "Transport error in initializeDevice()");
                     EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
                     synchronized (backupManagerService.mQueueLock) {
                         backupManagerService.recordInitPendingLocked(true, transportName);
                     }
                     // do this via another alarm to make sure of the wakelock states
                     long delay = transport.requestBackupTime();
-                    Slog.w(RefactoredBackupManagerService.TAG, "Init failed on " + transportName + " resched in " + delay);
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "Init failed on " + transportName + " resched in " + delay);
                     backupManagerService.mAlarmManager.set(AlarmManager.RTC_WAKEUP,
-                        System.currentTimeMillis() + delay, backupManagerService.mRunInitIntent);
+                            System.currentTimeMillis() + delay,
+                            backupManagerService.mRunInitIntent);
                 }
             }
         } catch (Exception e) {
diff --git a/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java b/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
index 54545c1b9..743f382 100644
--- a/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
+++ b/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
@@ -19,6 +19,7 @@
 import android.database.ContentObserver;
 import android.os.Handler;
 import android.util.Slog;
+
 import com.android.server.backup.KeyValueBackupJob;
 import com.android.server.backup.RefactoredBackupManagerService;
 
@@ -27,7 +28,7 @@
     private RefactoredBackupManagerService backupManagerService;
 
     public ProvisionedObserver(
-        RefactoredBackupManagerService backupManagerService, Handler handler) {
+            RefactoredBackupManagerService backupManagerService, Handler handler) {
         super(handler);
         this.backupManagerService = backupManagerService;
     }
@@ -39,14 +40,16 @@
         backupManagerService.mProvisioned = wasProvisioned || isProvisioned;
         if (RefactoredBackupManagerService.MORE_DEBUG) {
             Slog.d(RefactoredBackupManagerService.TAG, "Provisioning change: was=" + wasProvisioned
-                + " is=" + isProvisioned + " now=" + backupManagerService.mProvisioned);
+                    + " is=" + isProvisioned + " now=" + backupManagerService.mProvisioned);
         }
 
         synchronized (backupManagerService.mQueueLock) {
-            if (backupManagerService.mProvisioned && !wasProvisioned && backupManagerService.mEnabled) {
+            if (backupManagerService.mProvisioned && !wasProvisioned
+                    && backupManagerService.mEnabled) {
                 // we're now good to go, so start the backup alarms
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
-                  Slog.d(RefactoredBackupManagerService.TAG, "Now provisioned, so starting backups");
+                    Slog.d(RefactoredBackupManagerService.TAG,
+                            "Now provisioned, so starting backups");
                 }
                 KeyValueBackupJob.schedule(backupManagerService.mContext);
                 backupManagerService.scheduleNextFullBackupJob(0);
diff --git a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
index 0347c36..66d3736 100644
--- a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.os.Message;
 import android.util.Slog;
+
 import com.android.server.backup.RefactoredBackupManagerService;
 
 public class RunBackupReceiver extends BroadcastReceiver {
@@ -39,11 +40,12 @@
                     // If there are pending init operations, we process those
                     // and then settle into the usual periodic backup schedule.
                     if (RefactoredBackupManagerService.MORE_DEBUG) {
-                      Slog.v(RefactoredBackupManagerService.TAG, "Init pending at scheduled backup");
+                        Slog.v(RefactoredBackupManagerService.TAG,
+                                "Init pending at scheduled backup");
                     }
                     try {
                         backupManagerService.mAlarmManager.cancel(
-                            backupManagerService.mRunInitIntent);
+                                backupManagerService.mRunInitIntent);
                         backupManagerService.mRunInitIntent.send();
                     } catch (PendingIntent.CanceledException ce) {
                         Slog.e(RefactoredBackupManagerService.TAG, "Run init intent cancelled");
@@ -55,7 +57,7 @@
                     if (backupManagerService.mEnabled && backupManagerService.mProvisioned) {
                         if (!backupManagerService.mBackupRunning) {
                             if (RefactoredBackupManagerService.DEBUG) {
-                              Slog.v(RefactoredBackupManagerService.TAG, "Running a backup pass");
+                                Slog.v(RefactoredBackupManagerService.TAG, "Running a backup pass");
                             }
 
                             // Acquire the wakelock and pass it to the backup thread.  it will
@@ -64,14 +66,17 @@
                             backupManagerService.mWakelock.acquire();
 
                             Message msg = backupManagerService.mBackupHandler.obtainMessage(
-                                RefactoredBackupManagerService.MSG_RUN_BACKUP);
+                                    RefactoredBackupManagerService.MSG_RUN_BACKUP);
                             backupManagerService.mBackupHandler.sendMessage(msg);
                         } else {
-                            Slog.i(RefactoredBackupManagerService.TAG, "Backup time but one already running");
+                            Slog.i(RefactoredBackupManagerService.TAG,
+                                    "Backup time but one already running");
                         }
                     } else {
                         Slog.w(
-                            RefactoredBackupManagerService.TAG, "Backup pass but e=" + backupManagerService.mEnabled + " p=" + backupManagerService.mProvisioned);
+                                RefactoredBackupManagerService.TAG,
+                                "Backup pass but e=" + backupManagerService.mEnabled + " p="
+                                        + backupManagerService.mProvisioned);
                     }
                 }
             }
diff --git a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
index 1f1c714..7a487cc 100644
--- a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.os.Message;
 import android.util.Slog;
+
 import com.android.server.backup.RefactoredBackupManagerService;
 
 public class RunInitializeReceiver extends BroadcastReceiver {
@@ -35,7 +36,7 @@
         if (RefactoredBackupManagerService.RUN_INITIALIZE_ACTION.equals(intent.getAction())) {
             synchronized (backupManagerService.mQueueLock) {
                 if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.v(RefactoredBackupManagerService.TAG, "Running a device init");
+                    Slog.v(RefactoredBackupManagerService.TAG, "Running a device init");
                 }
 
                 // Acquire the wakelock and pass it to the init thread.  it will
@@ -43,7 +44,7 @@
                 backupManagerService.mWakelock.acquire();
 
                 Message msg = backupManagerService.mBackupHandler.obtainMessage(
-                    RefactoredBackupManagerService.MSG_RUN_INITIALIZE);
+                        RefactoredBackupManagerService.MSG_RUN_INITIALIZE);
                 backupManagerService.mBackupHandler.sendMessage(msg);
             }
         }
diff --git a/services/backup/java/com/android/server/backup/params/AdbBackupParams.java b/services/backup/java/com/android/server/backup/params/AdbBackupParams.java
index 86bc5fc..5c1ba24 100644
--- a/services/backup/java/com/android/server/backup/params/AdbBackupParams.java
+++ b/services/backup/java/com/android/server/backup/params/AdbBackupParams.java
@@ -31,8 +31,8 @@
     public String[] packages;
 
     public AdbBackupParams(ParcelFileDescriptor output, boolean saveApks, boolean saveObbs,
-        boolean saveShared, boolean alsoWidgets, boolean doAllApps, boolean doSystem,
-        boolean compress, boolean doKeyValue, String[] pkgList) {
+            boolean saveShared, boolean alsoWidgets, boolean doAllApps, boolean doSystem,
+            boolean compress, boolean doKeyValue, String[] pkgList) {
         fd = output;
         includeApks = saveApks;
         includeObbs = saveObbs;
diff --git a/services/backup/java/com/android/server/backup/params/AdbParams.java b/services/backup/java/com/android/server/backup/params/AdbParams.java
index f189aec..392f40d 100644
--- a/services/backup/java/com/android/server/backup/params/AdbParams.java
+++ b/services/backup/java/com/android/server/backup/params/AdbParams.java
@@ -18,6 +18,7 @@
 
 import android.app.backup.IFullBackupRestoreObserver;
 import android.os.ParcelFileDescriptor;
+
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
diff --git a/services/backup/java/com/android/server/backup/params/BackupParams.java b/services/backup/java/com/android/server/backup/params/BackupParams.java
index 81735069..4fd7ddb 100644
--- a/services/backup/java/com/android/server/backup/params/BackupParams.java
+++ b/services/backup/java/com/android/server/backup/params/BackupParams.java
@@ -18,7 +18,9 @@
 
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
+
 import com.android.internal.backup.IBackupTransport;
+
 import java.util.ArrayList;
 
 public class BackupParams {
@@ -33,8 +35,8 @@
     public boolean nonIncrementalBackup;
 
     public BackupParams(IBackupTransport transport, String dirName, ArrayList<String> kvPackages,
-        ArrayList<String> fullPackages, IBackupObserver observer,
-        IBackupManagerMonitor monitor, boolean userInitiated, boolean nonIncrementalBackup) {
+            ArrayList<String> fullPackages, IBackupObserver observer,
+            IBackupManagerMonitor monitor, boolean userInitiated, boolean nonIncrementalBackup) {
         this.transport = transport;
         this.dirName = dirName;
         this.kvPackages = kvPackages;
diff --git a/services/backup/java/com/android/server/backup/params/ClearParams.java b/services/backup/java/com/android/server/backup/params/ClearParams.java
index a62350c..d744efc 100644
--- a/services/backup/java/com/android/server/backup/params/ClearParams.java
+++ b/services/backup/java/com/android/server/backup/params/ClearParams.java
@@ -17,6 +17,7 @@
 package com.android.server.backup.params;
 
 import android.content.pm.PackageInfo;
+
 import com.android.internal.backup.IBackupTransport;
 
 public class ClearParams {
diff --git a/services/backup/java/com/android/server/backup/params/RestoreGetSetsParams.java b/services/backup/java/com/android/server/backup/params/RestoreGetSetsParams.java
index 5495d5b..bff476b 100644
--- a/services/backup/java/com/android/server/backup/params/RestoreGetSetsParams.java
+++ b/services/backup/java/com/android/server/backup/params/RestoreGetSetsParams.java
@@ -18,6 +18,7 @@
 
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IRestoreObserver;
+
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.restore.ActiveRestoreSession;
 
@@ -29,7 +30,7 @@
     public IBackupManagerMonitor monitor;
 
     public RestoreGetSetsParams(IBackupTransport _transport, ActiveRestoreSession _session,
-        IRestoreObserver _observer, IBackupManagerMonitor _monitor) {
+            IRestoreObserver _observer, IBackupManagerMonitor _monitor) {
         transport = _transport;
         session = _session;
         observer = _observer;
diff --git a/services/backup/java/com/android/server/backup/params/RestoreParams.java b/services/backup/java/com/android/server/backup/params/RestoreParams.java
index a0b4187..93ce00d 100644
--- a/services/backup/java/com/android/server/backup/params/RestoreParams.java
+++ b/services/backup/java/com/android/server/backup/params/RestoreParams.java
@@ -19,6 +19,7 @@
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IRestoreObserver;
 import android.content.pm.PackageInfo;
+
 import com.android.internal.backup.IBackupTransport;
 
 public class RestoreParams {
@@ -37,7 +38,7 @@
      * Restore a single package; no kill after restore
      */
     public RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
-        IBackupManagerMonitor _monitor, long _token, PackageInfo _pkg) {
+            IBackupManagerMonitor _monitor, long _token, PackageInfo _pkg) {
         transport = _transport;
         dirName = _dirName;
         observer = _obs;
@@ -53,7 +54,7 @@
      * Restore at install: PM token needed, kill after restore
      */
     public RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
-        IBackupManagerMonitor _monitor, long _token, String _pkgName, int _pmToken) {
+            IBackupManagerMonitor _monitor, long _token, String _pkgName, int _pmToken) {
         transport = _transport;
         dirName = _dirName;
         observer = _obs;
@@ -70,7 +71,7 @@
      * restore UXes use.
      */
     public RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
-        IBackupManagerMonitor _monitor, long _token) {
+            IBackupManagerMonitor _monitor, long _token) {
         transport = _transport;
         dirName = _dirName;
         observer = _obs;
@@ -87,8 +88,8 @@
      * whether it's to be considered a system-level restore.
      */
     public RestoreParams(IBackupTransport _transport, String _dirName, IRestoreObserver _obs,
-        IBackupManagerMonitor _monitor, long _token,
-        String[] _filterSet, boolean _isSystemRestore) {
+            IBackupManagerMonitor _monitor, long _token,
+            String[] _filterSet, boolean _isSystemRestore) {
         transport = _transport;
         dirName = _dirName;
         observer = _obs;
diff --git a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
index 090d8f8..4470751 100644
--- a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
+++ b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
@@ -26,6 +26,7 @@
 import android.os.Binder;
 import android.os.Message;
 import android.util.Slog;
+
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.RefactoredBackupManagerService;
 import com.android.server.backup.params.RestoreGetSetsParams;
@@ -46,7 +47,7 @@
     boolean mTimedOut = false;
 
     public ActiveRestoreSession(RefactoredBackupManagerService backupManagerService,
-        String packageName, String transport) {
+            String packageName, String transport) {
         this.backupManagerService = backupManagerService;
         mPackageName = packageName;
         mRestoreTransport = backupManagerService.mTransportManager.getTransportBinder(transport);
@@ -58,9 +59,10 @@
 
     // --- Binder interface ---
     public synchronized int getAvailableRestoreSets(IRestoreObserver observer,
-        IBackupManagerMonitor monitor) {
-        backupManagerService.mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
-            "getAvailableRestoreSets");
+            IBackupManagerMonitor monitor) {
+        backupManagerService.mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.BACKUP,
+                "getAvailableRestoreSets");
         if (observer == null) {
             throw new IllegalArgumentException("Observer must not be null");
         }
@@ -85,14 +87,14 @@
             // until we're done.  It gets started again when the result
             // comes in.
             backupManagerService.mBackupHandler.removeMessages(
-                RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+                    RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
 
             // spin off the transport request to our service thread
             backupManagerService.mWakelock.acquire();
             Message msg = backupManagerService.mBackupHandler.obtainMessage(
-                RefactoredBackupManagerService.MSG_RUN_GET_RESTORE_SETS,
-                new RestoreGetSetsParams(mRestoreTransport, this, observer,
-                    monitor));
+                    RefactoredBackupManagerService.MSG_RUN_GET_RESTORE_SETS,
+                    new RestoreGetSetsParams(mRestoreTransport, this, observer,
+                            monitor));
             backupManagerService.mBackupHandler.sendMessage(msg);
             return 0;
         } catch (Exception e) {
@@ -104,13 +106,14 @@
     }
 
     public synchronized int restoreAll(long token, IRestoreObserver observer,
-        IBackupManagerMonitor monitor) {
-        backupManagerService.mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
-            "performRestore");
+            IBackupManagerMonitor monitor) {
+        backupManagerService.mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.BACKUP,
+                "performRestore");
 
         if (RefactoredBackupManagerService.DEBUG) {
-          Slog.d(TAG, "restoreAll token=" + Long.toHexString(token)
-              + " observer=" + observer);
+            Slog.d(TAG, "restoreAll token=" + Long.toHexString(token)
+                    + " observer=" + observer);
         }
 
         if (mEnded) {
@@ -146,7 +149,7 @@
                 if (token == mRestoreSets[i].token) {
                     // Real work, so stop the session timeout until we finalize the restore
                     backupManagerService.mBackupHandler.removeMessages(
-                        RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+                            RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
 
                     long oldId = Binder.clearCallingIdentity();
                     backupManagerService.mWakelock.acquire();
@@ -154,9 +157,9 @@
                         Slog.d(TAG, "restoreAll() kicking off");
                     }
                     Message msg = backupManagerService.mBackupHandler.obtainMessage(
-                        RefactoredBackupManagerService.MSG_RUN_RESTORE);
+                            RefactoredBackupManagerService.MSG_RUN_RESTORE);
                     msg.obj = new RestoreParams(mRestoreTransport, dirName,
-                        observer, monitor, token);
+                            observer, monitor, token);
                     backupManagerService.mBackupHandler.sendMessage(msg);
                     Binder.restoreCallingIdentity(oldId);
                     return 0;
@@ -170,9 +173,10 @@
 
     // Restores of more than a single package are treated as 'system' restores
     public synchronized int restoreSome(long token, IRestoreObserver observer,
-        IBackupManagerMonitor monitor, String[] packages) {
-        backupManagerService.mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
-            "performRestore");
+            IBackupManagerMonitor monitor, String[] packages) {
+        backupManagerService.mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.BACKUP,
+                "performRestore");
 
         if (RefactoredBackupManagerService.DEBUG) {
             StringBuilder b = new StringBuilder(128);
@@ -196,7 +200,7 @@
                     if (!first) {
                         b.append(", ");
                     } else {
-                      first = false;
+                        first = false;
                     }
                     b.append(s);
                 }
@@ -238,7 +242,7 @@
                 if (token == mRestoreSets[i].token) {
                     // Stop the session timeout until we finalize the restore
                     backupManagerService.mBackupHandler.removeMessages(
-                        RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+                            RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
 
                     long oldId = Binder.clearCallingIdentity();
                     backupManagerService.mWakelock.acquire();
@@ -246,9 +250,9 @@
                         Slog.d(TAG, "restoreSome() of " + packages.length + " packages");
                     }
                     Message msg = backupManagerService.mBackupHandler.obtainMessage(
-                        RefactoredBackupManagerService.MSG_RUN_RESTORE);
+                            RefactoredBackupManagerService.MSG_RUN_RESTORE);
                     msg.obj = new RestoreParams(mRestoreTransport, dirName, observer, monitor,
-                        token, packages, packages.length > 1);
+                            token, packages, packages.length > 1);
                     backupManagerService.mBackupHandler.sendMessage(msg);
                     Binder.restoreCallingIdentity(oldId);
                     return 0;
@@ -261,10 +265,10 @@
     }
 
     public synchronized int restorePackage(String packageName, IRestoreObserver observer,
-        IBackupManagerMonitor monitor) {
+            IBackupManagerMonitor monitor) {
         if (RefactoredBackupManagerService.DEBUG) {
-          Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer
-              + "monitor=" + monitor);
+            Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer
+                    + "monitor=" + monitor);
         }
 
         if (mEnded) {
@@ -279,7 +283,7 @@
         if (mPackageName != null) {
             if (!mPackageName.equals(packageName)) {
                 Slog.e(TAG, "Ignoring attempt to restore pkg=" + packageName
-                    + " on session for package " + mPackageName);
+                        + " on session for package " + mPackageName);
                 return -1;
             }
         }
@@ -295,11 +299,11 @@
         // If the caller is not privileged and is not coming from the target
         // app's uid, throw a permission exception back to the caller.
         int perm = backupManagerService.mContext.checkPermission(android.Manifest.permission.BACKUP,
-            Binder.getCallingPid(), Binder.getCallingUid());
+                Binder.getCallingPid(), Binder.getCallingUid());
         if ((perm == PackageManager.PERMISSION_DENIED) &&
-            (app.applicationInfo.uid != Binder.getCallingUid())) {
+                (app.applicationInfo.uid != Binder.getCallingUid())) {
             Slog.w(TAG, "restorePackage: bad packageName=" + packageName
-                + " or calling uid=" + Binder.getCallingUid());
+                    + " or calling uid=" + Binder.getCallingUid());
             throw new SecurityException("No permission to restore other packages");
         }
 
@@ -310,8 +314,8 @@
             // to the ancestral dataset if not.
             long token = backupManagerService.getAvailableRestoreToken(packageName);
             if (RefactoredBackupManagerService.DEBUG) {
-              Slog.v(TAG, "restorePackage pkg=" + packageName
-                  + " token=" + Long.toHexString(token));
+                Slog.v(TAG, "restorePackage pkg=" + packageName
+                        + " token=" + Long.toHexString(token));
             }
 
             // If we didn't come up with a place to look -- no ancestral dataset and
@@ -319,7 +323,7 @@
             // to do but return failure.
             if (token == 0) {
                 if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.w(TAG, "No data available for this package; not restoring");
+                    Slog.w(TAG, "No data available for this package; not restoring");
                 }
                 return -1;
             }
@@ -330,13 +334,13 @@
             } catch (Exception e) {
                 // Transport went AWOL; fail.
                 Slog.e(TAG,
-                    "Unable to get transport dir for restorePackage: " + e.getMessage());
+                        "Unable to get transport dir for restorePackage: " + e.getMessage());
                 return -1;
             }
 
             // Stop the session timeout until we finalize the restore
             backupManagerService.mBackupHandler.removeMessages(
-                RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+                    RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
 
             // Ready to go:  enqueue the restore request and claim success
             backupManagerService.mWakelock.acquire();
@@ -344,9 +348,9 @@
                 Slog.d(TAG, "restorePackage() : " + packageName);
             }
             Message msg = backupManagerService.mBackupHandler.obtainMessage(
-                RefactoredBackupManagerService.MSG_RUN_RESTORE);
+                    RefactoredBackupManagerService.MSG_RUN_RESTORE);
             msg.obj = new RestoreParams(mRestoreTransport, dirName, observer, monitor,
-                token, app);
+                    token, app);
             backupManagerService.mBackupHandler.sendMessage(msg);
         } finally {
             Binder.restoreCallingIdentity(oldId);
@@ -357,11 +361,11 @@
     // Posted to the handler to tear down a restore session in a cleanly synchronized way
     public class EndRestoreRunnable implements Runnable {
 
-      RefactoredBackupManagerService mBackupManager;
+        RefactoredBackupManagerService mBackupManager;
         ActiveRestoreSession mSession;
 
         public EndRestoreRunnable(RefactoredBackupManagerService manager,
-            ActiveRestoreSession session) {
+                ActiveRestoreSession session) {
             mBackupManager = manager;
             mSession = session;
         }
@@ -381,7 +385,7 @@
 
     public synchronized void endRestoreSession() {
         if (RefactoredBackupManagerService.DEBUG) {
-          Slog.d(TAG, "endRestoreSession");
+            Slog.d(TAG, "endRestoreSession");
         }
 
         if (mTimedOut) {
@@ -393,6 +397,7 @@
             throw new IllegalStateException("Restore session already ended");
         }
 
-        backupManagerService.mBackupHandler.post(new EndRestoreRunnable(backupManagerService, this));
+        backupManagerService.mBackupHandler.post(
+                new EndRestoreRunnable(backupManagerService, this));
     }
 }
diff --git a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
index 2360b5c..5e3664f 100644
--- a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
+++ b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
@@ -17,8 +17,10 @@
 package com.android.server.backup.restore;
 
 import android.util.Slog;
+
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.RefactoredBackupManagerService;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -27,13 +29,13 @@
  */
 public class AdbRestoreFinishedLatch implements BackupRestoreTask {
 
-  private static final String TAG = "AdbRestoreFinishedLatch";
+    private static final String TAG = "AdbRestoreFinishedLatch";
     private RefactoredBackupManagerService backupManagerService;
     final CountDownLatch mLatch;
     private final int mCurrentOpToken;
 
     public AdbRestoreFinishedLatch(RefactoredBackupManagerService backupManagerService,
-        int currentOpToken) {
+            int currentOpToken) {
         this.backupManagerService = backupManagerService;
         mLatch = new CountDownLatch(1);
         mCurrentOpToken = currentOpToken;
@@ -42,7 +44,8 @@
     void await() {
         boolean latched = false;
         try {
-            latched = mLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
+            latched = mLatch.await(RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                    TimeUnit.MILLISECONDS);
         } catch (InterruptedException e) {
             Slog.w(TAG, "Interrupted!");
         }
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index 5722543..0b1eec2 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -54,10 +54,12 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Slog;
+
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.FileMetadata;
 import com.android.server.backup.RefactoredBackupManagerService;
 import com.android.server.backup.fullbackup.FullBackupObbConnection;
+
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.File;
@@ -104,14 +106,14 @@
 
     // possible handling states for a given package in the restore dataset
     final HashMap<String, RestorePolicy> mPackagePolicies
-        = new HashMap<>();
+            = new HashMap<>();
 
     // installer package names for each encountered app, derived from the manifests
     final HashMap<String, String> mPackageInstallers = new HashMap<>();
 
     // Signatures for a given package found in its manifest file
     final HashMap<String, Signature[]> mManifestSignatures
-        = new HashMap<>();
+            = new HashMap<>();
 
     // Packages we've already wiped data on when restoring their first file
     final HashSet<String> mClearedPackages = new HashSet<>();
@@ -134,13 +136,13 @@
     // invocations of the full restore API asynchronously. Used by adb restore.
     class RestoreFileRunnable implements Runnable {
 
-      IBackupAgent mAgent;
+        IBackupAgent mAgent;
         FileMetadata mInfo;
         ParcelFileDescriptor mSocket;
         int mToken;
 
         RestoreFileRunnable(IBackupAgent agent, FileMetadata info,
-            ParcelFileDescriptor socket, int token) throws IOException {
+                ParcelFileDescriptor socket, int token) throws IOException {
             mAgent = agent;
             mInfo = info;
             mToken = token;
@@ -157,8 +159,8 @@
         public void run() {
             try {
                 mAgent.doRestoreFile(mSocket, mInfo.size, mInfo.type,
-                    mInfo.domain, mInfo.path, mInfo.mode, mInfo.mtime,
-                    mToken, backupManagerService.mBackupManagerBinder);
+                        mInfo.domain, mInfo.path, mInfo.mode, mInfo.mtime,
+                        mToken, backupManagerService.mBackupManagerBinder);
             } catch (RemoteException e) {
                 // never happens; this is used strictly for local binder calls
             }
@@ -166,9 +168,9 @@
     }
 
     public FullRestoreEngine(RefactoredBackupManagerService backupManagerService,
-        BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer,
-        IBackupManagerMonitor monitor, PackageInfo onlyPackage, boolean allowApks,
-        boolean allowObbs, int ephemeralOpToken) {
+            BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer,
+            IBackupManagerMonitor monitor, PackageInfo onlyPackage, boolean allowApks,
+            boolean allowObbs, int ephemeralOpToken) {
         this.backupManagerService = backupManagerService;
         mEphemeralOpToken = ephemeralOpToken;
         mMonitorTask = monitorTask;
@@ -212,8 +214,9 @@
                     // one app's data but see a different app's on the wire
                     if (mOnlyPackage != null) {
                         if (!pkg.equals(mOnlyPackage.packageName)) {
-                            Slog.w(RefactoredBackupManagerService.TAG, "Expected data for " + mOnlyPackage
-                                + " but saw " + pkg);
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Expected data for " + mOnlyPackage
+                                            + " but saw " + pkg);
                             setResult(RestoreEngine.TRANSPORT_FAILURE);
                             setRunning(false);
                             return false;
@@ -230,7 +233,8 @@
                     // and let the observer know we're considering a new app.
                     if (mAgent != null) {
                         if (RefactoredBackupManagerService.DEBUG) {
-                          Slog.d(RefactoredBackupManagerService.TAG, "Saw new package; finalizing old one");
+                            Slog.d(RefactoredBackupManagerService.TAG,
+                                    "Saw new package; finalizing old one");
                         }
                         // Now we're really done
                         tearDownPipes();
@@ -248,7 +252,8 @@
                     // input file
                     skipTarPadding(info.size, instream);
                     sendOnRestorePackage(pkg);
-                } else if (info.path.equals(RefactoredBackupManagerService.BACKUP_METADATA_FILENAME)) {
+                } else if (info.path.equals(
+                        RefactoredBackupManagerService.BACKUP_METADATA_FILENAME)) {
                     // Metadata blobs!
                     readMetadata(info, instream);
                     skipTarPadding(info.size, instream);
@@ -267,15 +272,16 @@
                             // see MUST be the apk.
                             if (info.domain.equals(FullBackup.APK_TREE_TOKEN)) {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "APK file; installing");
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "APK file; installing");
                                 }
                                 // Try to install the app.
                                 String installerName = mPackageInstallers.get(pkg);
                                 okay = installApk(info, installerName, instream);
                                 // good to go; promote to ACCEPT
                                 mPackagePolicies.put(pkg, (okay)
-                                    ? RestorePolicy.ACCEPT
-                                    : RestorePolicy.IGNORE);
+                                        ? RestorePolicy.ACCEPT
+                                        : RestorePolicy.IGNORE);
                                 // At this point we've consumed this file entry
                                 // ourselves, so just strip the tar footer and
                                 // go on to the next file in the input stream
@@ -292,7 +298,8 @@
                         case ACCEPT:
                             if (info.domain.equals(FullBackup.APK_TREE_TOKEN)) {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "apk present but ACCEPT");
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "apk present but ACCEPT");
                                 }
                                 // we can take the data without the apk, so we
                                 // *want* to do so.  skip the apk by declaring this
@@ -306,7 +313,8 @@
                             // Something has gone dreadfully wrong when determining
                             // the restore policy from the manifest.  Ignore the
                             // rest of this package's data.
-                            Slog.e(RefactoredBackupManagerService.TAG, "Invalid policy from manifest");
+                            Slog.e(RefactoredBackupManagerService.TAG,
+                                    "Invalid policy from manifest");
                             okay = false;
                             mPackagePolicies.put(pkg, RestorePolicy.IGNORE);
                             break;
@@ -320,15 +328,18 @@
                     // If the policy is satisfied, go ahead and set up to pipe the
                     // data to the agent.
                     if (RefactoredBackupManagerService.MORE_DEBUG && okay && mAgent != null) {
-                        Slog.i(RefactoredBackupManagerService.TAG, "Reusing existing agent instance");
+                        Slog.i(RefactoredBackupManagerService.TAG,
+                                "Reusing existing agent instance");
                     }
                     if (okay && mAgent == null) {
                         if (RefactoredBackupManagerService.MORE_DEBUG) {
-                          Slog.d(RefactoredBackupManagerService.TAG, "Need to launch agent for " + pkg);
+                            Slog.d(RefactoredBackupManagerService.TAG,
+                                    "Need to launch agent for " + pkg);
                         }
 
                         try {
-                            mTargetApp = backupManagerService.mPackageManager.getApplicationInfo(pkg, 0);
+                            mTargetApp = backupManagerService.mPackageManager.getApplicationInfo(
+                                    pkg, 0);
 
                             // If we haven't sent any data to this app yet, we probably
                             // need to clear it first.  Check that.
@@ -338,28 +349,29 @@
                                 // restore.
                                 if (mTargetApp.backupAgentName == null) {
                                     if (RefactoredBackupManagerService.DEBUG) {
-                                      Slog.d(RefactoredBackupManagerService.TAG,
-                                          "Clearing app data preparatory to full restore");
+                                        Slog.d(RefactoredBackupManagerService.TAG,
+                                                "Clearing app data preparatory to full restore");
                                     }
                                     backupManagerService.clearApplicationDataSynchronous(pkg);
                                 } else {
                                     if (RefactoredBackupManagerService.MORE_DEBUG) {
-                                      Slog.d(RefactoredBackupManagerService.TAG, "backup agent ("
-                                          + mTargetApp.backupAgentName + ") => no clear");
+                                        Slog.d(RefactoredBackupManagerService.TAG, "backup agent ("
+                                                + mTargetApp.backupAgentName + ") => no clear");
                                     }
                                 }
                                 mClearedPackages.add(pkg);
                             } else {
                                 if (RefactoredBackupManagerService.MORE_DEBUG) {
                                     Slog.d(RefactoredBackupManagerService.TAG,
-                                        "We've initialized this app already; no clear required");
+                                            "We've initialized this app already; no clear "
+                                                    + "required");
                                 }
                             }
 
                             // All set; now set up the IPC and launch the agent
                             setUpPipes();
                             mAgent = backupManagerService.bindToAgentSynchronous(mTargetApp,
-                                ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL);
+                                    ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL);
                             mAgentPackage = pkg;
                         } catch (IOException e) {
                             // fall through to error handling
@@ -369,7 +381,8 @@
 
                         if (mAgent == null) {
                             Slog.e(
-                                RefactoredBackupManagerService.TAG, "Unable to create agent for " + pkg);
+                                    RefactoredBackupManagerService.TAG,
+                                    "Unable to create agent for " + pkg);
                             okay = false;
                             tearDownPipes();
                             mPackagePolicies.put(pkg, RestorePolicy.IGNORE);
@@ -380,7 +393,7 @@
                     // should never happen but a little paranoia here won't go amiss.
                     if (okay && !pkg.equals(mAgentPackage)) {
                         Slog.e(RefactoredBackupManagerService.TAG, "Restoring data for " + pkg
-                            + " but agent is for " + mAgentPackage);
+                                + " but agent is for " + mAgentPackage);
                         okay = false;
                     }
 
@@ -393,46 +406,54 @@
                         long toCopy = info.size;
                         try {
                             backupManagerService.prepareOperationTimeout(mEphemeralOpToken,
-                                RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL, mMonitorTask,
-                                RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
+                                    RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                                    mMonitorTask,
+                                    RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
 
                             if (info.domain.equals(FullBackup.OBB_TREE_TOKEN)) {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "Restoring OBB file for " + pkg
-                                      + " : " + info.path);
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "Restoring OBB file for " + pkg
+                                                    + " : " + info.path);
                                 }
                                 mObbConnection.restoreObbFile(pkg, mPipes[0],
-                                    info.size, info.type, info.path, info.mode,
-                                    info.mtime, mEphemeralOpToken, backupManagerService.mBackupManagerBinder);
+                                        info.size, info.type, info.path, info.mode,
+                                        info.mtime, mEphemeralOpToken,
+                                        backupManagerService.mBackupManagerBinder);
                             } else {
                                 if (RefactoredBackupManagerService.MORE_DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "Invoking agent to restore file "
-                                      + info.path);
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "Invoking agent to restore file "
+                                                    + info.path);
                                 }
                                 // fire up the app's agent listening on the socket.  If
                                 // the agent is running in the system process we can't
                                 // just invoke it asynchronously, so we provide a thread
                                 // for it here.
                                 if (mTargetApp.processName.equals("system")) {
-                                    Slog.d(RefactoredBackupManagerService.TAG, "system process agent - spinning a thread");
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "system process agent - spinning a thread");
                                     RestoreFileRunnable runner = new RestoreFileRunnable(
-                                        mAgent, info, mPipes[0], mEphemeralOpToken);
+                                            mAgent, info, mPipes[0], mEphemeralOpToken);
                                     new Thread(runner, "restore-sys-runner").start();
                                 } else {
                                     mAgent.doRestoreFile(mPipes[0], info.size, info.type,
-                                        info.domain, info.path, info.mode, info.mtime,
-                                        mEphemeralOpToken, backupManagerService.mBackupManagerBinder);
+                                            info.domain, info.path, info.mode, info.mtime,
+                                            mEphemeralOpToken,
+                                            backupManagerService.mBackupManagerBinder);
                                 }
                             }
                         } catch (IOException e) {
                             // couldn't dup the socket for a process-local restore
-                            Slog.d(RefactoredBackupManagerService.TAG, "Couldn't establish restore");
+                            Slog.d(RefactoredBackupManagerService.TAG,
+                                    "Couldn't establish restore");
                             agentSuccess = false;
                             okay = false;
                         } catch (RemoteException e) {
                             // whoops, remote entity went away.  We'll eat the content
                             // ourselves, then, and not copy it over.
-                            Slog.e(RefactoredBackupManagerService.TAG, "Agent crashed during full restore");
+                            Slog.e(RefactoredBackupManagerService.TAG,
+                                    "Agent crashed during full restore");
                             agentSuccess = false;
                             okay = false;
                         }
@@ -440,21 +461,22 @@
                         // Copy over the data if the agent is still good
                         if (okay) {
                             if (RefactoredBackupManagerService.MORE_DEBUG) {
-                                Slog.v(RefactoredBackupManagerService.TAG, "  copying to restore agent: "
-                                    + toCopy + " bytes");
+                                Slog.v(RefactoredBackupManagerService.TAG,
+                                        "  copying to restore agent: "
+                                                + toCopy + " bytes");
                             }
                             boolean pipeOkay = true;
                             FileOutputStream pipe = new FileOutputStream(
-                                mPipes[1].getFileDescriptor());
+                                    mPipes[1].getFileDescriptor());
                             while (toCopy > 0) {
                                 int toRead = (toCopy > mBuffer.length)
-                                    ? mBuffer.length : (int) toCopy;
+                                        ? mBuffer.length : (int) toCopy;
                                 int nRead = instream.read(mBuffer, 0, toRead);
                                 if (nRead >= 0) {
-                                  mBytes += nRead;
+                                    mBytes += nRead;
                                 }
                                 if (nRead <= 0) {
-                                  break;
+                                    break;
                                 }
                                 toCopy -= nRead;
 
@@ -464,8 +486,9 @@
                                     try {
                                         pipe.write(mBuffer, 0, nRead);
                                     } catch (IOException e) {
-                                        Slog.e(RefactoredBackupManagerService.TAG, "Failed to write to restore pipe: "
-                                            + e.getMessage());
+                                        Slog.e(RefactoredBackupManagerService.TAG,
+                                                "Failed to write to restore pipe: "
+                                                        + e.getMessage());
                                         pipeOkay = false;
                                     }
                                 }
@@ -477,15 +500,17 @@
 
                             // and now that we've sent it all, wait for the remote
                             // side to acknowledge receipt
-                            agentSuccess = backupManagerService.waitUntilOperationComplete(mEphemeralOpToken);
+                            agentSuccess = backupManagerService.waitUntilOperationComplete(
+                                    mEphemeralOpToken);
                         }
 
                         // okay, if the remote end failed at any point, deal with
                         // it by ignoring the rest of the restore on it
                         if (!agentSuccess) {
-                            Slog.w(RefactoredBackupManagerService.TAG, "Agent failure; ending restore");
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Agent failure; ending restore");
                             backupManagerService.mBackupHandler.removeMessages(
-                                RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
+                                    RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
                             tearDownPipes();
                             tearDownAgent(mTargetApp);
                             mAgent = null;
@@ -506,18 +531,18 @@
                     // next stream entry by reading and discarding this file.
                     if (!okay) {
                         if (RefactoredBackupManagerService.MORE_DEBUG) {
-                          Slog.d(RefactoredBackupManagerService.TAG, "[discarding file content]");
+                            Slog.d(RefactoredBackupManagerService.TAG, "[discarding file content]");
                         }
                         long bytesToConsume = (info.size + 511) & ~511;
                         while (bytesToConsume > 0) {
                             int toRead = (bytesToConsume > mBuffer.length)
-                                ? mBuffer.length : (int) bytesToConsume;
+                                    ? mBuffer.length : (int) bytesToConsume;
                             long nRead = instream.read(mBuffer, 0, toRead);
                             if (nRead >= 0) {
-                              mBytes += nRead;
+                                mBytes += nRead;
                             }
                             if (nRead <= 0) {
-                              break;
+                                break;
                             }
                             bytesToConsume -= nRead;
                         }
@@ -526,7 +551,8 @@
             }
         } catch (IOException e) {
             if (RefactoredBackupManagerService.DEBUG) {
-              Slog.w(RefactoredBackupManagerService.TAG, "io exception on restore socket read: " + e.getMessage());
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "io exception on restore socket read: " + e.getMessage());
             }
             setResult(RestoreEngine.TRANSPORT_FAILURE);
             info = null;
@@ -535,7 +561,8 @@
         // If we got here we're either running smoothly or we've finished
         if (info == null) {
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-                Slog.i(RefactoredBackupManagerService.TAG, "No [more] data for this package; tearing down");
+                Slog.i(RefactoredBackupManagerService.TAG,
+                        "No [more] data for this package; tearing down");
             }
             tearDownPipes();
             setRunning(false);
@@ -584,7 +611,7 @@
 
     class RestoreInstallObserver extends PackageInstallObserver {
 
-      final AtomicBoolean mDone = new AtomicBoolean();
+        final AtomicBoolean mDone = new AtomicBoolean();
         String mPackageName;
         int mResult;
 
@@ -611,7 +638,7 @@
 
         @Override
         public void onPackageInstalled(String packageName, int returnCode,
-            String msg, Bundle extras) {
+                String msg, Bundle extras) {
             synchronized (mDone) {
                 mResult = returnCode;
                 mPackageName = packageName;
@@ -623,7 +650,7 @@
 
     class RestoreDeleteObserver extends IPackageDeleteObserver.Stub {
 
-      final AtomicBoolean mDone = new AtomicBoolean();
+        final AtomicBoolean mDone = new AtomicBoolean();
         int mResult;
 
         public void reset() {
@@ -660,7 +687,8 @@
         boolean okay = true;
 
         if (RefactoredBackupManagerService.DEBUG) {
-          Slog.d(RefactoredBackupManagerService.TAG, "Installing from backup: " + info.packageName);
+            Slog.d(RefactoredBackupManagerService.TAG,
+                    "Installing from backup: " + info.packageName);
         }
 
         // The file content is an .apk file.  Copy it out to a staging location and
@@ -674,7 +702,7 @@
                 long toRead = (buffer.length < size) ? buffer.length : size;
                 int didRead = instream.read(buffer, 0, (int) toRead);
                 if (didRead >= 0) {
-                  mBytes += didRead;
+                    mBytes += didRead;
                 }
                 apkStream.write(buffer, 0, didRead);
                 size -= didRead;
@@ -688,8 +716,8 @@
             Uri packageUri = Uri.fromFile(apkFile);
             mInstallObserver.reset();
             backupManagerService.mPackageManager.installPackage(packageUri, mInstallObserver,
-                PackageManager.INSTALL_REPLACE_EXISTING | PackageManager.INSTALL_FROM_ADB,
-                installerPackage);
+                    PackageManager.INSTALL_REPLACE_EXISTING | PackageManager.INSTALL_FROM_ADB,
+                    installerPackage);
             mInstallObserver.waitForCompletion();
 
             if (mInstallObserver.getResult() != PackageManager.INSTALL_SUCCEEDED) {
@@ -703,20 +731,24 @@
                 // Okay, the install succeeded.  Make sure it was the right app.
                 boolean uninstall = false;
                 if (!mInstallObserver.mPackageName.equals(info.packageName)) {
-                    Slog.w(RefactoredBackupManagerService.TAG, "Restore stream claimed to include apk for "
-                        + info.packageName + " but apk was really "
-                        + mInstallObserver.mPackageName);
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "Restore stream claimed to include apk for "
+                                    + info.packageName + " but apk was really "
+                                    + mInstallObserver.mPackageName);
                     // delete the package we just put in place; it might be fraudulent
                     okay = false;
                     uninstall = true;
                 } else {
                     try {
-                        PackageInfo pkg = backupManagerService.mPackageManager.getPackageInfo(info.packageName,
-                            PackageManager.GET_SIGNATURES);
+                        PackageInfo pkg = backupManagerService.mPackageManager.getPackageInfo(
+                                info.packageName,
+                                PackageManager.GET_SIGNATURES);
                         if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP)
-                            == 0) {
-                            Slog.w(RefactoredBackupManagerService.TAG, "Restore stream contains apk of package "
-                                + info.packageName + " but it disallows backup/restore");
+                                == 0) {
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Restore stream contains apk of package "
+                                            + info.packageName
+                                            + " but it disallows backup/restore");
                             okay = false;
                         } else {
                             // So far so good -- do the signatures match the manifest?
@@ -725,21 +757,24 @@
                                 // If this is a system-uid app without a declared backup agent,
                                 // don't restore any of the file data.
                                 if ((pkg.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
-                                    && (pkg.applicationInfo.backupAgentName == null)) {
-                                    Slog.w(RefactoredBackupManagerService.TAG, "Installed app " + info.packageName
-                                        + " has restricted uid and no agent");
+                                        && (pkg.applicationInfo.backupAgentName == null)) {
+                                    Slog.w(RefactoredBackupManagerService.TAG,
+                                            "Installed app " + info.packageName
+                                                    + " has restricted uid and no agent");
                                     okay = false;
                                 }
                             } else {
-                                Slog.w(RefactoredBackupManagerService.TAG, "Installed app " + info.packageName
-                                    + " signatures do not match restore manifest");
+                                Slog.w(RefactoredBackupManagerService.TAG,
+                                        "Installed app " + info.packageName
+                                                + " signatures do not match restore manifest");
                                 okay = false;
                                 uninstall = true;
                             }
                         }
                     } catch (NameNotFoundException e) {
-                        Slog.w(RefactoredBackupManagerService.TAG, "Install of package " + info.packageName
-                            + " succeeded but now not found");
+                        Slog.w(RefactoredBackupManagerService.TAG,
+                                "Install of package " + info.packageName
+                                        + " succeeded but now not found");
                         okay = false;
                     }
                 }
@@ -748,13 +783,15 @@
                 // that we just installed.
                 if (uninstall) {
                     mDeleteObserver.reset();
-                    backupManagerService.mPackageManager.deletePackage(mInstallObserver.mPackageName,
-                        mDeleteObserver, 0);
+                    backupManagerService.mPackageManager.deletePackage(
+                            mInstallObserver.mPackageName,
+                            mDeleteObserver, 0);
                     mDeleteObserver.waitForCompletion();
                 }
             }
         } catch (IOException e) {
-            Slog.e(RefactoredBackupManagerService.TAG, "Unable to transcribe restored apk for install");
+            Slog.e(RefactoredBackupManagerService.TAG,
+                    "Unable to transcribe restored apk for install");
             okay = false;
         } finally {
             apkFile.delete();
@@ -770,13 +807,14 @@
         if (partial > 0) {
             final int needed = 512 - (int) partial;
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-                Slog.i(RefactoredBackupManagerService.TAG, "Skipping tar padding: " + needed + " bytes");
+                Slog.i(RefactoredBackupManagerService.TAG,
+                        "Skipping tar padding: " + needed + " bytes");
             }
             byte[] buffer = new byte[needed];
             if (readExactly(instream, buffer, 0, needed) == needed) {
                 mBytes += needed;
             } else {
-              throw new IOException("Unexpected EOF in padding");
+                throw new IOException("Unexpected EOF in padding");
             }
         }
     }
@@ -792,7 +830,7 @@
         if (readExactly(instream, buffer, 0, (int) info.size) == info.size) {
             mBytes += info.size;
         } else {
-          throw new IOException("Unexpected EOF in widget data");
+            throw new IOException("Unexpected EOF in widget data");
         }
 
         String[] str = new String[1];
@@ -805,20 +843,21 @@
                 // Data checks out -- the rest of the buffer is a concatenation of
                 // binary blobs as described in the comment at writeAppWidgetData()
                 ByteArrayInputStream bin = new ByteArrayInputStream(buffer,
-                    offset, buffer.length - offset);
+                        offset, buffer.length - offset);
                 DataInputStream in = new DataInputStream(bin);
                 while (bin.available() > 0) {
                     int token = in.readInt();
                     int size = in.readInt();
                     if (size > 64 * 1024) {
                         throw new IOException("Datum "
-                            + Integer.toHexString(token)
-                            + " too big; corrupt? size=" + info.size);
+                                + Integer.toHexString(token)
+                                + " too big; corrupt? size=" + info.size);
                     }
                     switch (token) {
                         case RefactoredBackupManagerService.BACKUP_WIDGET_METADATA_TOKEN: {
                             if (RefactoredBackupManagerService.MORE_DEBUG) {
-                                Slog.i(RefactoredBackupManagerService.TAG, "Got widget metadata for " + info.packageName);
+                                Slog.i(RefactoredBackupManagerService.TAG,
+                                        "Got widget metadata for " + info.packageName);
                             }
                             mWidgetData = new byte[size];
                             in.read(mWidgetData);
@@ -827,8 +866,8 @@
                         default: {
                             if (RefactoredBackupManagerService.DEBUG) {
                                 Slog.i(RefactoredBackupManagerService.TAG, "Ignoring metadata blob "
-                                    + Integer.toHexString(token)
-                                    + " for " + info.packageName);
+                                        + Integer.toHexString(token)
+                                        + " for " + info.packageName);
                             }
                             in.skipBytes(size);
                             break;
@@ -836,38 +875,39 @@
                     }
                 }
             } else {
-                Slog.w(RefactoredBackupManagerService.TAG, "Metadata mismatch: package " + info.packageName
-                    + " but widget data for " + pkg);
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "Metadata mismatch: package " + info.packageName
+                                + " but widget data for " + pkg);
 
                 Bundle monitoringExtras = backupManagerService.putMonitoringExtra(null,
-                    EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+                        EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
                 monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
-                    BackupManagerMonitor.EXTRA_LOG_WIDGET_PACKAGE_NAME, pkg);
+                        BackupManagerMonitor.EXTRA_LOG_WIDGET_PACKAGE_NAME, pkg);
                 mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                    BackupManagerMonitor.LOG_EVENT_ID_WIDGET_METADATA_MISMATCH,
-                    null,
-                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                    monitoringExtras);
+                        BackupManagerMonitor.LOG_EVENT_ID_WIDGET_METADATA_MISMATCH,
+                        null,
+                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        monitoringExtras);
             }
         } else {
             Slog.w(RefactoredBackupManagerService.TAG, "Unsupported metadata version " + version);
 
             Bundle monitoringExtras = backupManagerService
-                .putMonitoringExtra(null, EXTRA_LOG_EVENT_PACKAGE_NAME,
-                    info.packageName);
+                    .putMonitoringExtra(null, EXTRA_LOG_EVENT_PACKAGE_NAME,
+                            info.packageName);
             monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
-                EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
+                    EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                BackupManagerMonitor.LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION,
-                null,
-                LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                monitoringExtras);
+                    BackupManagerMonitor.LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION,
+                    null,
+                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                    monitoringExtras);
         }
     }
 
     // Returns a policy constant
     RestorePolicy readAppManifest(FileMetadata info, InputStream instream)
-        throws IOException {
+            throws IOException {
         // Fail on suspiciously large manifest files
         if (info.size > 64 * 1024) {
             throw new IOException("Restore manifest too big; corrupt? size=" + info.size);
@@ -875,13 +915,14 @@
 
         byte[] buffer = new byte[(int) info.size];
         if (RefactoredBackupManagerService.MORE_DEBUG) {
-            Slog.i(RefactoredBackupManagerService.TAG, "   readAppManifest() looking for " + info.size + " bytes, "
-                + mBytes + " already consumed");
+            Slog.i(RefactoredBackupManagerService.TAG,
+                    "   readAppManifest() looking for " + info.size + " bytes, "
+                            + mBytes + " already consumed");
         }
         if (readExactly(instream, buffer, 0, (int) info.size) == info.size) {
             mBytes += info.size;
         } else {
-          throw new IOException("Unexpected EOF in manifest");
+            throw new IOException("Unexpected EOF in manifest");
         }
 
         RestorePolicy policy = RestorePolicy.IGNORE;
@@ -918,16 +959,17 @@
 
                         // Okay, got the manifest info we need...
                         try {
-                            PackageInfo pkgInfo = backupManagerService.mPackageManager.getPackageInfo(
-                                info.packageName, PackageManager.GET_SIGNATURES);
+                            PackageInfo pkgInfo =
+                                    backupManagerService.mPackageManager.getPackageInfo(
+                                            info.packageName, PackageManager.GET_SIGNATURES);
                             // Fall through to IGNORE if the app explicitly disallows backup
                             final int flags = pkgInfo.applicationInfo.flags;
                             if ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
                                 // Restore system-uid-space packages only if they have
                                 // defined a custom backup agent
                                 if ((pkgInfo.applicationInfo.uid
-                                    >= Process.FIRST_APPLICATION_UID)
-                                    || (pkgInfo.applicationInfo.backupAgentName != null)) {
+                                        >= Process.FIRST_APPLICATION_UID)
+                                        || (pkgInfo.applicationInfo.backupAgentName != null)) {
                                     // Verify signatures against any installed version; if they
                                     // don't match, then we fall though and ignore the data.  The
                                     // signatureMatch() method explicitly ignores the signature
@@ -935,78 +977,92 @@
                                     // such packages are signed with the platform cert instead of
                                     // the app developer's cert, so they're different on every
                                     // device.
-                                    if (RefactoredBackupManagerService.signaturesMatch(sigs, pkgInfo)) {
+                                    if (RefactoredBackupManagerService.signaturesMatch(sigs,
+                                            pkgInfo)) {
                                         if ((pkgInfo.applicationInfo.flags
-                                            & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
+                                                & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
                                             Slog.i(RefactoredBackupManagerService.TAG,
-                                                "Package has restoreAnyVersion; taking data");
-                                            mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                                                LOG_EVENT_ID_RESTORE_ANY_VERSION,
-                                                pkgInfo,
-                                                LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                                null);
+                                                    "Package has restoreAnyVersion; taking data");
+                                            mMonitor = RefactoredBackupManagerService.monitorEvent(
+                                                    mMonitor,
+                                                    LOG_EVENT_ID_RESTORE_ANY_VERSION,
+                                                    pkgInfo,
+                                                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                                    null);
                                             policy = RestorePolicy.ACCEPT;
                                         } else if (pkgInfo.versionCode >= version) {
-                                            Slog.i(RefactoredBackupManagerService.TAG, "Sig + version match; taking data");
+                                            Slog.i(RefactoredBackupManagerService.TAG,
+                                                    "Sig + version match; taking data");
                                             policy = RestorePolicy.ACCEPT;
-                                            mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                                                LOG_EVENT_ID_VERSIONS_MATCH,
-                                                pkgInfo,
-                                                LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                                null);
+                                            mMonitor = RefactoredBackupManagerService.monitorEvent(
+                                                    mMonitor,
+                                                    LOG_EVENT_ID_VERSIONS_MATCH,
+                                                    pkgInfo,
+                                                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                                    null);
                                         } else {
                                             // The data is from a newer version of the app than
                                             // is presently installed.  That means we can only
                                             // use it if the matching apk is also supplied.
                                             if (mAllowApks) {
-                                                Slog.i(RefactoredBackupManagerService.TAG, "Data version " + version
-                                                    + " is newer than installed version "
-                                                    + pkgInfo.versionCode
-                                                    + " - requiring apk");
+                                                Slog.i(RefactoredBackupManagerService.TAG,
+                                                        "Data version " + version
+                                                                + " is newer than installed "
+                                                                + "version "
+                                                                + pkgInfo.versionCode
+                                                                + " - requiring apk");
                                                 policy = RestorePolicy.ACCEPT_IF_APK;
                                             } else {
-                                                Slog.i(RefactoredBackupManagerService.TAG, "Data requires newer version "
-                                                    + version + "; ignoring");
+                                                Slog.i(RefactoredBackupManagerService.TAG,
+                                                        "Data requires newer version "
+                                                                + version + "; ignoring");
                                                 mMonitor = RefactoredBackupManagerService
-                                                    .monitorEvent(mMonitor,
-                                                        LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER,
-                                                        pkgInfo,
-                                                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                                        backupManagerService.putMonitoringExtra(null,
-                                                            EXTRA_LOG_OLD_VERSION,
-                                                            version));
+                                                        .monitorEvent(mMonitor,
+                                                                LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER,
+                                                                pkgInfo,
+                                                                LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                                                backupManagerService
+                                                                        .putMonitoringExtra(
+                                                                        null,
+                                                                        EXTRA_LOG_OLD_VERSION,
+                                                                        version));
 
                                                 policy = RestorePolicy.IGNORE;
                                             }
                                         }
                                     } else {
-                                        Slog.w(RefactoredBackupManagerService.TAG, "Restore manifest signatures do not match "
-                                            + "installed application for " + info.packageName);
-                                        mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                                            LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH,
-                                            pkgInfo,
-                                            LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                            null);
+                                        Slog.w(RefactoredBackupManagerService.TAG,
+                                                "Restore manifest signatures do not match "
+                                                        + "installed application for "
+                                                        + info.packageName);
+                                        mMonitor = RefactoredBackupManagerService.monitorEvent(
+                                                mMonitor,
+                                                LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH,
+                                                pkgInfo,
+                                                LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                                null);
                                     }
                                 } else {
-                                    Slog.w(RefactoredBackupManagerService.TAG, "Package " + info.packageName
-                                        + " is system level with no agent");
+                                    Slog.w(RefactoredBackupManagerService.TAG,
+                                            "Package " + info.packageName
+                                                    + " is system level with no agent");
                                     mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                                        LOG_EVENT_ID_SYSTEM_APP_NO_AGENT,
-                                        pkgInfo,
-                                        LOG_EVENT_CATEGORY_AGENT,
-                                        null);
+                                            LOG_EVENT_ID_SYSTEM_APP_NO_AGENT,
+                                            pkgInfo,
+                                            LOG_EVENT_CATEGORY_AGENT,
+                                            null);
                                 }
                             } else {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.i(RefactoredBackupManagerService.TAG, "Restore manifest from "
-                                      + info.packageName + " but allowBackup=false");
+                                    Slog.i(RefactoredBackupManagerService.TAG,
+                                            "Restore manifest from "
+                                                    + info.packageName + " but allowBackup=false");
                                 }
                                 mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                                    LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE,
-                                    pkgInfo,
-                                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                    null);
+                                        LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE,
+                                        pkgInfo,
+                                        LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                        null);
                             }
                         } catch (NameNotFoundException e) {
                             // Okay, the target app isn't installed.  We can process
@@ -1014,78 +1070,86 @@
                             // apk file and we can successfully install it.
                             if (mAllowApks) {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.i(RefactoredBackupManagerService.TAG, "Package " + info.packageName
-                                      + " not installed; requiring apk in dataset");
+                                    Slog.i(RefactoredBackupManagerService.TAG,
+                                            "Package " + info.packageName
+                                                    + " not installed; requiring apk in dataset");
                                 }
                                 policy = RestorePolicy.ACCEPT_IF_APK;
                             } else {
                                 policy = RestorePolicy.IGNORE;
                             }
                             Bundle monitoringExtras = backupManagerService.putMonitoringExtra(null,
-                                EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
-                            monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
-                                EXTRA_LOG_POLICY_ALLOW_APKS, mAllowApks);
+                                    EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+                            monitoringExtras = backupManagerService.putMonitoringExtra(
+                                    monitoringExtras,
+                                    EXTRA_LOG_POLICY_ALLOW_APKS, mAllowApks);
                             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                                LOG_EVENT_ID_APK_NOT_INSTALLED,
-                                null,
-                                LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                                monitoringExtras);
+                                    LOG_EVENT_ID_APK_NOT_INSTALLED,
+                                    null,
+                                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                    monitoringExtras);
                         }
 
                         if (policy == RestorePolicy.ACCEPT_IF_APK && !hasApk) {
-                            Slog.i(RefactoredBackupManagerService.TAG, "Cannot restore package " + info.packageName
-                                + " without the matching .apk");
+                            Slog.i(RefactoredBackupManagerService.TAG,
+                                    "Cannot restore package " + info.packageName
+                                            + " without the matching .apk");
                             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                                LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK,
+                                    LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK,
+                                    null,
+                                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                                    backupManagerService.putMonitoringExtra(null,
+                                            EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
+                        }
+                    } else {
+                        Slog.i(RefactoredBackupManagerService.TAG,
+                                "Missing signature on backed-up package "
+                                        + info.packageName);
+                        mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
+                                LOG_EVENT_ID_MISSING_SIGNATURE,
                                 null,
                                 LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
                                 backupManagerService.putMonitoringExtra(null,
-                                    EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
-                        }
-                    } else {
-                        Slog.i(RefactoredBackupManagerService.TAG, "Missing signature on backed-up package "
-                            + info.packageName);
-                        mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                            LOG_EVENT_ID_MISSING_SIGNATURE,
-                            null,
-                            LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                            backupManagerService.putMonitoringExtra(null,
-                                EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
+                                        EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
                     }
                 } else {
-                    Slog.i(RefactoredBackupManagerService.TAG, "Expected package " + info.packageName
-                        + " but restore manifest claims " + manifestPackage);
+                    Slog.i(RefactoredBackupManagerService.TAG,
+                            "Expected package " + info.packageName
+                                    + " but restore manifest claims " + manifestPackage);
                     Bundle monitoringExtras = backupManagerService.putMonitoringExtra(null,
-                        EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+                            EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
                     monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
-                        EXTRA_LOG_MANIFEST_PACKAGE_NAME, manifestPackage);
+                            EXTRA_LOG_MANIFEST_PACKAGE_NAME, manifestPackage);
                     mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                        LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE,
+                            LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE,
+                            null,
+                            LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                            monitoringExtras);
+                }
+            } else {
+                Slog.i(RefactoredBackupManagerService.TAG,
+                        "Unknown restore manifest version " + version
+                                + " for package " + info.packageName);
+                Bundle monitoringExtras = backupManagerService.putMonitoringExtra(null,
+                        EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
+                monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
+                        EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
+                mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
+                        BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_VERSION,
                         null,
                         LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
                         monitoringExtras);
-                }
-            } else {
-                Slog.i(RefactoredBackupManagerService.TAG, "Unknown restore manifest version " + version
-                    + " for package " + info.packageName);
-                Bundle monitoringExtras = backupManagerService.putMonitoringExtra(null,
-                    EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName);
-                monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
-                    EXTRA_LOG_EVENT_PACKAGE_VERSION, version);
-                mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                    BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_VERSION,
-                    null,
-                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                    monitoringExtras);
 
             }
         } catch (NumberFormatException e) {
-            Slog.w(RefactoredBackupManagerService.TAG, "Corrupt restore manifest for package " + info.packageName);
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Corrupt restore manifest for package " + info.packageName);
             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                BackupManagerMonitor.LOG_EVENT_ID_CORRUPT_MANIFEST,
-                null,
-                LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                backupManagerService.putMonitoringExtra(null, EXTRA_LOG_EVENT_PACKAGE_NAME, info.packageName));
+                    BackupManagerMonitor.LOG_EVENT_ID_CORRUPT_MANIFEST,
+                    null,
+                    LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                    backupManagerService.putMonitoringExtra(null, EXTRA_LOG_EVENT_PACKAGE_NAME,
+                            info.packageName));
         } catch (IllegalArgumentException e) {
             Slog.w(RefactoredBackupManagerService.TAG, e.getMessage());
         }
@@ -1098,7 +1162,7 @@
     int extractLine(byte[] buffer, int offset, String[] outStr) throws IOException {
         final int end = buffer.length;
         if (offset >= end) {
-          throw new IOException("Incomplete data");
+            throw new IOException("Incomplete data");
         }
 
         int pos;
@@ -1155,20 +1219,28 @@
             try {
                 // okay, presume we're okay, and extract the various metadata
                 info = new FileMetadata();
-                info.size = extractRadix(block, RefactoredBackupManagerService.TAR_HEADER_OFFSET_FILESIZE,
-                    RefactoredBackupManagerService.TAR_HEADER_LENGTH_FILESIZE, RefactoredBackupManagerService.TAR_HEADER_LONG_RADIX);
-                info.mtime = extractRadix(block, RefactoredBackupManagerService.TAR_HEADER_OFFSET_MODTIME,
-                    RefactoredBackupManagerService.TAR_HEADER_LENGTH_MODTIME, RefactoredBackupManagerService.TAR_HEADER_LONG_RADIX);
-                info.mode = extractRadix(block, RefactoredBackupManagerService.TAR_HEADER_OFFSET_MODE,
-                    RefactoredBackupManagerService.TAR_HEADER_LENGTH_MODE, RefactoredBackupManagerService.TAR_HEADER_LONG_RADIX);
+                info.size = extractRadix(block,
+                        RefactoredBackupManagerService.TAR_HEADER_OFFSET_FILESIZE,
+                        RefactoredBackupManagerService.TAR_HEADER_LENGTH_FILESIZE,
+                        RefactoredBackupManagerService.TAR_HEADER_LONG_RADIX);
+                info.mtime = extractRadix(block,
+                        RefactoredBackupManagerService.TAR_HEADER_OFFSET_MODTIME,
+                        RefactoredBackupManagerService.TAR_HEADER_LENGTH_MODTIME,
+                        RefactoredBackupManagerService.TAR_HEADER_LONG_RADIX);
+                info.mode = extractRadix(block,
+                        RefactoredBackupManagerService.TAR_HEADER_OFFSET_MODE,
+                        RefactoredBackupManagerService.TAR_HEADER_LENGTH_MODE,
+                        RefactoredBackupManagerService.TAR_HEADER_LONG_RADIX);
 
-                info.path = extractString(block, RefactoredBackupManagerService.TAR_HEADER_OFFSET_PATH_PREFIX,
-                    RefactoredBackupManagerService.TAR_HEADER_LENGTH_PATH_PREFIX);
-                String path = extractString(block, RefactoredBackupManagerService.TAR_HEADER_OFFSET_PATH,
-                    RefactoredBackupManagerService.TAR_HEADER_LENGTH_PATH);
+                info.path = extractString(block,
+                        RefactoredBackupManagerService.TAR_HEADER_OFFSET_PATH_PREFIX,
+                        RefactoredBackupManagerService.TAR_HEADER_LENGTH_PATH_PREFIX);
+                String path = extractString(block,
+                        RefactoredBackupManagerService.TAR_HEADER_OFFSET_PATH,
+                        RefactoredBackupManagerService.TAR_HEADER_LENGTH_PATH);
                 if (path.length() > 0) {
                     if (info.path.length() > 0) {
-                      info.path += '/';
+                        info.path += '/';
                     }
                     info.path += path;
                 }
@@ -1184,7 +1256,7 @@
                         gotHeader = readTarHeader(instream, block);
                     }
                     if (!gotHeader) {
-                      throw new IOException("Bad or missing pax header");
+                        throw new IOException("Bad or missing pax header");
                     }
 
                     typeChar = block[RefactoredBackupManagerService.TAR_HEADER_OFFSET_TYPE_CHAR];
@@ -1192,12 +1264,13 @@
 
                 switch (typeChar) {
                     case '0':
-                      info.type = BackupAgent.TYPE_FILE;
-                      break;
+                        info.type = BackupAgent.TYPE_FILE;
+                        break;
                     case '5': {
                         info.type = BackupAgent.TYPE_DIRECTORY;
                         if (info.size != 0) {
-                            Slog.w(RefactoredBackupManagerService.TAG, "Directory entry with nonzero size in header");
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Directory entry with nonzero size in header");
                             info.size = 0;
                         }
                         break;
@@ -1205,12 +1278,14 @@
                     case 0: {
                         // presume EOF
                         if (RefactoredBackupManagerService.MORE_DEBUG) {
-                          Slog.w(RefactoredBackupManagerService.TAG, "Saw type=0 in tar header block, info=" + info);
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Saw type=0 in tar header block, info=" + info);
                         }
                         return null;
                     }
                     default: {
-                        Slog.e(RefactoredBackupManagerService.TAG, "Unknown tar entity type: " + typeChar);
+                        Slog.e(RefactoredBackupManagerService.TAG,
+                                "Unknown tar entity type: " + typeChar);
                         throw new IOException("Unknown entity type " + typeChar);
                     }
                 }
@@ -1219,16 +1294,17 @@
                 //
                 // first: apps/shared/unrecognized
                 if (FullBackup.SHARED_PREFIX.regionMatches(0,
-                    info.path, 0, FullBackup.SHARED_PREFIX.length())) {
+                        info.path, 0, FullBackup.SHARED_PREFIX.length())) {
                     // File in shared storage.  !!! TODO: implement this.
                     info.path = info.path.substring(FullBackup.SHARED_PREFIX.length());
                     info.packageName = RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
                     info.domain = FullBackup.SHARED_STORAGE_TOKEN;
                     if (RefactoredBackupManagerService.DEBUG) {
-                      Slog.i(RefactoredBackupManagerService.TAG, "File in shared storage: " + info.path);
+                        Slog.i(RefactoredBackupManagerService.TAG,
+                                "File in shared storage: " + info.path);
                     }
                 } else if (FullBackup.APPS_PREFIX.regionMatches(0,
-                    info.path, 0, FullBackup.APPS_PREFIX.length())) {
+                        info.path, 0, FullBackup.APPS_PREFIX.length())) {
                     // App content!  Parse out the package name and domain
 
                     // strip the apps/ prefix
@@ -1237,7 +1313,7 @@
                     // extract the package name
                     int slash = info.path.indexOf('/');
                     if (slash < 0) {
-                      throw new IOException("Illegal semantic path in " + info.path);
+                        throw new IOException("Illegal semantic path in " + info.path);
                     }
                     info.packageName = info.path.substring(0, slash);
                     info.path = info.path.substring(slash + 1);
@@ -1245,11 +1321,12 @@
                     // if it's a manifest or metadata payload we're done, otherwise parse
                     // out the domain into which the file will be restored
                     if (!info.path.equals(RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME)
-                        && !info.path.equals(RefactoredBackupManagerService.BACKUP_METADATA_FILENAME)) {
+                            && !info.path.equals(
+                            RefactoredBackupManagerService.BACKUP_METADATA_FILENAME)) {
                         slash = info.path.indexOf('/');
                         if (slash < 0) {
                             throw new IOException("Illegal semantic path in non-manifest "
-                                + info.path);
+                                    + info.path);
                         }
                         info.domain = info.path.substring(0, slash);
                         info.path = info.path.substring(slash + 1);
@@ -1257,7 +1334,8 @@
                 }
             } catch (IOException e) {
                 if (RefactoredBackupManagerService.DEBUG) {
-                    Slog.e(RefactoredBackupManagerService.TAG, "Parse error in header: " + e.getMessage());
+                    Slog.e(RefactoredBackupManagerService.TAG,
+                            "Parse error in header: " + e.getMessage());
                     if (RefactoredBackupManagerService.MORE_DEBUG) {
                         HEXLOG(block);
                     }
@@ -1283,7 +1361,8 @@
             // the app.
             if (info.path.startsWith("no_backup/")) {
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
-                    Slog.i(RefactoredBackupManagerService.TAG, "Dropping no_backup file path " + info.path);
+                    Slog.i(RefactoredBackupManagerService.TAG,
+                            "Dropping no_backup file path " + info.path);
                 }
                 return false;
             }
@@ -1322,26 +1401,28 @@
     // Returns false if EOF is encountered before the requested number of bytes
     // could be read.
     int readExactly(InputStream in, byte[] buffer, int offset, int size)
-        throws IOException {
+            throws IOException {
         if (size <= 0) {
-          throw new IllegalArgumentException("size must be > 0");
+            throw new IllegalArgumentException("size must be > 0");
         }
-      if (RefactoredBackupManagerService.MORE_DEBUG) {
-        Slog.i(RefactoredBackupManagerService.TAG, "  ... readExactly(" + size + ") called");
-      }
+        if (RefactoredBackupManagerService.MORE_DEBUG) {
+            Slog.i(RefactoredBackupManagerService.TAG, "  ... readExactly(" + size + ") called");
+        }
         int soFar = 0;
         while (soFar < size) {
             int nRead = in.read(buffer, offset + soFar, size - soFar);
             if (nRead <= 0) {
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
-                  Slog.w(RefactoredBackupManagerService.TAG, "- wanted exactly " + size + " but got only " + soFar);
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "- wanted exactly " + size + " but got only " + soFar);
                 }
                 break;
             }
             soFar += nRead;
-          if (RefactoredBackupManagerService.MORE_DEBUG) {
-            Slog.v(RefactoredBackupManagerService.TAG, "   + got " + nRead + "; now wanting " + (size - soFar));
-          }
+            if (RefactoredBackupManagerService.MORE_DEBUG) {
+                Slog.v(RefactoredBackupManagerService.TAG,
+                        "   + got " + nRead + "; now wanting " + (size - soFar));
+            }
         }
         return soFar;
     }
@@ -1349,10 +1430,10 @@
     boolean readTarHeader(InputStream instream, byte[] block) throws IOException {
         final int got = readExactly(instream, block, 0, 512);
         if (got == 0) {
-          return false;     // Clean EOF
+            return false;     // Clean EOF
         }
         if (got < 512) {
-          throw new IOException("Unable to read full block header");
+            throw new IOException("Unable to read full block header");
         }
         mBytes += 512;
         return true;
@@ -1360,11 +1441,12 @@
 
     // overwrites 'info' fields based on the pax extended header
     boolean readPaxExtendedHeader(InputStream instream, FileMetadata info)
-        throws IOException {
+            throws IOException {
         // We should never see a pax extended header larger than this
         if (info.size > 32 * 1024) {
-            Slog.w(RefactoredBackupManagerService.TAG, "Suspiciously large pax header size " + info.size
-                + " - aborting");
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Suspiciously large pax header size " + info.size
+                            + " - aborting");
             throw new IOException("Sanity failure: pax header size " + info.size);
         }
 
@@ -1382,7 +1464,7 @@
             // extract the line at 'offset'
             int eol = offset + 1;
             while (eol < contentSize && data[eol] != ' ') {
-              eol++;
+                eol++;
             }
             if (eol >= contentSize) {
                 // error: we just hit EOD looking for the end of the size field
@@ -1394,7 +1476,7 @@
             eol = offset + linelen - 1; // trailing LF
             int value;
             for (value = key + 1; data[value] != '=' && value <= eol; value++) {
-              ;
+                ;
             }
             if (value > eol) {
                 throw new IOException("Invalid pax declaration");
@@ -1411,7 +1493,7 @@
                 info.size = Long.parseLong(valStr);
             } else {
                 if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.i(RefactoredBackupManagerService.TAG, "Unhandled pax key: " + key);
+                    Slog.i(RefactoredBackupManagerService.TAG, "Unhandled pax key: " + key);
                 }
             }
 
@@ -1422,18 +1504,18 @@
     }
 
     long extractRadix(byte[] data, int offset, int maxChars, int radix)
-        throws IOException {
+            throws IOException {
         long value = 0;
         final int end = offset + maxChars;
         for (int i = offset; i < end; i++) {
             final byte b = data[i];
             // Numeric fields in tar can terminate with either NUL or SPC
             if (b == 0 || b == ' ') {
-              break;
+                break;
             }
             if (b < '0' || b > ('0' + radix - 1)) {
                 throw new IOException("Invalid number in header: '" + (char) b
-                    + "' for radix " + radix);
+                        + "' for radix " + radix);
             }
             value = radix * value + (b - '0');
         }
@@ -1445,7 +1527,7 @@
         int eos = offset;
         // tar string fields terminate early with a NUL
         while (eos < end && data[eos] != 0) {
-          eos++;
+            eos++;
         }
         return new String(data, offset, eos - offset, "US-ASCII");
     }
@@ -1455,7 +1537,8 @@
             try {
                 mObserver.onStartRestore();
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full restore observer went away: startRestore");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full restore observer went away: startRestore");
                 mObserver = null;
             }
         }
@@ -1467,7 +1550,8 @@
                 // TODO: use a more user-friendly name string
                 mObserver.onRestorePackage(name);
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full restore observer went away: restorePackage");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full restore observer went away: restorePackage");
                 mObserver = null;
             }
         }
@@ -1478,7 +1562,8 @@
             try {
                 mObserver.onEndRestore();
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full restore observer went away: endRestore");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full restore observer went away: endRestore");
                 mObserver = null;
             }
         }
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 39c001c..94ae76e 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -35,11 +35,13 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Slog;
+
 import com.android.server.backup.FileMetadata;
 import com.android.server.backup.KeyValueAdbRestoreEngine;
 import com.android.server.backup.PackageManagerBackupAgent;
 import com.android.server.backup.RefactoredBackupManagerService;
 import com.android.server.backup.fullbackup.FullBackupObbConnection;
+
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.File;
@@ -57,6 +59,7 @@
 import java.util.HashSet;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.zip.InflaterInputStream;
+
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
 import javax.crypto.CipherInputStream;
@@ -88,7 +91,7 @@
     // of the "restore finished" API asynchronously.  Used by adb restore.
     class RestoreFinishedRunnable implements Runnable {
 
-      final IBackupAgent mAgent;
+        final IBackupAgent mAgent;
         final int mToken;
 
         RestoreFinishedRunnable(IBackupAgent agent, int token) {
@@ -108,21 +111,21 @@
 
     // possible handling states for a given package in the restore dataset
     final HashMap<String, RestorePolicy> mPackagePolicies
-        = new HashMap<>();
+            = new HashMap<>();
 
     // installer package names for each encountered app, derived from the manifests
     final HashMap<String, String> mPackageInstallers = new HashMap<>();
 
     // Signatures for a given package found in its manifest file
     final HashMap<String, Signature[]> mManifestSignatures
-        = new HashMap<>();
+            = new HashMap<>();
 
     // Packages we've already wiped data on when restoring their first file
     final HashSet<String> mClearedPackages = new HashSet<>();
 
     public PerformAdbRestoreTask(RefactoredBackupManagerService backupManagerService,
-        ParcelFileDescriptor fd, String curPassword, String decryptPassword,
-        IFullBackupRestoreObserver observer, AtomicBoolean latch) {
+            ParcelFileDescriptor fd, String curPassword, String decryptPassword,
+            IFullBackupRestoreObserver observer, AtomicBoolean latch) {
         this.backupManagerService = backupManagerService;
         mInputFile = fd;
         mCurrentPassword = curPassword;
@@ -131,7 +134,7 @@
         mLatchObject = latch;
         mAgent = null;
         mPackageManagerBackupAgent = new PackageManagerBackupAgent(
-            backupManagerService.mPackageManager);
+                backupManagerService.mPackageManager);
         mAgentPackage = null;
         mTargetApp = null;
         mObbConnection = new FullBackupObbConnection(backupManagerService);
@@ -144,13 +147,13 @@
 
     class RestoreFileRunnable implements Runnable {
 
-      IBackupAgent mAgent;
+        IBackupAgent mAgent;
         FileMetadata mInfo;
         ParcelFileDescriptor mSocket;
         int mToken;
 
         RestoreFileRunnable(IBackupAgent agent, FileMetadata info,
-            ParcelFileDescriptor socket, int token) throws IOException {
+                ParcelFileDescriptor socket, int token) throws IOException {
             mAgent = agent;
             mInfo = info;
             mToken = token;
@@ -167,8 +170,8 @@
         public void run() {
             try {
                 mAgent.doRestoreFile(mSocket, mInfo.size, mInfo.type,
-                    mInfo.domain, mInfo.path, mInfo.mode, mInfo.mtime,
-                    mToken, backupManagerService.mBackupManagerBinder);
+                        mInfo.domain, mInfo.path, mInfo.mode, mInfo.mtime,
+                        mToken, backupManagerService.mBackupManagerBinder);
             } catch (RemoteException e) {
                 // never happens; this is used strictly for local binder calls
             }
@@ -183,7 +186,8 @@
 
         // Are we able to restore shared-storage data?
         if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
-            mPackagePolicies.put(RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE, RestorePolicy.ACCEPT);
+            mPackagePolicies.put(RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE,
+                    RestorePolicy.ACCEPT);
         }
 
         FileInputStream rawInStream = null;
@@ -191,7 +195,8 @@
         try {
             if (!backupManagerService.backupPasswordMatches(mCurrentPassword)) {
                 if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.w(RefactoredBackupManagerService.TAG, "Backup password mismatch; aborting");
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "Backup password mismatch; aborting");
                 }
                 return;
             }
@@ -210,7 +215,8 @@
             final int headerLen = RefactoredBackupManagerService.BACKUP_FILE_HEADER_MAGIC.length();
             byte[] streamHeader = new byte[headerLen];
             rawDataIn.readFully(streamHeader);
-            byte[] magicBytes = RefactoredBackupManagerService.BACKUP_FILE_HEADER_MAGIC.getBytes("UTF-8");
+            byte[] magicBytes = RefactoredBackupManagerService.BACKUP_FILE_HEADER_MAGIC.getBytes(
+                    "UTF-8");
             if (Arrays.equals(magicBytes, streamHeader)) {
                 // okay, header looks good.  now parse out the rest of the fields.
                 String s = readHeaderLine(rawInStream);
@@ -228,18 +234,19 @@
                         okay = true;
                     } else if (mDecryptPassword != null && mDecryptPassword.length() > 0) {
                         preCompressStream = decodeAesHeaderAndInitialize(s, pbkdf2Fallback,
-                            rawInStream);
+                                rawInStream);
                         if (preCompressStream != null) {
                             okay = true;
                         }
                     } else {
-                      Slog.w(RefactoredBackupManagerService.TAG, "Archive is encrypted but no password given");
+                        Slog.w(RefactoredBackupManagerService.TAG,
+                                "Archive is encrypted but no password given");
                     }
                 } else {
-                  Slog.w(RefactoredBackupManagerService.TAG, "Wrong header version: " + s);
+                    Slog.w(RefactoredBackupManagerService.TAG, "Wrong header version: " + s);
                 }
             } else {
-              Slog.w(RefactoredBackupManagerService.TAG, "Didn't read the right header magic");
+                Slog.w(RefactoredBackupManagerService.TAG, "Didn't read the right header magic");
             }
 
             if (!okay) {
@@ -256,7 +263,8 @@
             } while (didRestore);
 
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Slog.v(RefactoredBackupManagerService.TAG, "Done consuming input tarfile, total bytes=" + mBytes);
+                Slog.v(RefactoredBackupManagerService.TAG,
+                        "Done consuming input tarfile, total bytes=" + mBytes);
             }
         } catch (IOException e) {
             Slog.e(RefactoredBackupManagerService.TAG, "Unable to read restore input");
@@ -266,10 +274,10 @@
 
             try {
                 if (rawDataIn != null) {
-                  rawDataIn.close();
+                    rawDataIn.close();
                 }
                 if (rawInStream != null) {
-                  rawInStream.close();
+                    rawInStream.close();
                 }
                 mInputFile.close();
             } catch (IOException e) {
@@ -292,7 +300,7 @@
         StringBuilder buffer = new StringBuilder(80);
         while ((c = in.read()) >= 0) {
             if (c == '\n') {
-              break;   // consume and discard the newlines
+                break;   // consume and discard the newlines
             }
             buffer.append((char) c);
         }
@@ -300,20 +308,20 @@
     }
 
     InputStream attemptMasterKeyDecryption(String algorithm, byte[] userSalt, byte[] ckSalt,
-        int rounds, String userIvHex, String masterKeyBlobHex, InputStream rawInStream,
-        boolean doLog) {
+            int rounds, String userIvHex, String masterKeyBlobHex, InputStream rawInStream,
+            boolean doLog) {
         InputStream result = null;
 
         try {
             Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
             SecretKey userKey = backupManagerService
-                .buildPasswordKey(algorithm, mDecryptPassword, userSalt,
-                    rounds);
+                    .buildPasswordKey(algorithm, mDecryptPassword, userSalt,
+                            rounds);
             byte[] IV = backupManagerService.hexToByteArray(userIvHex);
             IvParameterSpec ivSpec = new IvParameterSpec(IV);
             c.init(Cipher.DECRYPT_MODE,
-                new SecretKeySpec(userKey.getEncoded(), "AES"),
-                ivSpec);
+                    new SecretKeySpec(userKey.getEncoded(), "AES"),
+                    ivSpec);
             byte[] mkCipher = backupManagerService.hexToByteArray(masterKeyBlobHex);
             byte[] mkBlob = c.doFinal(mkCipher);
 
@@ -325,28 +333,29 @@
             // then the master key itself
             len = mkBlob[offset++];
             byte[] mk = Arrays.copyOfRange(mkBlob,
-                offset, offset + len);
+                    offset, offset + len);
             offset += len;
             // and finally the master key checksum hash
             len = mkBlob[offset++];
             byte[] mkChecksum = Arrays.copyOfRange(mkBlob,
-                offset, offset + len);
+                    offset, offset + len);
 
             // now validate the decrypted master key against the checksum
-            byte[] calculatedCk = backupManagerService.makeKeyChecksum(algorithm, mk, ckSalt, rounds);
+            byte[] calculatedCk = backupManagerService.makeKeyChecksum(algorithm, mk, ckSalt,
+                    rounds);
             if (Arrays.equals(calculatedCk, mkChecksum)) {
                 ivSpec = new IvParameterSpec(IV);
                 c.init(Cipher.DECRYPT_MODE,
-                    new SecretKeySpec(mk, "AES"),
-                    ivSpec);
+                        new SecretKeySpec(mk, "AES"),
+                        ivSpec);
                 // Only if all of the above worked properly will 'result' be assigned
                 result = new CipherInputStream(rawInStream, c);
             } else if (doLog) {
-              Slog.w(RefactoredBackupManagerService.TAG, "Incorrect password");
+                Slog.w(RefactoredBackupManagerService.TAG, "Incorrect password");
             }
         } catch (InvalidAlgorithmParameterException e) {
             if (doLog) {
-              Slog.e(RefactoredBackupManagerService.TAG, "Needed parameter spec unavailable!", e);
+                Slog.e(RefactoredBackupManagerService.TAG, "Needed parameter spec unavailable!", e);
             }
         } catch (BadPaddingException e) {
             // This case frequently occurs when the wrong password is used to decrypt
@@ -354,23 +363,24 @@
             // used in the checksum failure log in order to avoid providing additional
             // information to an attacker.
             if (doLog) {
-              Slog.w(RefactoredBackupManagerService.TAG, "Incorrect password");
+                Slog.w(RefactoredBackupManagerService.TAG, "Incorrect password");
             }
         } catch (IllegalBlockSizeException e) {
             if (doLog) {
-              Slog.w(RefactoredBackupManagerService.TAG, "Invalid block size in master key");
+                Slog.w(RefactoredBackupManagerService.TAG, "Invalid block size in master key");
             }
         } catch (NoSuchAlgorithmException e) {
             if (doLog) {
-              Slog.e(RefactoredBackupManagerService.TAG, "Needed decryption algorithm unavailable!");
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Needed decryption algorithm unavailable!");
             }
         } catch (NoSuchPaddingException e) {
             if (doLog) {
-              Slog.e(RefactoredBackupManagerService.TAG, "Needed padding mechanism unavailable!");
+                Slog.e(RefactoredBackupManagerService.TAG, "Needed padding mechanism unavailable!");
             }
         } catch (InvalidKeyException e) {
             if (doLog) {
-              Slog.w(RefactoredBackupManagerService.TAG, "Illegal password; aborting");
+                Slog.w(RefactoredBackupManagerService.TAG, "Illegal password; aborting");
             }
         }
 
@@ -378,7 +388,7 @@
     }
 
     InputStream decodeAesHeaderAndInitialize(String encryptionName, boolean pbkdf2Fallback,
-        InputStream rawInStream) {
+            InputStream rawInStream) {
         InputStream result = null;
         try {
             if (encryptionName.equals(RefactoredBackupManagerService.ENCRYPTION_ALGORITHM_NAME)) {
@@ -395,15 +405,17 @@
                 String masterKeyBlobHex = readHeaderLine(rawInStream); // 9
 
                 // decrypt the master key blob
-                result = attemptMasterKeyDecryption(RefactoredBackupManagerService.PBKDF_CURRENT, userSalt, ckSalt,
-                    rounds, userIvHex, masterKeyBlobHex, rawInStream, false);
+                result = attemptMasterKeyDecryption(RefactoredBackupManagerService.PBKDF_CURRENT,
+                        userSalt, ckSalt,
+                        rounds, userIvHex, masterKeyBlobHex, rawInStream, false);
                 if (result == null && pbkdf2Fallback) {
                     result = attemptMasterKeyDecryption(
-                        RefactoredBackupManagerService.PBKDF_FALLBACK, userSalt, ckSalt,
-                        rounds, userIvHex, masterKeyBlobHex, rawInStream, true);
+                            RefactoredBackupManagerService.PBKDF_FALLBACK, userSalt, ckSalt,
+                            rounds, userIvHex, masterKeyBlobHex, rawInStream, true);
                 }
             } else {
-              Slog.w(RefactoredBackupManagerService.TAG, "Unsupported encryption method: " + encryptionName);
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "Unsupported encryption method: " + encryptionName);
             }
         } catch (NumberFormatException e) {
             Slog.w(RefactoredBackupManagerService.TAG, "Can't parse restore data header");
@@ -435,7 +447,8 @@
                     // and let the observer know we're considering a new app.
                     if (mAgent != null) {
                         if (RefactoredBackupManagerService.DEBUG) {
-                          Slog.d(RefactoredBackupManagerService.TAG, "Saw new package; finalizing old one");
+                            Slog.d(RefactoredBackupManagerService.TAG,
+                                    "Saw new package; finalizing old one");
                         }
                         // Now we're really done
                         tearDownPipes();
@@ -453,7 +466,8 @@
                     // input file
                     skipTarPadding(info.size, instream);
                     sendOnRestorePackage(pkg);
-                } else if (info.path.equals(RefactoredBackupManagerService.BACKUP_METADATA_FILENAME)) {
+                } else if (info.path.equals(
+                        RefactoredBackupManagerService.BACKUP_METADATA_FILENAME)) {
                     // Metadata blobs!
                     readMetadata(info, instream);
                     skipTarPadding(info.size, instream);
@@ -472,15 +486,16 @@
                             // see MUST be the apk.
                             if (info.domain.equals(FullBackup.APK_TREE_TOKEN)) {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "APK file; installing");
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "APK file; installing");
                                 }
                                 // Try to install the app.
                                 String installerName = mPackageInstallers.get(pkg);
                                 okay = installApk(info, installerName, instream);
                                 // good to go; promote to ACCEPT
                                 mPackagePolicies.put(pkg, (okay)
-                                    ? RestorePolicy.ACCEPT
-                                    : RestorePolicy.IGNORE);
+                                        ? RestorePolicy.ACCEPT
+                                        : RestorePolicy.IGNORE);
                                 // At this point we've consumed this file entry
                                 // ourselves, so just strip the tar footer and
                                 // go on to the next file in the input stream
@@ -497,7 +512,8 @@
                         case ACCEPT:
                             if (info.domain.equals(FullBackup.APK_TREE_TOKEN)) {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "apk present but ACCEPT");
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "apk present but ACCEPT");
                                 }
                                 // we can take the data without the apk, so we
                                 // *want* to do so.  skip the apk by declaring this
@@ -511,7 +527,8 @@
                             // Something has gone dreadfully wrong when determining
                             // the restore policy from the manifest.  Ignore the
                             // rest of this package's data.
-                            Slog.e(RefactoredBackupManagerService.TAG, "Invalid policy from manifest");
+                            Slog.e(RefactoredBackupManagerService.TAG,
+                                    "Invalid policy from manifest");
                             okay = false;
                             mPackagePolicies.put(pkg, RestorePolicy.IGNORE);
                             break;
@@ -520,7 +537,8 @@
                     // The path needs to be canonical
                     if (info.path.contains("..") || info.path.contains("//")) {
                         if (RefactoredBackupManagerService.MORE_DEBUG) {
-                            Slog.w(RefactoredBackupManagerService.TAG, "Dropping invalid path " + info.path);
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Dropping invalid path " + info.path);
                         }
                         okay = false;
                     }
@@ -528,15 +546,18 @@
                     // If the policy is satisfied, go ahead and set up to pipe the
                     // data to the agent.
                     if (RefactoredBackupManagerService.DEBUG && okay && mAgent != null) {
-                        Slog.i(RefactoredBackupManagerService.TAG, "Reusing existing agent instance");
+                        Slog.i(RefactoredBackupManagerService.TAG,
+                                "Reusing existing agent instance");
                     }
                     if (okay && mAgent == null) {
                         if (RefactoredBackupManagerService.DEBUG) {
-                          Slog.d(RefactoredBackupManagerService.TAG, "Need to launch agent for " + pkg);
+                            Slog.d(RefactoredBackupManagerService.TAG,
+                                    "Need to launch agent for " + pkg);
                         }
 
                         try {
-                            mTargetApp = backupManagerService.mPackageManager.getApplicationInfo(pkg, 0);
+                            mTargetApp = backupManagerService.mPackageManager.getApplicationInfo(
+                                    pkg, 0);
 
                             // If we haven't sent any data to this app yet, we probably
                             // need to clear it first.  Check that.
@@ -546,28 +567,29 @@
                                 // restore.
                                 if (mTargetApp.backupAgentName == null) {
                                     if (RefactoredBackupManagerService.DEBUG) {
-                                      Slog.d(RefactoredBackupManagerService.TAG,
-                                          "Clearing app data preparatory to full restore");
+                                        Slog.d(RefactoredBackupManagerService.TAG,
+                                                "Clearing app data preparatory to full restore");
                                     }
                                     backupManagerService.clearApplicationDataSynchronous(pkg);
                                 } else {
                                     if (RefactoredBackupManagerService.DEBUG) {
-                                      Slog.d(RefactoredBackupManagerService.TAG, "backup agent ("
-                                          + mTargetApp.backupAgentName + ") => no clear");
+                                        Slog.d(RefactoredBackupManagerService.TAG, "backup agent ("
+                                                + mTargetApp.backupAgentName + ") => no clear");
                                     }
                                 }
                                 mClearedPackages.add(pkg);
                             } else {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG,
-                                      "We've initialized this app already; no clear required");
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "We've initialized this app already; no clear "
+                                                    + "required");
                                 }
                             }
 
                             // All set; now set up the IPC and launch the agent
                             setUpPipes();
                             mAgent = backupManagerService.bindToAgentSynchronous(mTargetApp,
-                                ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL);
+                                    ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL);
                             mAgentPackage = pkg;
                         } catch (IOException e) {
                             // fall through to error handling
@@ -577,7 +599,8 @@
 
                         if (mAgent == null) {
                             if (RefactoredBackupManagerService.DEBUG) {
-                              Slog.d(RefactoredBackupManagerService.TAG, "Unable to create agent for " + pkg);
+                                Slog.d(RefactoredBackupManagerService.TAG,
+                                        "Unable to create agent for " + pkg);
                             }
                             okay = false;
                             tearDownPipes();
@@ -589,7 +612,7 @@
                     // should never happen but a little paranoia here won't go amiss.
                     if (okay && !pkg.equals(mAgentPackage)) {
                         Slog.e(RefactoredBackupManagerService.TAG, "Restoring data for " + pkg
-                            + " but agent is for " + mAgentPackage);
+                                + " but agent is for " + mAgentPackage);
                         okay = false;
                     }
 
@@ -603,55 +626,65 @@
                         final int token = backupManagerService.generateRandomIntegerToken();
                         try {
                             backupManagerService
-                                .prepareOperationTimeout(token, RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL, null,
-                                    RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
+                                    .prepareOperationTimeout(token,
+                                            RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL,
+                                            null,
+                                            RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
                             if (FullBackup.OBB_TREE_TOKEN.equals(info.domain)) {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "Restoring OBB file for " + pkg
-                                      + " : " + info.path);
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "Restoring OBB file for " + pkg
+                                                    + " : " + info.path);
                                 }
                                 mObbConnection.restoreObbFile(pkg, mPipes[0],
-                                    info.size, info.type, info.path, info.mode,
-                                    info.mtime, token, backupManagerService.mBackupManagerBinder);
+                                        info.size, info.type, info.path, info.mode,
+                                        info.mtime, token,
+                                        backupManagerService.mBackupManagerBinder);
                             } else if (FullBackup.KEY_VALUE_DATA_TOKEN.equals(info.domain)) {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "Restoring key-value file for " + pkg
-                                      + " : " + info.path);
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "Restoring key-value file for " + pkg
+                                                    + " : " + info.path);
                                 }
                                 KeyValueAdbRestoreEngine restoreEngine =
-                                    new KeyValueAdbRestoreEngine(
-                                        backupManagerService,
-                                        backupManagerService.mDataDir, info, mPipes[0], mAgent, token);
+                                        new KeyValueAdbRestoreEngine(
+                                                backupManagerService,
+                                                backupManagerService.mDataDir, info, mPipes[0],
+                                                mAgent, token);
                                 new Thread(restoreEngine, "restore-key-value-runner").start();
                             } else {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.d(RefactoredBackupManagerService.TAG, "Invoking agent to restore file "
-                                      + info.path);
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "Invoking agent to restore file "
+                                                    + info.path);
                                 }
                                 // fire up the app's agent listening on the socket.  If
                                 // the agent is running in the system process we can't
                                 // just invoke it asynchronously, so we provide a thread
                                 // for it here.
                                 if (mTargetApp.processName.equals("system")) {
-                                    Slog.d(RefactoredBackupManagerService.TAG, "system process agent - spinning a thread");
+                                    Slog.d(RefactoredBackupManagerService.TAG,
+                                            "system process agent - spinning a thread");
                                     RestoreFileRunnable runner = new RestoreFileRunnable(
-                                        mAgent, info, mPipes[0], token);
+                                            mAgent, info, mPipes[0], token);
                                     new Thread(runner, "restore-sys-runner").start();
                                 } else {
                                     mAgent.doRestoreFile(mPipes[0], info.size, info.type,
-                                        info.domain, info.path, info.mode, info.mtime,
-                                        token, backupManagerService.mBackupManagerBinder);
+                                            info.domain, info.path, info.mode, info.mtime,
+                                            token, backupManagerService.mBackupManagerBinder);
                                 }
                             }
                         } catch (IOException e) {
                             // couldn't dup the socket for a process-local restore
-                            Slog.d(RefactoredBackupManagerService.TAG, "Couldn't establish restore");
+                            Slog.d(RefactoredBackupManagerService.TAG,
+                                    "Couldn't establish restore");
                             agentSuccess = false;
                             okay = false;
                         } catch (RemoteException e) {
                             // whoops, remote entity went away.  We'll eat the content
                             // ourselves, then, and not copy it over.
-                            Slog.e(RefactoredBackupManagerService.TAG, "Agent crashed during full restore");
+                            Slog.e(RefactoredBackupManagerService.TAG,
+                                    "Agent crashed during full restore");
                             agentSuccess = false;
                             okay = false;
                         }
@@ -660,16 +693,16 @@
                         if (okay) {
                             boolean pipeOkay = true;
                             FileOutputStream pipe = new FileOutputStream(
-                                mPipes[1].getFileDescriptor());
+                                    mPipes[1].getFileDescriptor());
                             while (toCopy > 0) {
                                 int toRead = (toCopy > buffer.length)
-                                    ? buffer.length : (int) toCopy;
+                                        ? buffer.length : (int) toCopy;
                                 int nRead = instream.read(buffer, 0, toRead);
                                 if (nRead >= 0) {
-                                  mBytes += nRead;
+                                    mBytes += nRead;
                                 }
                                 if (nRead <= 0) {
-                                  break;
+                                    break;
                                 }
                                 toCopy -= nRead;
 
@@ -679,7 +712,8 @@
                                     try {
                                         pipe.write(buffer, 0, nRead);
                                     } catch (IOException e) {
-                                        Slog.e(RefactoredBackupManagerService.TAG, "Failed to write to restore pipe", e);
+                                        Slog.e(RefactoredBackupManagerService.TAG,
+                                                "Failed to write to restore pipe", e);
                                         pipeOkay = false;
                                     }
                                 }
@@ -699,10 +733,10 @@
                         if (!agentSuccess) {
                             if (RefactoredBackupManagerService.DEBUG) {
                                 Slog.d(RefactoredBackupManagerService.TAG,
-                                    "Agent failure restoring " + pkg + "; now ignoring");
+                                        "Agent failure restoring " + pkg + "; now ignoring");
                             }
                             backupManagerService.mBackupHandler.removeMessages(
-                                RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
+                                    RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
                             tearDownPipes();
                             tearDownAgent(mTargetApp, false);
                             mPackagePolicies.put(pkg, RestorePolicy.IGNORE);
@@ -714,18 +748,18 @@
                     // reading and discarding this file.
                     if (!okay) {
                         if (RefactoredBackupManagerService.DEBUG) {
-                          Slog.d(RefactoredBackupManagerService.TAG, "[discarding file content]");
+                            Slog.d(RefactoredBackupManagerService.TAG, "[discarding file content]");
                         }
                         long bytesToConsume = (info.size + 511) & ~511;
                         while (bytesToConsume > 0) {
                             int toRead = (bytesToConsume > buffer.length)
-                                ? buffer.length : (int) bytesToConsume;
+                                    ? buffer.length : (int) bytesToConsume;
                             long nRead = instream.read(buffer, 0, toRead);
                             if (nRead >= 0) {
-                              mBytes += nRead;
+                                mBytes += nRead;
                             }
                             if (nRead <= 0) {
-                              break;
+                                break;
                             }
                             bytesToConsume -= nRead;
                         }
@@ -734,7 +768,8 @@
             }
         } catch (IOException e) {
             if (RefactoredBackupManagerService.DEBUG) {
-              Slog.w(RefactoredBackupManagerService.TAG, "io exception on restore socket read", e);
+                Slog.w(RefactoredBackupManagerService.TAG, "io exception on restore socket read",
+                        e);
             }
             // treat as EOF
             info = null;
@@ -768,13 +803,16 @@
                 if (doRestoreFinished) {
                     final int token = backupManagerService.generateRandomIntegerToken();
                     final AdbRestoreFinishedLatch latch = new AdbRestoreFinishedLatch(
-                        backupManagerService, token);
+                            backupManagerService, token);
                     backupManagerService
-                        .prepareOperationTimeout(token, RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL, latch,
-                            RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
+                            .prepareOperationTimeout(token,
+                                    RefactoredBackupManagerService.TIMEOUT_FULL_BACKUP_INTERVAL,
+                                    latch,
+                                    RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
                     if (mTargetApp.processName.equals("system")) {
                         if (RefactoredBackupManagerService.MORE_DEBUG) {
-                            Slog.d(RefactoredBackupManagerService.TAG, "system agent - restoreFinished on thread");
+                            Slog.d(RefactoredBackupManagerService.TAG,
+                                    "system agent - restoreFinished on thread");
                         }
                         Runnable runner = new RestoreFinishedRunnable(mAgent, token);
                         new Thread(runner, "restore-sys-finished-runner").start();
@@ -792,14 +830,16 @@
                 // !!! We hardcode the confirmation UI's package name here rather than use a
                 //     manifest flag!  TODO something less direct.
                 if (app.uid >= Process.FIRST_APPLICATION_UID
-                    && !app.packageName.equals("com.android.backupconfirm")) {
+                        && !app.packageName.equals("com.android.backupconfirm")) {
                     if (RefactoredBackupManagerService.DEBUG) {
-                      Slog.d(RefactoredBackupManagerService.TAG, "Killing host process");
+                        Slog.d(RefactoredBackupManagerService.TAG, "Killing host process");
                     }
-                    backupManagerService.mActivityManager.killApplicationProcess(app.processName, app.uid);
+                    backupManagerService.mActivityManager.killApplicationProcess(app.processName,
+                            app.uid);
                 } else {
                     if (RefactoredBackupManagerService.DEBUG) {
-                      Slog.d(RefactoredBackupManagerService.TAG, "Not killing after full restore");
+                        Slog.d(RefactoredBackupManagerService.TAG,
+                                "Not killing after full restore");
                     }
                 }
             } catch (RemoteException e) {
@@ -811,7 +851,7 @@
 
     class RestoreInstallObserver extends PackageInstallObserver {
 
-      final AtomicBoolean mDone = new AtomicBoolean();
+        final AtomicBoolean mDone = new AtomicBoolean();
         String mPackageName;
         int mResult;
 
@@ -838,7 +878,7 @@
 
         @Override
         public void onPackageInstalled(String packageName, int returnCode,
-            String msg, Bundle extras) {
+                String msg, Bundle extras) {
             synchronized (mDone) {
                 mResult = returnCode;
                 mPackageName = packageName;
@@ -850,7 +890,7 @@
 
     class RestoreDeleteObserver extends IPackageDeleteObserver.Stub {
 
-      final AtomicBoolean mDone = new AtomicBoolean();
+        final AtomicBoolean mDone = new AtomicBoolean();
         int mResult;
 
         public void reset() {
@@ -887,7 +927,8 @@
         boolean okay = true;
 
         if (RefactoredBackupManagerService.DEBUG) {
-          Slog.d(RefactoredBackupManagerService.TAG, "Installing from backup: " + info.packageName);
+            Slog.d(RefactoredBackupManagerService.TAG,
+                    "Installing from backup: " + info.packageName);
         }
 
         // The file content is an .apk file.  Copy it out to a staging location and
@@ -901,7 +942,7 @@
                 long toRead = (buffer.length < size) ? buffer.length : size;
                 int didRead = instream.read(buffer, 0, (int) toRead);
                 if (didRead >= 0) {
-                  mBytes += didRead;
+                    mBytes += didRead;
                 }
                 apkStream.write(buffer, 0, didRead);
                 size -= didRead;
@@ -915,8 +956,8 @@
             Uri packageUri = Uri.fromFile(apkFile);
             mInstallObserver.reset();
             backupManagerService.mPackageManager.installPackage(packageUri, mInstallObserver,
-                PackageManager.INSTALL_REPLACE_EXISTING | PackageManager.INSTALL_FROM_ADB,
-                installerPackage);
+                    PackageManager.INSTALL_REPLACE_EXISTING | PackageManager.INSTALL_FROM_ADB,
+                    installerPackage);
             mInstallObserver.waitForCompletion();
 
             if (mInstallObserver.getResult() != PackageManager.INSTALL_SUCCEEDED) {
@@ -930,20 +971,24 @@
                 // Okay, the install succeeded.  Make sure it was the right app.
                 boolean uninstall = false;
                 if (!mInstallObserver.mPackageName.equals(info.packageName)) {
-                    Slog.w(RefactoredBackupManagerService.TAG, "Restore stream claimed to include apk for "
-                        + info.packageName + " but apk was really "
-                        + mInstallObserver.mPackageName);
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "Restore stream claimed to include apk for "
+                                    + info.packageName + " but apk was really "
+                                    + mInstallObserver.mPackageName);
                     // delete the package we just put in place; it might be fraudulent
                     okay = false;
                     uninstall = true;
                 } else {
                     try {
-                        PackageInfo pkg = backupManagerService.mPackageManager.getPackageInfo(info.packageName,
-                            PackageManager.GET_SIGNATURES);
+                        PackageInfo pkg = backupManagerService.mPackageManager.getPackageInfo(
+                                info.packageName,
+                                PackageManager.GET_SIGNATURES);
                         if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP)
-                            == 0) {
-                            Slog.w(RefactoredBackupManagerService.TAG, "Restore stream contains apk of package "
-                                + info.packageName + " but it disallows backup/restore");
+                                == 0) {
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Restore stream contains apk of package "
+                                            + info.packageName
+                                            + " but it disallows backup/restore");
                             okay = false;
                         } else {
                             // So far so good -- do the signatures match the manifest?
@@ -952,21 +997,24 @@
                                 // If this is a system-uid app without a declared backup agent,
                                 // don't restore any of the file data.
                                 if ((pkg.applicationInfo.uid < Process.FIRST_APPLICATION_UID)
-                                    && (pkg.applicationInfo.backupAgentName == null)) {
-                                    Slog.w(RefactoredBackupManagerService.TAG, "Installed app " + info.packageName
-                                        + " has restricted uid and no agent");
+                                        && (pkg.applicationInfo.backupAgentName == null)) {
+                                    Slog.w(RefactoredBackupManagerService.TAG,
+                                            "Installed app " + info.packageName
+                                                    + " has restricted uid and no agent");
                                     okay = false;
                                 }
                             } else {
-                                Slog.w(RefactoredBackupManagerService.TAG, "Installed app " + info.packageName
-                                    + " signatures do not match restore manifest");
+                                Slog.w(RefactoredBackupManagerService.TAG,
+                                        "Installed app " + info.packageName
+                                                + " signatures do not match restore manifest");
                                 okay = false;
                                 uninstall = true;
                             }
                         }
                     } catch (NameNotFoundException e) {
-                        Slog.w(RefactoredBackupManagerService.TAG, "Install of package " + info.packageName
-                            + " succeeded but now not found");
+                        Slog.w(RefactoredBackupManagerService.TAG,
+                                "Install of package " + info.packageName
+                                        + " succeeded but now not found");
                         okay = false;
                     }
                 }
@@ -975,13 +1023,15 @@
                 // that we just installed.
                 if (uninstall) {
                     mDeleteObserver.reset();
-                    backupManagerService.mPackageManager.deletePackage(mInstallObserver.mPackageName,
-                        mDeleteObserver, 0);
+                    backupManagerService.mPackageManager.deletePackage(
+                            mInstallObserver.mPackageName,
+                            mDeleteObserver, 0);
                     mDeleteObserver.waitForCompletion();
                 }
             }
         } catch (IOException e) {
-            Slog.e(RefactoredBackupManagerService.TAG, "Unable to transcribe restored apk for install");
+            Slog.e(RefactoredBackupManagerService.TAG,
+                    "Unable to transcribe restored apk for install");
             okay = false;
         } finally {
             apkFile.delete();
@@ -1000,7 +1050,7 @@
             if (readExactly(instream, buffer, 0, needed) == needed) {
                 mBytes += needed;
             } else {
-              throw new IOException("Unexpected EOF in padding");
+                throw new IOException("Unexpected EOF in padding");
             }
         }
     }
@@ -1016,7 +1066,7 @@
         if (readExactly(instream, buffer, 0, (int) info.size) == info.size) {
             mBytes += info.size;
         } else {
-          throw new IOException("Unexpected EOF in widget data");
+            throw new IOException("Unexpected EOF in widget data");
         }
 
         String[] str = new String[1];
@@ -1029,20 +1079,21 @@
                 // Data checks out -- the rest of the buffer is a concatenation of
                 // binary blobs as described in the comment at writeAppWidgetData()
                 ByteArrayInputStream bin = new ByteArrayInputStream(buffer,
-                    offset, buffer.length - offset);
+                        offset, buffer.length - offset);
                 DataInputStream in = new DataInputStream(bin);
                 while (bin.available() > 0) {
                     int token = in.readInt();
                     int size = in.readInt();
                     if (size > 64 * 1024) {
                         throw new IOException("Datum "
-                            + Integer.toHexString(token)
-                            + " too big; corrupt? size=" + info.size);
+                                + Integer.toHexString(token)
+                                + " too big; corrupt? size=" + info.size);
                     }
                     switch (token) {
                         case RefactoredBackupManagerService.BACKUP_WIDGET_METADATA_TOKEN: {
                             if (RefactoredBackupManagerService.MORE_DEBUG) {
-                                Slog.i(RefactoredBackupManagerService.TAG, "Got widget metadata for " + info.packageName);
+                                Slog.i(RefactoredBackupManagerService.TAG,
+                                        "Got widget metadata for " + info.packageName);
                             }
                             mWidgetData = new byte[size];
                             in.read(mWidgetData);
@@ -1051,8 +1102,8 @@
                         default: {
                             if (RefactoredBackupManagerService.DEBUG) {
                                 Slog.i(RefactoredBackupManagerService.TAG, "Ignoring metadata blob "
-                                    + Integer.toHexString(token)
-                                    + " for " + info.packageName);
+                                        + Integer.toHexString(token)
+                                        + " for " + info.packageName);
                             }
                             in.skipBytes(size);
                             break;
@@ -1060,8 +1111,9 @@
                     }
                 }
             } else {
-                Slog.w(RefactoredBackupManagerService.TAG, "Metadata mismatch: package " + info.packageName
-                    + " but widget data for " + pkg);
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "Metadata mismatch: package " + info.packageName
+                                + " but widget data for " + pkg);
             }
         } else {
             Slog.w(RefactoredBackupManagerService.TAG, "Unsupported metadata version " + version);
@@ -1070,7 +1122,7 @@
 
     // Returns a policy constant; takes a buffer arg to reduce memory churn
     RestorePolicy readAppManifest(FileMetadata info, InputStream instream)
-        throws IOException {
+            throws IOException {
         // Fail on suspiciously large manifest files
         if (info.size > 64 * 1024) {
             throw new IOException("Restore manifest too big; corrupt? size=" + info.size);
@@ -1080,7 +1132,7 @@
         if (readExactly(instream, buffer, 0, (int) info.size) == info.size) {
             mBytes += info.size;
         } else {
-          throw new IOException("Unexpected EOF in manifest");
+            throw new IOException("Unexpected EOF in manifest");
         }
 
         RestorePolicy policy = RestorePolicy.IGNORE;
@@ -1117,16 +1169,17 @@
 
                         // Okay, got the manifest info we need...
                         try {
-                            PackageInfo pkgInfo = backupManagerService.mPackageManager.getPackageInfo(
-                                info.packageName, PackageManager.GET_SIGNATURES);
+                            PackageInfo pkgInfo =
+                                    backupManagerService.mPackageManager.getPackageInfo(
+                                            info.packageName, PackageManager.GET_SIGNATURES);
                             // Fall through to IGNORE if the app explicitly disallows backup
                             final int flags = pkgInfo.applicationInfo.flags;
                             if ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
                                 // Restore system-uid-space packages only if they have
                                 // defined a custom backup agent
                                 if ((pkgInfo.applicationInfo.uid
-                                    >= Process.FIRST_APPLICATION_UID)
-                                    || (pkgInfo.applicationInfo.backupAgentName != null)) {
+                                        >= Process.FIRST_APPLICATION_UID)
+                                        || (pkgInfo.applicationInfo.backupAgentName != null)) {
                                     // Verify signatures against any installed version; if they
                                     // don't match, then we fall though and ignore the data.  The
                                     // signatureMatch() method explicitly ignores the signature
@@ -1134,36 +1187,44 @@
                                     // such packages are signed with the platform cert instead of
                                     // the app developer's cert, so they're different on every
                                     // device.
-                                    if (RefactoredBackupManagerService.signaturesMatch(sigs, pkgInfo)) {
+                                    if (RefactoredBackupManagerService.signaturesMatch(sigs,
+                                            pkgInfo)) {
                                         if ((pkgInfo.applicationInfo.flags
-                                            & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
+                                                & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) != 0) {
                                             Slog.i(RefactoredBackupManagerService.TAG,
-                                                "Package has restoreAnyVersion; taking data");
+                                                    "Package has restoreAnyVersion; taking data");
                                             policy = RestorePolicy.ACCEPT;
                                         } else if (pkgInfo.versionCode >= version) {
-                                            Slog.i(RefactoredBackupManagerService.TAG, "Sig + version match; taking data");
+                                            Slog.i(RefactoredBackupManagerService.TAG,
+                                                    "Sig + version match; taking data");
                                             policy = RestorePolicy.ACCEPT;
                                         } else {
                                             // The data is from a newer version of the app than
                                             // is presently installed.  That means we can only
                                             // use it if the matching apk is also supplied.
-                                            Slog.d(RefactoredBackupManagerService.TAG, "Data version " + version
-                                                + " is newer than installed version "
-                                                + pkgInfo.versionCode + " - requiring apk");
+                                            Slog.d(RefactoredBackupManagerService.TAG,
+                                                    "Data version " + version
+                                                            + " is newer than installed version "
+                                                            + pkgInfo.versionCode
+                                                            + " - requiring apk");
                                             policy = RestorePolicy.ACCEPT_IF_APK;
                                         }
                                     } else {
-                                        Slog.w(RefactoredBackupManagerService.TAG, "Restore manifest signatures do not match "
-                                            + "installed application for " + info.packageName);
+                                        Slog.w(RefactoredBackupManagerService.TAG,
+                                                "Restore manifest signatures do not match "
+                                                        + "installed application for "
+                                                        + info.packageName);
                                     }
                                 } else {
-                                    Slog.w(RefactoredBackupManagerService.TAG, "Package " + info.packageName
-                                        + " is system level with no agent");
+                                    Slog.w(RefactoredBackupManagerService.TAG,
+                                            "Package " + info.packageName
+                                                    + " is system level with no agent");
                                 }
                             } else {
                                 if (RefactoredBackupManagerService.DEBUG) {
-                                  Slog.i(RefactoredBackupManagerService.TAG, "Restore manifest from "
-                                      + info.packageName + " but allowBackup=false");
+                                    Slog.i(RefactoredBackupManagerService.TAG,
+                                            "Restore manifest from "
+                                                    + info.packageName + " but allowBackup=false");
                                 }
                             }
                         } catch (NameNotFoundException e) {
@@ -1171,30 +1232,36 @@
                             // the restore properly only if the dataset provides the
                             // apk file and we can successfully install it.
                             if (RefactoredBackupManagerService.DEBUG) {
-                              Slog.i(RefactoredBackupManagerService.TAG, "Package " + info.packageName
-                                  + " not installed; requiring apk in dataset");
+                                Slog.i(RefactoredBackupManagerService.TAG,
+                                        "Package " + info.packageName
+                                                + " not installed; requiring apk in dataset");
                             }
                             policy = RestorePolicy.ACCEPT_IF_APK;
                         }
 
                         if (policy == RestorePolicy.ACCEPT_IF_APK && !hasApk) {
-                            Slog.i(RefactoredBackupManagerService.TAG, "Cannot restore package " + info.packageName
-                                + " without the matching .apk");
+                            Slog.i(RefactoredBackupManagerService.TAG,
+                                    "Cannot restore package " + info.packageName
+                                            + " without the matching .apk");
                         }
                     } else {
-                        Slog.i(RefactoredBackupManagerService.TAG, "Missing signature on backed-up package "
-                            + info.packageName);
+                        Slog.i(RefactoredBackupManagerService.TAG,
+                                "Missing signature on backed-up package "
+                                        + info.packageName);
                     }
                 } else {
-                    Slog.i(RefactoredBackupManagerService.TAG, "Expected package " + info.packageName
-                        + " but restore manifest claims " + manifestPackage);
+                    Slog.i(RefactoredBackupManagerService.TAG,
+                            "Expected package " + info.packageName
+                                    + " but restore manifest claims " + manifestPackage);
                 }
             } else {
-                Slog.i(RefactoredBackupManagerService.TAG, "Unknown restore manifest version " + version
-                    + " for package " + info.packageName);
+                Slog.i(RefactoredBackupManagerService.TAG,
+                        "Unknown restore manifest version " + version
+                                + " for package " + info.packageName);
             }
         } catch (NumberFormatException e) {
-            Slog.w(RefactoredBackupManagerService.TAG, "Corrupt restore manifest for package " + info.packageName);
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Corrupt restore manifest for package " + info.packageName);
         } catch (IllegalArgumentException e) {
             Slog.w(RefactoredBackupManagerService.TAG, e.getMessage());
         }
@@ -1207,7 +1274,7 @@
     int extractLine(byte[] buffer, int offset, String[] outStr) throws IOException {
         final int end = buffer.length;
         if (offset >= end) {
-          throw new IOException("Incomplete data");
+            throw new IOException("Incomplete data");
         }
 
         int pos;
@@ -1272,7 +1339,7 @@
                 String path = extractString(block, 0, 100);
                 if (path.length() > 0) {
                     if (info.path.length() > 0) {
-                      info.path += '/';
+                        info.path += '/';
                     }
                     info.path += path;
                 }
@@ -1288,7 +1355,7 @@
                         gotHeader = readTarHeader(instream, block);
                     }
                     if (!gotHeader) {
-                      throw new IOException("Bad or missing pax header");
+                        throw new IOException("Bad or missing pax header");
                     }
 
                     typeChar = block[156];
@@ -1296,12 +1363,13 @@
 
                 switch (typeChar) {
                     case '0':
-                      info.type = BackupAgent.TYPE_FILE;
-                      break;
+                        info.type = BackupAgent.TYPE_FILE;
+                        break;
                     case '5': {
                         info.type = BackupAgent.TYPE_DIRECTORY;
                         if (info.size != 0) {
-                            Slog.w(RefactoredBackupManagerService.TAG, "Directory entry with nonzero size in header");
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Directory entry with nonzero size in header");
                             info.size = 0;
                         }
                         break;
@@ -1309,12 +1377,14 @@
                     case 0: {
                         // presume EOF
                         if (RefactoredBackupManagerService.DEBUG) {
-                          Slog.w(RefactoredBackupManagerService.TAG, "Saw type=0 in tar header block, info=" + info);
+                            Slog.w(RefactoredBackupManagerService.TAG,
+                                    "Saw type=0 in tar header block, info=" + info);
                         }
                         return null;
                     }
                     default: {
-                        Slog.e(RefactoredBackupManagerService.TAG, "Unknown tar entity type: " + typeChar);
+                        Slog.e(RefactoredBackupManagerService.TAG,
+                                "Unknown tar entity type: " + typeChar);
                         throw new IOException("Unknown entity type " + typeChar);
                     }
                 }
@@ -1323,16 +1393,17 @@
                 //
                 // first: apps/shared/unrecognized
                 if (FullBackup.SHARED_PREFIX.regionMatches(0,
-                    info.path, 0, FullBackup.SHARED_PREFIX.length())) {
+                        info.path, 0, FullBackup.SHARED_PREFIX.length())) {
                     // File in shared storage.  !!! TODO: implement this.
                     info.path = info.path.substring(FullBackup.SHARED_PREFIX.length());
                     info.packageName = RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
                     info.domain = FullBackup.SHARED_STORAGE_TOKEN;
                     if (RefactoredBackupManagerService.DEBUG) {
-                      Slog.i(RefactoredBackupManagerService.TAG, "File in shared storage: " + info.path);
+                        Slog.i(RefactoredBackupManagerService.TAG,
+                                "File in shared storage: " + info.path);
                     }
                 } else if (FullBackup.APPS_PREFIX.regionMatches(0,
-                    info.path, 0, FullBackup.APPS_PREFIX.length())) {
+                        info.path, 0, FullBackup.APPS_PREFIX.length())) {
                     // App content!  Parse out the package name and domain
 
                     // strip the apps/ prefix
@@ -1341,7 +1412,7 @@
                     // extract the package name
                     int slash = info.path.indexOf('/');
                     if (slash < 0) {
-                      throw new IOException("Illegal semantic path in " + info.path);
+                        throw new IOException("Illegal semantic path in " + info.path);
                     }
                     info.packageName = info.path.substring(0, slash);
                     info.path = info.path.substring(slash + 1);
@@ -1349,11 +1420,12 @@
                     // if it's a manifest or metadata payload we're done, otherwise parse
                     // out the domain into which the file will be restored
                     if (!info.path.equals(RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME)
-                        && !info.path.equals(RefactoredBackupManagerService.BACKUP_METADATA_FILENAME)) {
+                            && !info.path.equals(
+                            RefactoredBackupManagerService.BACKUP_METADATA_FILENAME)) {
                         slash = info.path.indexOf('/');
                         if (slash < 0) {
-                          throw new IOException(
-                              "Illegal semantic path in non-manifest " + info.path);
+                            throw new IOException(
+                                    "Illegal semantic path in non-manifest " + info.path);
                         }
                         info.domain = info.path.substring(0, slash);
                         info.path = info.path.substring(slash + 1);
@@ -1361,7 +1433,8 @@
                 }
             } catch (IOException e) {
                 if (RefactoredBackupManagerService.DEBUG) {
-                    Slog.e(RefactoredBackupManagerService.TAG, "Parse error in header: " + e.getMessage());
+                    Slog.e(RefactoredBackupManagerService.TAG,
+                            "Parse error in header: " + e.getMessage());
                     HEXLOG(block);
                 }
                 throw e;
@@ -1391,9 +1464,9 @@
     // Returns false if EOF is encountered before the requested number of bytes
     // could be read.
     int readExactly(InputStream in, byte[] buffer, int offset, int size)
-        throws IOException {
+            throws IOException {
         if (size <= 0) {
-          throw new IllegalArgumentException("size must be > 0");
+            throw new IllegalArgumentException("size must be > 0");
         }
 
         int soFar = 0;
@@ -1401,7 +1474,8 @@
             int nRead = in.read(buffer, offset + soFar, size - soFar);
             if (nRead <= 0) {
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
-                  Slog.w(RefactoredBackupManagerService.TAG, "- wanted exactly " + size + " but got only " + soFar);
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "- wanted exactly " + size + " but got only " + soFar);
                 }
                 break;
             }
@@ -1413,10 +1487,10 @@
     boolean readTarHeader(InputStream instream, byte[] block) throws IOException {
         final int got = readExactly(instream, block, 0, 512);
         if (got == 0) {
-          return false;     // Clean EOF
+            return false;     // Clean EOF
         }
         if (got < 512) {
-          throw new IOException("Unable to read full block header");
+            throw new IOException("Unable to read full block header");
         }
         mBytes += 512;
         return true;
@@ -1424,11 +1498,12 @@
 
     // overwrites 'info' fields based on the pax extended header
     boolean readPaxExtendedHeader(InputStream instream, FileMetadata info)
-        throws IOException {
+            throws IOException {
         // We should never see a pax extended header larger than this
         if (info.size > 32 * 1024) {
-            Slog.w(RefactoredBackupManagerService.TAG, "Suspiciously large pax header size " + info.size
-                + " - aborting");
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Suspiciously large pax header size " + info.size
+                            + " - aborting");
             throw new IOException("Sanity failure: pax header size " + info.size);
         }
 
@@ -1446,7 +1521,7 @@
             // extract the line at 'offset'
             int eol = offset + 1;
             while (eol < contentSize && data[eol] != ' ') {
-              eol++;
+                eol++;
             }
             if (eol >= contentSize) {
                 // error: we just hit EOD looking for the end of the size field
@@ -1458,7 +1533,7 @@
             eol = offset + linelen - 1; // trailing LF
             int value;
             for (value = key + 1; data[value] != '=' && value <= eol; value++) {
-              ;
+                ;
             }
             if (value > eol) {
                 throw new IOException("Invalid pax declaration");
@@ -1475,7 +1550,7 @@
                 info.size = Long.parseLong(valStr);
             } else {
                 if (RefactoredBackupManagerService.DEBUG) {
-                  Slog.i(RefactoredBackupManagerService.TAG, "Unhandled pax key: " + key);
+                    Slog.i(RefactoredBackupManagerService.TAG, "Unhandled pax key: " + key);
                 }
             }
 
@@ -1486,18 +1561,18 @@
     }
 
     long extractRadix(byte[] data, int offset, int maxChars, int radix)
-        throws IOException {
+            throws IOException {
         long value = 0;
         final int end = offset + maxChars;
         for (int i = offset; i < end; i++) {
             final byte b = data[i];
             // Numeric fields in tar can terminate with either NUL or SPC
             if (b == 0 || b == ' ') {
-              break;
+                break;
             }
             if (b < '0' || b > ('0' + radix - 1)) {
                 throw new IOException(
-                    "Invalid number in header: '" + (char) b + "' for radix " + radix);
+                        "Invalid number in header: '" + (char) b + "' for radix " + radix);
             }
             value = radix * value + (b - '0');
         }
@@ -1509,7 +1584,7 @@
         int eos = offset;
         // tar string fields terminate early with a NUL
         while (eos < end && data[eos] != 0) {
-          eos++;
+            eos++;
         }
         return new String(data, offset, eos - offset, "US-ASCII");
     }
@@ -1519,7 +1594,8 @@
             try {
                 mObserver.onStartRestore();
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full restore observer went away: startRestore");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full restore observer went away: startRestore");
                 mObserver = null;
             }
         }
@@ -1531,7 +1607,8 @@
                 // TODO: use a more user-friendly name string
                 mObserver.onRestorePackage(name);
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full restore observer went away: restorePackage");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full restore observer went away: restorePackage");
                 mObserver = null;
             }
         }
@@ -1542,7 +1619,8 @@
             try {
                 mObserver.onEndRestore();
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "full restore observer went away: endRestore");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "full restore observer went away: endRestore");
                 mObserver = null;
             }
         }
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 7c9bd38..23e03ab 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -38,6 +38,7 @@
 import android.os.UserHandle;
 import android.util.EventLog;
 import android.util.Slog;
+
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.AppWidgetBackupBridge;
 import com.android.server.EventLogTags;
@@ -46,13 +47,15 @@
 import com.android.server.backup.PackageManagerBackupAgent;
 import com.android.server.backup.PackageManagerBackupAgent.Metadata;
 import com.android.server.backup.RefactoredBackupManagerService;
+
+import libcore.io.IoUtils;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-import libcore.io.IoUtils;
 
 public class PerformUnifiedRestoreTask implements BackupRestoreTask {
 
@@ -135,9 +138,9 @@
     // Invariant: mWakelock is already held, and this task is responsible for
     // releasing it at the end of the restore operation.
     public PerformUnifiedRestoreTask(RefactoredBackupManagerService backupManagerService,
-        IBackupTransport transport, IRestoreObserver observer,
-        IBackupManagerMonitor monitor, long restoreSetToken, PackageInfo targetPackage,
-        int pmToken, boolean isFullSystemRestore, String[] filterSet) {
+            IBackupTransport transport, IRestoreObserver observer,
+            IBackupManagerMonitor monitor, long restoreSetToken, PackageInfo targetPackage,
+            int pmToken, boolean isFullSystemRestore, String[] filterSet) {
         this.backupManagerService = backupManagerService;
         mEphemeralOpToken = backupManagerService.generateRandomIntegerToken();
         mState = UnifiedRestoreState.INITIAL;
@@ -162,11 +165,12 @@
             if (filterSet == null) {
                 // We want everything and a pony
                 List<PackageInfo> apps =
-                    PackageManagerBackupAgent.getStorableApplications(
-                        backupManagerService.mPackageManager);
+                        PackageManagerBackupAgent.getStorableApplications(
+                                backupManagerService.mPackageManager);
                 filterSet = packagesToNames(apps);
                 if (RefactoredBackupManagerService.DEBUG) {
-                    Slog.i(RefactoredBackupManagerService.TAG, "Full restore; asking about " + filterSet.length + " apps");
+                    Slog.i(RefactoredBackupManagerService.TAG,
+                            "Full restore; asking about " + filterSet.length + " apps");
                 }
             }
 
@@ -179,7 +183,8 @@
             boolean hasSettings = false;
             for (int i = 0; i < filterSet.length; i++) {
                 try {
-                    PackageInfo info = backupManagerService.mPackageManager.getPackageInfo(filterSet[i], 0);
+                    PackageInfo info = backupManagerService.mPackageManager.getPackageInfo(
+                            filterSet[i], 0);
                     if ("android".equals(info.packageName)) {
                         hasSystem = true;
                         continue;
@@ -189,7 +194,8 @@
                         continue;
                     }
 
-                    if (RefactoredBackupManagerService.appIsEligibleForBackup(info.applicationInfo)) {
+                    if (RefactoredBackupManagerService.appIsEligibleForBackup(
+                            info.applicationInfo)) {
                         mAcceptSet.add(info);
                     }
                 } catch (NameNotFoundException e) {
@@ -198,7 +204,8 @@
             }
             if (hasSystem) {
                 try {
-                    mAcceptSet.add(0, backupManagerService.mPackageManager.getPackageInfo("android", 0));
+                    mAcceptSet.add(0,
+                            backupManagerService.mPackageManager.getPackageInfo("android", 0));
                 } catch (NameNotFoundException e) {
                     // won't happen; we know a priori that it's valid
                 }
@@ -206,7 +213,7 @@
             if (hasSettings) {
                 try {
                     mAcceptSet.add(backupManagerService.mPackageManager.getPackageInfo(
-                        RefactoredBackupManagerService.SETTINGS_PACKAGE, 0));
+                            RefactoredBackupManagerService.SETTINGS_PACKAGE, 0));
                 } catch (NameNotFoundException e) {
                     // this one is always valid too
                 }
@@ -214,7 +221,8 @@
         }
 
         if (RefactoredBackupManagerService.MORE_DEBUG) {
-            Slog.v(RefactoredBackupManagerService.TAG, "Restore; accept set size is " + mAcceptSet.size());
+            Slog.v(RefactoredBackupManagerService.TAG,
+                    "Restore; accept set size is " + mAcceptSet.size());
             for (PackageInfo info : mAcceptSet) {
                 Slog.v(RefactoredBackupManagerService.TAG, "   " + info.packageName);
             }
@@ -234,7 +242,7 @@
     @Override
     public void execute() {
         if (RefactoredBackupManagerService.MORE_DEBUG) {
-          Slog.v(RefactoredBackupManagerService.TAG, "*** Executing restore step " + mState);
+            Slog.v(RefactoredBackupManagerService.TAG, "*** Executing restore step " + mState);
         }
         switch (mState) {
             case INITIAL:
@@ -259,7 +267,7 @@
 
             case FINAL:
                 if (!mFinished) {
-                  finalizeRestore();
+                    finalizeRestore();
                 } else {
                     Slog.e(RefactoredBackupManagerService.TAG, "Duplicate finish");
                 }
@@ -332,7 +340,8 @@
             PackageInfo[] packages = mAcceptSet.toArray(new PackageInfo[0]);
             mStatus = mTransport.startRestore(mToken, packages);
             if (mStatus != BackupTransport.TRANSPORT_OK) {
-                Slog.e(RefactoredBackupManagerService.TAG, "Transport error " + mStatus + "; no restore possible");
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Transport error " + mStatus + "; no restore possible");
                 mStatus = BackupTransport.TRANSPORT_ERROR;
                 executeNextState(UnifiedRestoreState.FINAL);
                 return;
@@ -340,22 +349,24 @@
 
             RestoreDescription desc = mTransport.nextRestorePackage();
             if (desc == null) {
-                Slog.e(RefactoredBackupManagerService.TAG, "No restore metadata available; halting");
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "No restore metadata available; halting");
                 mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                    BackupManagerMonitor.LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE,
-                    mCurrentPackage,
-                    BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
+                        BackupManagerMonitor.LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                 mStatus = BackupTransport.TRANSPORT_ERROR;
                 executeNextState(UnifiedRestoreState.FINAL);
                 return;
             }
-            if (!RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL.equals(desc.getPackageName())) {
+            if (!RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL.equals(
+                    desc.getPackageName())) {
                 Slog.e(RefactoredBackupManagerService.TAG, "Required package metadata but got "
-                    + desc.getPackageName());
+                        + desc.getPackageName());
                 mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                    BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED,
-                    mCurrentPackage,
-                    BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
+                        BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                 mStatus = BackupTransport.TRANSPORT_ERROR;
                 executeNextState(UnifiedRestoreState.FINAL);
                 return;
@@ -378,23 +389,24 @@
             // synchronous we also know that we should cancel the pending timeout
             // message.
             backupManagerService.mBackupHandler.removeMessages(
-                RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
+                    RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT);
 
             // Verify that the backup set includes metadata.  If not, we can't do
             // signature/version verification etc, so we simply do not proceed with
             // the restore operation.
             if (!mPmAgent.hasMetadata()) {
-                Slog.e(RefactoredBackupManagerService.TAG, "PM agent has no metadata, so not restoring");
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "PM agent has no metadata, so not restoring");
                 mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                    BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA,
-                    mCurrentPackage,
-                    BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
+                        BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
-                    RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL,
-                    "Package manager restore metadata missing");
+                        RefactoredBackupManagerService.PACKAGE_MANAGER_SENTINEL,
+                        "Package manager restore metadata missing");
                 mStatus = BackupTransport.TRANSPORT_ERROR;
                 backupManagerService.mBackupHandler.removeMessages(
-                    RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
+                        RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
                 executeNextState(UnifiedRestoreState.FINAL);
                 return;
             }
@@ -404,14 +416,15 @@
 
         } catch (Exception e) {
             // If we lost the transport at any time, halt
-            Slog.e(RefactoredBackupManagerService.TAG, "Unable to contact transport for restore: " + e.getMessage());
+            Slog.e(RefactoredBackupManagerService.TAG,
+                    "Unable to contact transport for restore: " + e.getMessage());
             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT,
-                null,
-                BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
+                    BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT,
+                    null,
+                    BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
             mStatus = BackupTransport.TRANSPORT_ERROR;
             backupManagerService.mBackupHandler.removeMessages(
-                RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
+                    RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
             executeNextState(UnifiedRestoreState.FINAL);
             return;
         }
@@ -424,7 +437,7 @@
         try {
             mRestoreDescription = mTransport.nextRestorePackage();
             final String pkgName = (mRestoreDescription != null)
-                ? mRestoreDescription.getPackageName() : null;
+                    ? mRestoreDescription.getPackageName() : null;
             if (pkgName == null) {
                 Slog.e(RefactoredBackupManagerService.TAG, "Failure getting next package name");
                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
@@ -433,7 +446,8 @@
             } else if (mRestoreDescription == RestoreDescription.NO_MORE_PACKAGES) {
                 // Yay we've reached the end cleanly
                 if (RefactoredBackupManagerService.DEBUG) {
-                    Slog.v(RefactoredBackupManagerService.TAG, "No more packages; finishing restore");
+                    Slog.v(RefactoredBackupManagerService.TAG,
+                            "No more packages; finishing restore");
                 }
                 int millis = (int) (SystemClock.elapsedRealtime() - mStartRealtime);
                 EventLog.writeEvent(EventLogTags.RESTORE_SUCCESS, mCount, millis);
@@ -442,7 +456,8 @@
             }
 
             if (RefactoredBackupManagerService.DEBUG) {
-                Slog.i(RefactoredBackupManagerService.TAG, "Next restore package: " + mRestoreDescription);
+                Slog.i(RefactoredBackupManagerService.TAG,
+                        "Next restore package: " + mRestoreDescription);
             }
             sendOnRestorePackage(pkgName);
 
@@ -450,25 +465,25 @@
             if (metaInfo == null) {
                 Slog.e(RefactoredBackupManagerService.TAG, "No metadata for " + pkgName);
                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName,
-                    "Package metadata missing");
+                        "Package metadata missing");
                 nextState = UnifiedRestoreState.RUNNING_QUEUE;
                 return;
             }
 
             try {
                 mCurrentPackage = backupManagerService.mPackageManager.getPackageInfo(
-                    pkgName, PackageManager.GET_SIGNATURES);
+                        pkgName, PackageManager.GET_SIGNATURES);
             } catch (NameNotFoundException e) {
                 // Whoops, we thought we could restore this package but it
                 // turns out not to be present.  Skip it.
                 Slog.e(RefactoredBackupManagerService.TAG, "Package not present: " + pkgName);
                 mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                    BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_PRESENT,
-                    mCurrentPackage,
-                    BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                    null);
+                        BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_PRESENT,
+                        mCurrentPackage,
+                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                        null);
                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName,
-                    "Package missing on device");
+                        "Package missing on device");
                 nextState = UnifiedRestoreState.RUNNING_QUEUE;
                 return;
             }
@@ -478,48 +493,50 @@
                 // installed.  If the app has not declared that it is prepared to
                 // handle this case, we do not attempt the restore.
                 if ((mCurrentPackage.applicationInfo.flags
-                    & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) {
+                        & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) {
                     String message = "Source version " + metaInfo.versionCode
-                        + " > installed version " + mCurrentPackage.versionCode;
-                    Slog.w(RefactoredBackupManagerService.TAG, "Package " + pkgName + ": " + message);
+                            + " > installed version " + mCurrentPackage.versionCode;
+                    Slog.w(RefactoredBackupManagerService.TAG,
+                            "Package " + pkgName + ": " + message);
                     Bundle monitoringExtras = backupManagerService.putMonitoringExtra(null,
-                        BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
-                        metaInfo.versionCode);
+                            BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
+                            metaInfo.versionCode);
                     monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
-                        BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false);
+                            BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false);
                     mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                        BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
-                        mCurrentPackage,
-                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                        monitoringExtras);
+                            BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
+                            mCurrentPackage,
+                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                            monitoringExtras);
                     EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
-                        pkgName, message);
+                            pkgName, message);
                     nextState = UnifiedRestoreState.RUNNING_QUEUE;
                     return;
                 } else {
                     if (RefactoredBackupManagerService.DEBUG) {
-                      Slog.v(RefactoredBackupManagerService.TAG, "Source version " + metaInfo.versionCode
-                          + " > installed version " + mCurrentPackage.versionCode
-                          + " but restoreAnyVersion");
+                        Slog.v(RefactoredBackupManagerService.TAG,
+                                "Source version " + metaInfo.versionCode
+                                        + " > installed version " + mCurrentPackage.versionCode
+                                        + " but restoreAnyVersion");
                     }
                     Bundle monitoringExtras = backupManagerService.putMonitoringExtra(null,
-                        BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
-                        metaInfo.versionCode);
+                            BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
+                            metaInfo.versionCode);
                     monitoringExtras = backupManagerService.putMonitoringExtra(monitoringExtras,
-                        BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true);
+                            BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true);
                     mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                        BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
-                        mCurrentPackage,
-                        BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
-                        monitoringExtras);
+                            BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
+                            mCurrentPackage,
+                            BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+                            monitoringExtras);
                 }
             }
 
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Slog.v(RefactoredBackupManagerService.TAG, "Package " + pkgName
-                  + " restore version [" + metaInfo.versionCode
-                  + "] is compatible with installed version ["
-                  + mCurrentPackage.versionCode + "]");
+                Slog.v(RefactoredBackupManagerService.TAG, "Package " + pkgName
+                        + " restore version [" + metaInfo.versionCode
+                        + "] is compatible with installed version ["
+                        + mCurrentPackage.versionCode + "]");
             }
 
             // Reset per-package preconditions and fire the appropriate next state
@@ -536,8 +553,9 @@
                 return;
             }
         } catch (Exception e) {
-            Slog.e(RefactoredBackupManagerService.TAG, "Can't get next restore target from transport; halting: "
-                + e.getMessage());
+            Slog.e(RefactoredBackupManagerService.TAG,
+                    "Can't get next restore target from transport; halting: "
+                            + e.getMessage());
             EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
             nextState = UnifiedRestoreState.FINAL;
             return;
@@ -555,43 +573,45 @@
         // Validate some semantic requirements that apply in this way
         // only to the key/value restore API flow
         if (mCurrentPackage.applicationInfo.backupAgentName == null
-            || "".equals(mCurrentPackage.applicationInfo.backupAgentName)) {
+                || "".equals(mCurrentPackage.applicationInfo.backupAgentName)) {
             if (RefactoredBackupManagerService.MORE_DEBUG) {
                 Slog.i(RefactoredBackupManagerService.TAG, "Data exists for package " + packageName
-                    + " but app has no agent; skipping");
+                        + " but app has no agent; skipping");
             }
             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                BackupManagerMonitor.LOG_EVENT_ID_APP_HAS_NO_AGENT, mCurrentPackage,
-                BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
+                    BackupManagerMonitor.LOG_EVENT_ID_APP_HAS_NO_AGENT, mCurrentPackage,
+                    BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
-                "Package has no agent");
+                    "Package has no agent");
             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
             return;
         }
 
         Metadata metaInfo = mPmAgent.getRestoredMetadata(packageName);
         if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage)) {
-            Slog.w(RefactoredBackupManagerService.TAG, "Signature mismatch restoring " + packageName);
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Signature mismatch restoring " + packageName);
             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH, mCurrentPackage,
-                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
+                    BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH, mCurrentPackage,
+                    BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
-                "Signature mismatch");
+                    "Signature mismatch");
             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
             return;
         }
 
         // Good to go!  Set up and bind the agent...
         mAgent = backupManagerService.bindToAgentSynchronous(
-            mCurrentPackage.applicationInfo,
-            ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
+                mCurrentPackage.applicationInfo,
+                ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
         if (mAgent == null) {
-            Slog.w(RefactoredBackupManagerService.TAG, "Can't find backup agent for " + packageName);
+            Slog.w(RefactoredBackupManagerService.TAG,
+                    "Can't find backup agent for " + packageName);
             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                BackupManagerMonitor.LOG_EVENT_ID_CANT_FIND_AGENT, mCurrentPackage,
-                BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
+                    BackupManagerMonitor.LOG_EVENT_ID_CANT_FIND_AGENT, mCurrentPackage,
+                    BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
-                "Restore agent missing");
+                    "Restore agent missing");
             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
             return;
         }
@@ -604,7 +624,8 @@
             initiateOneRestore(mCurrentPackage, metaInfo.versionCode);
             ++mCount;
         } catch (Exception e) {
-            Slog.e(RefactoredBackupManagerService.TAG, "Error when attempting restore: " + e.toString());
+            Slog.e(RefactoredBackupManagerService.TAG,
+                    "Error when attempting restore: " + e.toString());
             keyValueAgentErrorCleanup();
             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
         }
@@ -615,7 +636,8 @@
         final String packageName = app.packageName;
 
         if (RefactoredBackupManagerService.DEBUG) {
-          Slog.d(RefactoredBackupManagerService.TAG, "initiateOneRestore packageName=" + packageName);
+            Slog.d(RefactoredBackupManagerService.TAG,
+                    "initiateOneRestore packageName=" + packageName);
         }
 
         // !!! TODO: get the dirs from the transport
@@ -635,14 +657,15 @@
         try {
             // Run the transport's restore pass
             stage = ParcelFileDescriptor.open(downloadFile,
-                ParcelFileDescriptor.MODE_READ_WRITE |
-                    ParcelFileDescriptor.MODE_CREATE |
-                    ParcelFileDescriptor.MODE_TRUNCATE);
+                    ParcelFileDescriptor.MODE_READ_WRITE |
+                            ParcelFileDescriptor.MODE_CREATE |
+                            ParcelFileDescriptor.MODE_TRUNCATE);
 
             if (mTransport.getRestoreData(stage) != BackupTransport.TRANSPORT_OK) {
                 // Transport-level failure, so we wind everything up and
                 // terminate the restore operation.
-                Slog.e(RefactoredBackupManagerService.TAG, "Error getting restore data for " + packageName);
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Error getting restore data for " + packageName);
                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
                 stage.close();
                 downloadFile.delete();
@@ -656,12 +679,12 @@
             if (staging) {
                 stage.close();
                 stage = ParcelFileDescriptor.open(downloadFile,
-                    ParcelFileDescriptor.MODE_READ_ONLY);
+                        ParcelFileDescriptor.MODE_READ_ONLY);
 
                 mBackupData = ParcelFileDescriptor.open(mBackupDataName,
-                    ParcelFileDescriptor.MODE_READ_WRITE |
-                        ParcelFileDescriptor.MODE_CREATE |
-                        ParcelFileDescriptor.MODE_TRUNCATE);
+                        ParcelFileDescriptor.MODE_READ_WRITE |
+                                ParcelFileDescriptor.MODE_CREATE |
+                                ParcelFileDescriptor.MODE_TRUNCATE);
 
                 BackupDataInput in = new BackupDataInput(stage.getFileDescriptor());
                 BackupDataOutput out = new BackupDataOutput(mBackupData.getFileDescriptor());
@@ -674,7 +697,8 @@
                     if (key.equals(RefactoredBackupManagerService.KEY_WIDGET_STATE)) {
                         if (RefactoredBackupManagerService.DEBUG) {
                             Slog.i(
-                                RefactoredBackupManagerService.TAG, "Restoring widget state for " + packageName);
+                                    RefactoredBackupManagerService.TAG,
+                                    "Restoring widget state for " + packageName);
                         }
                         mWidgetData = new byte[size];
                         in.readEntityData(mWidgetData, 0, size);
@@ -695,25 +719,27 @@
             stage.close();
 
             mBackupData = ParcelFileDescriptor.open(mBackupDataName,
-                ParcelFileDescriptor.MODE_READ_ONLY);
+                    ParcelFileDescriptor.MODE_READ_ONLY);
 
             mNewState = ParcelFileDescriptor.open(mNewStateName,
-                ParcelFileDescriptor.MODE_READ_WRITE |
-                    ParcelFileDescriptor.MODE_CREATE |
-                    ParcelFileDescriptor.MODE_TRUNCATE);
+                    ParcelFileDescriptor.MODE_READ_WRITE |
+                            ParcelFileDescriptor.MODE_CREATE |
+                            ParcelFileDescriptor.MODE_TRUNCATE);
 
             // Kick off the restore, checking for hung agents.  The timeout or
             // the operationComplete() callback will schedule the next step,
             // so we do not do that here.
             backupManagerService
-                .prepareOperationTimeout(mEphemeralOpToken, RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL,
-                    this, RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
+                    .prepareOperationTimeout(mEphemeralOpToken,
+                            RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL,
+                            this, RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
             mAgent.doRestore(mBackupData, appVersionCode, mNewState,
-                mEphemeralOpToken, backupManagerService.mBackupManagerBinder);
+                    mEphemeralOpToken, backupManagerService.mBackupManagerBinder);
         } catch (Exception e) {
-            Slog.e(RefactoredBackupManagerService.TAG, "Unable to call app for restore: " + packageName, e);
+            Slog.e(RefactoredBackupManagerService.TAG,
+                    "Unable to call app for restore: " + packageName, e);
             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
-                packageName, e.toString());
+                    packageName, e.toString());
             keyValueAgentErrorCleanup();    // clears any pending timeout messages as well
 
             // After a restore failure we go back to running the queue.  If there
@@ -738,7 +764,7 @@
             StreamFeederThread feeder = new StreamFeederThread();
             if (RefactoredBackupManagerService.MORE_DEBUG) {
                 Slog.i(RefactoredBackupManagerService.TAG, "Spinning threads for stream restore of "
-                    + mCurrentPackage.packageName);
+                        + mCurrentPackage.packageName);
             }
             new Thread(feeder, "unified-stream-feeder").start();
 
@@ -748,7 +774,8 @@
             // Unable to instantiate the feeder thread -- we need to bail on the
             // current target.  We haven't asked the transport for data yet, though,
             // so we can do that simply by going back to running the restore queue.
-            Slog.e(RefactoredBackupManagerService.TAG, "Unable to construct pipes for stream restore!");
+            Slog.e(RefactoredBackupManagerService.TAG,
+                    "Unable to construct pipes for stream restore!");
             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
         }
     }
@@ -757,16 +784,18 @@
     private void restoreFinished() {
         try {
             backupManagerService
-                .prepareOperationTimeout(mEphemeralOpToken, RefactoredBackupManagerService.TIMEOUT_RESTORE_FINISHED_INTERVAL, this,
-                    RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
+                    .prepareOperationTimeout(mEphemeralOpToken,
+                            RefactoredBackupManagerService.TIMEOUT_RESTORE_FINISHED_INTERVAL, this,
+                            RefactoredBackupManagerService.OP_TYPE_RESTORE_WAIT);
             mAgent.doRestoreFinished(mEphemeralOpToken, backupManagerService.mBackupManagerBinder);
             // If we get this far, the callback or timeout will schedule the
             // next restore state, so we're done
         } catch (Exception e) {
             final String packageName = mCurrentPackage.packageName;
-            Slog.e(RefactoredBackupManagerService.TAG, "Unable to finalize restore of " + packageName);
+            Slog.e(RefactoredBackupManagerService.TAG,
+                    "Unable to finalize restore of " + packageName);
             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
-                packageName, e.toString());
+                    packageName, e.toString());
             keyValueAgentErrorCleanup();
             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
         }
@@ -774,7 +803,7 @@
 
     class StreamFeederThread extends RestoreEngine implements Runnable, BackupRestoreTask {
 
-      final String TAG = "StreamFeederThread";
+        final String TAG = "StreamFeederThread";
         FullRestoreEngine mEngine;
         EngineThread mEngineThread;
 
@@ -799,10 +828,10 @@
             int status = BackupTransport.TRANSPORT_OK;
 
             EventLog.writeEvent(EventLogTags.FULL_RESTORE_PACKAGE,
-                mCurrentPackage.packageName);
+                    mCurrentPackage.packageName);
 
             mEngine = new FullRestoreEngine(backupManagerService, this, null,
-                mMonitor, mCurrentPackage, false, false, mEphemeralOpToken);
+                    mMonitor, mCurrentPackage, false, false, mEphemeralOpToken);
             mEngineThread = new EngineThread(mEngine, mEnginePipes[0]);
 
             ParcelFileDescriptor eWriteEnd = mEnginePipes[1];
@@ -825,7 +854,8 @@
                         // The transport wrote this many bytes of restore data to the
                         // pipe, so pass it along to the engine.
                         if (RefactoredBackupManagerService.MORE_DEBUG) {
-                            Slog.v(RefactoredBackupManagerService.TAG, "  <- transport provided chunk size " + result);
+                            Slog.v(RefactoredBackupManagerService.TAG,
+                                    "  <- transport provided chunk size " + result);
                         }
                         if (result > bufferSize) {
                             bufferSize = result;
@@ -837,28 +867,32 @@
                             engineOut.write(buffer, 0, n);
                             toCopy -= n;
                             if (RefactoredBackupManagerService.MORE_DEBUG) {
-                                Slog.v(RefactoredBackupManagerService.TAG, "  -> wrote " + n + " to engine, left=" + toCopy);
+                                Slog.v(RefactoredBackupManagerService.TAG,
+                                        "  -> wrote " + n + " to engine, left=" + toCopy);
                             }
                         }
                     } else if (result == BackupTransport.NO_MORE_DATA) {
                         // Clean finish.  Wind up and we're done!
                         if (RefactoredBackupManagerService.MORE_DEBUG) {
-                            Slog.i(RefactoredBackupManagerService.TAG, "Got clean full-restore EOF for "
-                                + mCurrentPackage.packageName);
+                            Slog.i(RefactoredBackupManagerService.TAG,
+                                    "Got clean full-restore EOF for "
+                                            + mCurrentPackage.packageName);
                         }
                         status = BackupTransport.TRANSPORT_OK;
                         break;
                     } else {
                         // Transport reported some sort of failure; the fall-through
                         // handling will deal properly with that.
-                        Slog.e(RefactoredBackupManagerService.TAG, "Error " + result + " streaming restore for "
-                            + mCurrentPackage.packageName);
+                        Slog.e(RefactoredBackupManagerService.TAG,
+                                "Error " + result + " streaming restore for "
+                                        + mCurrentPackage.packageName);
                         EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
                         status = result;
                     }
                 }
                 if (RefactoredBackupManagerService.MORE_DEBUG) {
-                  Slog.v(RefactoredBackupManagerService.TAG, "Done copying to engine, falling through");
+                    Slog.v(RefactoredBackupManagerService.TAG,
+                            "Done copying to engine, falling through");
                 }
             } catch (IOException e) {
                 // We lost our ability to communicate via the pipes.  That's worrying
@@ -866,13 +900,14 @@
                 // carry on with the next restore target.
                 Slog.e(RefactoredBackupManagerService.TAG, "Unable to route data for restore");
                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
-                    mCurrentPackage.packageName, "I/O error on pipes");
+                        mCurrentPackage.packageName, "I/O error on pipes");
                 status = BackupTransport.AGENT_ERROR;
             } catch (Exception e) {
                 // The transport threw; terminate the whole operation.  Closing
                 // the sockets will wake up the engine and it will then tidy up the
                 // remote end.
-                Slog.e(RefactoredBackupManagerService.TAG, "Transport failed during restore: " + e.getMessage());
+                Slog.e(RefactoredBackupManagerService.TAG,
+                        "Transport failed during restore: " + e.getMessage());
                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
                 status = BackupTransport.TRANSPORT_ERROR;
             } finally {
@@ -913,13 +948,15 @@
                     } catch (Exception e) {
                         // transport itself is dead; make sure we handle this as a
                         // fatal error
-                        Slog.e(RefactoredBackupManagerService.TAG, "Transport threw from abortFullRestore: " + e.getMessage());
+                        Slog.e(RefactoredBackupManagerService.TAG,
+                                "Transport threw from abortFullRestore: " + e.getMessage());
                         status = BackupTransport.TRANSPORT_ERROR;
                     }
 
                     // We also need to wipe the current target's data, as it's probably
                     // in an incoherent state.
-                    backupManagerService.clearApplicationDataSynchronous(mCurrentPackage.packageName);
+                    backupManagerService.clearApplicationDataSynchronous(
+                            mCurrentPackage.packageName);
 
                     // Schedule the next state based on the nature of our failure
                     if (status == BackupTransport.TRANSPORT_ERROR) {
@@ -946,12 +983,13 @@
         public void handleCancel(boolean cancelAll) {
             backupManagerService.removeOperation(mEphemeralOpToken);
             if (RefactoredBackupManagerService.DEBUG) {
-                Slog.w(RefactoredBackupManagerService.TAG, "Full-data restore target timed out; shutting down");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "Full-data restore target timed out; shutting down");
             }
 
             mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-                BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT,
-                mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
+                    BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT,
+                    mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
             mEngineThread.handleTimeout();
 
             IoUtils.closeQuietly(mEnginePipes[1]);
@@ -963,7 +1001,7 @@
 
     class EngineThread implements Runnable {
 
-      FullRestoreEngine mEngine;
+        FullRestoreEngine mEngine;
         FileInputStream mEngineStream;
 
         EngineThread(FullRestoreEngine engine, ParcelFileDescriptor engineSocket) {
@@ -1006,7 +1044,7 @@
     // state FINAL : tear everything down and we're done.
     private void finalizeRestore() {
         if (RefactoredBackupManagerService.MORE_DEBUG) {
-          Slog.d(RefactoredBackupManagerService.TAG, "finishing restore mObserver=" + mObserver);
+            Slog.d(RefactoredBackupManagerService.TAG, "finishing restore mObserver=" + mObserver);
         }
 
         try {
@@ -1020,29 +1058,31 @@
             try {
                 mObserver.restoreFinished(mStatus);
             } catch (RemoteException e) {
-                Slog.d(RefactoredBackupManagerService.TAG, "Restore observer died at restoreFinished");
+                Slog.d(RefactoredBackupManagerService.TAG,
+                        "Restore observer died at restoreFinished");
             }
         }
 
         // Clear any ongoing session timeout.
         backupManagerService.mBackupHandler.removeMessages(
-            RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
+                RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT);
 
         // If we have a PM token, we must under all circumstances be sure to
         // handshake when we've finished.
         if (mPmToken > 0) {
             if (RefactoredBackupManagerService.MORE_DEBUG) {
-              Slog.v(RefactoredBackupManagerService.TAG, "finishing PM token " + mPmToken);
+                Slog.v(RefactoredBackupManagerService.TAG, "finishing PM token " + mPmToken);
             }
             try {
-                backupManagerService.mPackageManagerBinder.finishPackageInstall(mPmToken, mDidLaunch);
+                backupManagerService.mPackageManagerBinder.finishPackageInstall(mPmToken,
+                        mDidLaunch);
             } catch (RemoteException e) { /* can't happen */ }
         } else {
             // We were invoked via an active restore session, not by the Package
             // Manager, so start up the session timeout again.
             backupManagerService.mBackupHandler.sendEmptyMessageDelayed(
-                RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT,
-                RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL);
+                    RefactoredBackupManagerService.MSG_RESTORE_SESSION_TIMEOUT,
+                    RefactoredBackupManagerService.TIMEOUT_RESTORE_INTERVAL);
         }
 
         // Kick off any work that may be needed regarding app widget restores
@@ -1067,8 +1107,8 @@
                 }
                 PerformUnifiedRestoreTask task = backupManagerService.mPendingRestores.remove();
                 backupManagerService.mBackupHandler.sendMessage(
-                    backupManagerService.mBackupHandler.obtainMessage(
-                        RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, task));
+                        backupManagerService.mBackupHandler.obtainMessage(
+                                RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, task));
 
             } else {
                 backupManagerService.mIsRestoreInProgress = false;
@@ -1094,15 +1134,15 @@
         mBackupDataName.delete();
         mStageName.delete();
         try {
-          if (mBackupData != null) {
-            mBackupData.close();
-          }
+            if (mBackupData != null) {
+                mBackupData.close();
+            }
         } catch (IOException e) {
         }
         try {
-          if (mNewState != null) {
-            mNewState.close();
-          }
+            if (mNewState != null) {
+                mNewState.close();
+            }
         } catch (IOException e) {
         }
         mBackupData = mNewState = null;
@@ -1127,7 +1167,8 @@
         if (mCurrentPackage.applicationInfo != null) {
             // unbind and tidy up even on timeout or failure
             try {
-                backupManagerService.mActivityManager.unbindBackupAgent(mCurrentPackage.applicationInfo);
+                backupManagerService.mActivityManager.unbindBackupAgent(
+                        mCurrentPackage.applicationInfo);
 
                 // The agent was probably running with a stub Application object,
                 // which isn't a valid run mode for the main app logic.  Shut
@@ -1138,24 +1179,26 @@
                 //
                 // We execute this kill when these conditions hold:
                 //    1. it's not a system-uid process,
-                //    2. the app did not request its own restore (mTargetPackage == null), and either
+                //    2. the app did not request its own restore (mTargetPackage == null), and
+                // either
                 //    3a. the app is a full-data target (TYPE_FULL_STREAM) or
                 //     b. the app does not state android:killAfterRestore="false" in its manifest
                 final int appFlags = mCurrentPackage.applicationInfo.flags;
                 final boolean killAfterRestore =
-                    (mCurrentPackage.applicationInfo.uid >= Process.FIRST_APPLICATION_UID)
-                        && ((mRestoreDescription.getDataType()
-                        == RestoreDescription.TYPE_FULL_STREAM)
-                        || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0));
+                        (mCurrentPackage.applicationInfo.uid >= Process.FIRST_APPLICATION_UID)
+                                && ((mRestoreDescription.getDataType()
+                                == RestoreDescription.TYPE_FULL_STREAM)
+                                || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0));
 
                 if (mTargetPackage == null && killAfterRestore) {
                     if (RefactoredBackupManagerService.DEBUG) {
-                      Slog.d(RefactoredBackupManagerService.TAG, "Restore complete, killing host process of "
-                          + mCurrentPackage.applicationInfo.processName);
+                        Slog.d(RefactoredBackupManagerService.TAG,
+                                "Restore complete, killing host process of "
+                                        + mCurrentPackage.applicationInfo.processName);
                     }
                     backupManagerService.mActivityManager.killApplicationProcess(
-                        mCurrentPackage.applicationInfo.processName,
-                        mCurrentPackage.applicationInfo.uid);
+                            mCurrentPackage.applicationInfo.processName,
+                            mCurrentPackage.applicationInfo.uid);
                 }
             } catch (RemoteException e) {
                 // can't happen; we run in the same process as the activity manager
@@ -1165,7 +1208,7 @@
         // The caller is responsible for reestablishing the state machine; our
         // responsibility here is to clear the decks for whatever comes next.
         backupManagerService.mBackupHandler.removeMessages(
-            RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT, this);
+                RefactoredBackupManagerService.MSG_RESTORE_OPERATION_TIMEOUT, this);
     }
 
     @Override
@@ -1173,8 +1216,8 @@
         backupManagerService.removeOperation(mEphemeralOpToken);
         if (RefactoredBackupManagerService.MORE_DEBUG) {
             Slog.i(RefactoredBackupManagerService.TAG, "operationComplete() during restore: target="
-                + mCurrentPackage.packageName
-                + " state=" + mState);
+                    + mCurrentPackage.packageName
+                    + " state=" + mState);
         }
 
         final UnifiedRestoreState nextState;
@@ -1200,7 +1243,7 @@
                 // app in the queue.
                 int size = (int) mBackupDataName.length();
                 EventLog.writeEvent(EventLogTags.RESTORE_PACKAGE,
-                    mCurrentPackage.packageName, size);
+                        mCurrentPackage.packageName, size);
 
                 // Just go back to running the restore queue
                 keyValueAgentCleanup();
@@ -1209,7 +1252,8 @@
                 // incorporate it into current bookeeping and then pass that along to
                 // the app as part of the restore-time work.
                 if (mWidgetData != null) {
-                    backupManagerService.restoreWidgetData(mCurrentPackage.packageName, mWidgetData);
+                    backupManagerService.restoreWidgetData(mCurrentPackage.packageName,
+                            mWidgetData);
                 }
 
                 nextState = UnifiedRestoreState.RUNNING_QUEUE;
@@ -1220,7 +1264,8 @@
                 // Some kind of horrible semantic error; we're in an unexpected state.
                 // Back off hard and wind up.
                 Slog.e(
-                    RefactoredBackupManagerService.TAG, "Unexpected restore callback into state " + mState);
+                        RefactoredBackupManagerService.TAG,
+                        "Unexpected restore callback into state " + mState);
                 keyValueAgentErrorCleanup();
                 nextState = UnifiedRestoreState.FINAL;
                 break;
@@ -1234,12 +1279,13 @@
     @Override
     public void handleCancel(boolean cancelAll) {
         backupManagerService.removeOperation(mEphemeralOpToken);
-        Slog.e(RefactoredBackupManagerService.TAG, "Timeout restoring application " + mCurrentPackage.packageName);
+        Slog.e(RefactoredBackupManagerService.TAG,
+                "Timeout restoring application " + mCurrentPackage.packageName);
         mMonitor = RefactoredBackupManagerService.monitorEvent(mMonitor,
-            BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT,
-            mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
+                BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT,
+                mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
         EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
-            mCurrentPackage.packageName, "restore timeout");
+                mCurrentPackage.packageName, "restore timeout");
         // Handle like an agent that threw on invocation: wipe it and go on to the next
         keyValueAgentErrorCleanup();
         executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
@@ -1247,12 +1293,12 @@
 
     void executeNextState(UnifiedRestoreState nextState) {
         if (RefactoredBackupManagerService.MORE_DEBUG) {
-          Slog.i(RefactoredBackupManagerService.TAG, " => executing next step on "
-              + this + " nextState=" + nextState);
+            Slog.i(RefactoredBackupManagerService.TAG, " => executing next step on "
+                    + this + " nextState=" + nextState);
         }
         mState = nextState;
         Message msg = backupManagerService.mBackupHandler.obtainMessage(
-            RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
+                RefactoredBackupManagerService.MSG_BACKUP_RESTORE_STEP, this);
         backupManagerService.mBackupHandler.sendMessage(msg);
     }
 
@@ -1262,7 +1308,8 @@
             try {
                 mObserver.restoreStarting(numPackages);
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "Restore observer went away: startRestore");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "Restore observer went away: startRestore");
                 mObserver = null;
             }
         }
@@ -1286,7 +1333,8 @@
             try {
                 mObserver.restoreFinished(mStatus);
             } catch (RemoteException e) {
-                Slog.w(RefactoredBackupManagerService.TAG, "Restore observer went away: endRestore");
+                Slog.w(RefactoredBackupManagerService.TAG,
+                        "Restore observer went away: endRestore");
                 mObserver = null;
             }
         }
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 8003d21..42ea713 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -20,17 +20,19 @@
 
 LOCAL_JAVA_LIBRARIES := \
     services.net \
-    android.hardware.light@2.0-java \
-    android.hardware.power@1.0-java \
-    android.hardware.tv.cec@1.0-java \
-    android.hidl.manager@1.0-java
+    android.hardware.light-V2.0-java \
+    android.hardware.power-V1.0-java \
+    android.hardware.tv.cec-V1.0-java \
+    android.hidl.manager-V1.0-java
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     tzdata_shared2 \
     tzdata_update2 \
-    android.hidl.base@1.0-java-static \
-    android.hardware.biometrics.fingerprint@2.1-java-static \
-    android.hardware.vibrator@1.0-java-constants \
+    android.hidl.base-V1.0-java-static \
+    android.hardware.weaver-V1.0-java-static \
+    android.hardware.biometrics.fingerprint-V2.1-java-static \
+    android.hardware.oemlock-V1.0-java-static \
+    android.hardware.vibrator-V1.0-java-constants \
 
 ifneq ($(INCREMENTAL_BUILDS),)
     LOCAL_PROGUARD_ENABLED := disabled
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index a93b801..4e2f396 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -29,6 +29,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.Nullable;
 import android.app.BroadcastOptions;
@@ -3326,13 +3327,6 @@
         Slog.e(TAG, s, t);
     }
 
-    private static <T> T checkNotNull(T value, String message) {
-        if (value == null) {
-            throw new NullPointerException(message);
-        }
-        return value;
-    }
-
     /**
      * Prepare for a VPN application.
      * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId},
@@ -4452,17 +4446,24 @@
         int last = 0;
         for (InetAddress dns : dnses) {
             ++last;
-            String key = "net.dns" + last;
-            String value = dns.getHostAddress();
-            mSystemProperties.set(key, value);
+            setNetDnsProperty(last, dns.getHostAddress());
         }
         for (int i = last + 1; i <= mNumDnsEntries; ++i) {
-            String key = "net.dns" + i;
-            mSystemProperties.set(key, "");
+            setNetDnsProperty(i, "");
         }
         mNumDnsEntries = last;
     }
 
+    private void setNetDnsProperty(int which, String value) {
+        final String key = "net.dns" + which;
+        // Log and forget errors setting unsupported properties.
+        try {
+            mSystemProperties.set(key, value);
+        } catch (Exception e) {
+            Log.e(TAG, "Error setting unsupported net.dns property: ", e);
+        }
+    }
+
     private String getNetworkPermission(NetworkCapabilities nc) {
         // TODO: make these permission strings AIDL constants instead.
         if (!nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
@@ -4624,8 +4625,8 @@
         msg.setData(bundle);
         try {
             if (VDBG) {
-                log("sending notification " + notifyTypeToName(notificationType) +
-                        " for " + nri.request);
+                String notification = ConnectivityManager.getCallbackName(notificationType);
+                log("sending notification " + notification + " for " + nri.request);
             }
             nri.messenger.send(msg);
         } catch (RemoteException e) {
@@ -5235,7 +5236,10 @@
     }
 
     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) {
-        if (VDBG) log("notifyType " + notifyTypeToName(notifyType) + " for " + networkAgent.name());
+        if (VDBG) {
+            String notification = ConnectivityManager.getCallbackName(notifyType);
+            log("notifyType " + notification + " for " + networkAgent.name());
+        }
         for (int i = 0; i < networkAgent.numNetworkRequests(); i++) {
             NetworkRequest nr = networkAgent.requestAt(i);
             NetworkRequestInfo nri = mNetworkRequests.get(nr);
@@ -5254,20 +5258,6 @@
         notifyNetworkCallbacks(networkAgent, notifyType, 0);
     }
 
-    private String notifyTypeToName(int notifyType) {
-        switch (notifyType) {
-            case ConnectivityManager.CALLBACK_PRECHECK:    return "PRECHECK";
-            case ConnectivityManager.CALLBACK_AVAILABLE:   return "AVAILABLE";
-            case ConnectivityManager.CALLBACK_LOSING:      return "LOSING";
-            case ConnectivityManager.CALLBACK_LOST:        return "LOST";
-            case ConnectivityManager.CALLBACK_UNAVAIL:     return "UNAVAILABLE";
-            case ConnectivityManager.CALLBACK_CAP_CHANGED: return "CAP_CHANGED";
-            case ConnectivityManager.CALLBACK_IP_CHANGED:  return "IP_CHANGED";
-            case ConnectivityManager.CALLBACK_RELEASED:    return "RELEASED";
-        }
-        return "UNKNOWN";
-    }
-
     /**
      * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
      * properties tracked by NetworkStatsService on an active iface has changed.
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 2e61550..6502c01 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -25,7 +25,7 @@
 # This is logged when the screen on broadcast has completed
 2727 power_screen_broadcast_stop (which|1|5),(wakelockCount|1|1)
 # This is logged when the screen is turned on or off.
-2728 power_screen_state (offOrOn|1|5),(becauseOfUser|1|5),(totalTouchDownTime|2|3),(touchCycles|1|1)
+2728 power_screen_state (offOrOn|1|5),(becauseOfUser|1|5),(totalTouchDownTime|2|3),(touchCycles|1|1),(latency|1|3)
 # This is logged when the partial wake lock (keeping the device awake
 # regardless of whether the screen is off) is acquired or released.
 2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3)
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 39bfeda..8ad3d23 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -49,6 +49,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.BinderThread;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -2146,6 +2147,7 @@
         return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
     }
 
+    @BinderThread
     @SuppressWarnings("deprecation")
     @Override
     public void setImeWindowStatus(IBinder token, IBinder startInputToken, int vis,
@@ -2161,9 +2163,23 @@
             mBackDisposition = backDisposition;
             updateSystemUiLocked(token, vis, backDisposition);
         }
+
+        final boolean dismissImeOnBackKeyPressed;
+        switch (backDisposition) {
+            case InputMethodService.BACK_DISPOSITION_WILL_DISMISS:
+                dismissImeOnBackKeyPressed = true;
+                break;
+            case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS:
+                dismissImeOnBackKeyPressed = false;
+                break;
+            default:
+            case InputMethodService.BACK_DISPOSITION_DEFAULT:
+                dismissImeOnBackKeyPressed = ((vis & InputMethodService.IME_VISIBLE) != 0);
+                break;
+        }
         mWindowManagerInternal.updateInputMethodWindowStatus(token,
                 (vis & InputMethodService.IME_VISIBLE) != 0,
-                info != null ? info.mTargetWindow : null);
+                dismissImeOnBackKeyPressed, info != null ? info.mTargetWindow : null);
     }
 
     private void updateSystemUi(IBinder token, int vis, int backDisposition) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index e26630b..db6e4f5 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -541,6 +541,7 @@
         migrateOldData();
         try {
             getGateKeeperService();
+            mSpManager.initWeaverService();
         } catch (RemoteException e) {
             Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
         }
@@ -1662,6 +1663,7 @@
     }
 
     private void removeUser(int userId, boolean unknownUser) {
+        mSpManager.removeUser(userId);
         mStorage.removeUser(userId);
         mStrongAuth.removeUser(userId);
 
diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java
index f5bae7c..761ae44 100644
--- a/services/core/java/com/android/server/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/LockSettingsStorage.java
@@ -37,6 +37,9 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Storage for the lock settings service.
@@ -442,6 +445,35 @@
         }
     }
 
+    public Map<Integer, List<Long>> listSyntheticPasswordHandlesForAllUsers(String stateName) {
+        Map<Integer, List<Long>> result = new ArrayMap<>();
+        final UserManager um = UserManager.get(mContext);
+        for (UserInfo user : um.getUsers(false)) {
+            result.put(user.id, listSyntheticPasswordHandlesForUser(stateName, user.id));
+        }
+        return result;
+    }
+
+    public List<Long> listSyntheticPasswordHandlesForUser(String stateName, int userId) {
+        File baseDir = getSyntheticPasswordDirectoryForUser(userId);
+        List<Long> result = new ArrayList<>();
+        File[] files = baseDir.listFiles();
+        if (files == null) {
+            return result;
+        }
+        for (File file : files) {
+            String[] parts = file.getName().split("\\.");
+            if (parts.length == 2 && parts[1].equals(stateName)) {
+                try {
+                    result.add(Long.parseUnsignedLong(parts[0], 16));
+                } catch (NumberFormatException e) {
+                    Slog.e(TAG, "Failed to parse handle " + parts[0]);
+                }
+            }
+        }
+        return result;
+    }
+
     @VisibleForTesting
     protected File getSyntheticPasswordDirectoryForUser(int userId) {
         return new File(Environment.getDataSystemDeDirectory(userId) ,SYNTHETIC_PASSWORD_DIRECTORY);
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index 26e471e..7080c41 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -23,6 +23,7 @@
 import android.os.AsyncTask;
 import android.os.RecoverySystem;
 import android.os.storage.StorageManager;
+import android.telephony.euicc.EuiccManager;
 import android.util.Log;
 import android.util.Slog;
 import android.view.WindowManager;
@@ -33,6 +34,8 @@
 
 public class MasterClearReceiver extends BroadcastReceiver {
     private static final String TAG = "MasterClear";
+    private boolean mWipeExternalStorage;
+    private boolean mWipeEims;
 
     @Override
     public void onReceive(final Context context, final Intent intent) {
@@ -53,8 +56,8 @@
 
         final boolean shutdown = intent.getBooleanExtra("shutdown", false);
         final String reason = intent.getStringExtra(Intent.EXTRA_REASON);
-        final boolean wipeExternalStorage = intent.getBooleanExtra(
-                Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);
+        mWipeExternalStorage = intent.getBooleanExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);
+        mWipeEims = intent.getBooleanExtra(Intent.EXTRA_WIPE_ESIMS, false);
         final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false)
                 || intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false);
 
@@ -74,20 +77,20 @@
             }
         };
 
-        if (wipeExternalStorage) {
+        if (mWipeExternalStorage || mWipeEims) {
             // thr will be started at the end of this task.
-            new WipeAdoptableDisksTask(context, thr).execute();
+            new WipeDataTask(context, thr).execute();
         } else {
             thr.start();
         }
     }
 
-    private class WipeAdoptableDisksTask extends AsyncTask<Void, Void, Void> {
+    private class WipeDataTask extends AsyncTask<Void, Void, Void> {
         private final Thread mChainedTask;
         private final Context mContext;
         private final ProgressDialog mProgressDialog;
 
-        public WipeAdoptableDisksTask(Context context, Thread chainedTask) {
+        public WipeDataTask(Context context, Thread chainedTask) {
             mContext = context;
             mChainedTask = chainedTask;
             mProgressDialog = new ProgressDialog(context);
@@ -104,9 +107,16 @@
         @Override
         protected Void doInBackground(Void... params) {
             Slog.w(TAG, "Wiping adoptable disks");
-            StorageManager sm = (StorageManager) mContext.getSystemService(
-                    Context.STORAGE_SERVICE);
-            sm.wipeAdoptableDisks();
+            if (mWipeExternalStorage) {
+                StorageManager sm = (StorageManager) mContext.getSystemService(
+                        Context.STORAGE_SERVICE);
+                sm.wipeAdoptableDisks();
+            }
+            if (mWipeEims) {
+                EuiccManager euiccManager = (EuiccManager) mContext.getSystemService(
+                        Context.EUICC_SERVICE);
+                // STOPSHIP: add EuiccManager API to factory reset eUICC
+            }
             return null;
         }
 
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 9218c25..d25b3cc 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -84,6 +84,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BiConsumer;
+import java.util.function.Function;
 import java.util.function.Supplier;
 import java.util.function.UnaryOperator;
 
@@ -106,6 +107,7 @@
     private final Object mServiceConnectionLock = new Object();
     private final Handler mHandler;
     private final DispatchingContentObserver mContentObserver;
+    private final Function<NetworkScorerAppData, ScoringServiceConnection> mServiceConnProducer;
 
     @GuardedBy("mPackageMonitorLock")
     private NetworkScorerPackageMonitor mPackageMonitor;
@@ -238,11 +240,13 @@
     }
 
     public NetworkScoreService(Context context) {
-      this(context, new NetworkScorerAppManager(context), Looper.myLooper());
+      this(context, new NetworkScorerAppManager(context),
+              ScoringServiceConnection::new, Looper.myLooper());
     }
 
     @VisibleForTesting
     NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager,
+            Function<NetworkScorerAppData, ScoringServiceConnection> serviceConnProducer,
             Looper looper) {
         mContext = context;
         mNetworkScorerAppManager = networkScoreAppManager;
@@ -257,6 +261,7 @@
         mRecommendationRequestTimeoutMs = TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS;
         mHandler = new ServiceHandler(looper);
         mContentObserver = new DispatchingContentObserver(context, mHandler);
+        mServiceConnProducer = serviceConnProducer;
     }
 
     /** Called when the system is ready to run third-party code but before it actually does so. */
@@ -356,17 +361,17 @@
             synchronized (mServiceConnectionLock) {
                 // If we're connected to a different component then drop it.
                 if (mServiceConnection != null
-                        && !mServiceConnection.mAppData.equals(appData)) {
+                        && !mServiceConnection.getAppData().equals(appData)) {
                     unbindFromScoringServiceIfNeeded();
                 }
 
                 // If we're not connected at all then create a new connection.
                 if (mServiceConnection == null) {
-                    mServiceConnection = new ScoringServiceConnection(appData);
+                    mServiceConnection = mServiceConnProducer.apply(appData);
                 }
 
                 // Make sure the connection is connected (idempotent)
-                mServiceConnection.connect(mContext);
+                mServiceConnection.bind(mContext);
             }
         } else { // otherwise make sure it isn't bound.
             unbindFromScoringServiceIfNeeded();
@@ -377,9 +382,9 @@
         if (DBG) Log.d(TAG, "unbindFromScoringServiceIfNeeded");
         synchronized (mServiceConnectionLock) {
             if (mServiceConnection != null) {
-                mServiceConnection.disconnect(mContext);
+                mServiceConnection.unbind(mContext);
                 if (DBG) Log.d(TAG, "Disconnected from: "
-                        + mServiceConnection.mAppData.getRecommendationServiceComponent());
+                        + mServiceConnection.getAppData().getRecommendationServiceComponent());
             }
             mServiceConnection = null;
         }
@@ -687,7 +692,7 @@
     public boolean isCallerActiveScorer(int callingUid) {
         synchronized (mServiceConnectionLock) {
             return mServiceConnection != null
-                    && mServiceConnection.mAppData.packageUid == callingUid;
+                    && mServiceConnection.getAppData().packageUid == callingUid;
         }
     }
 
@@ -720,7 +725,7 @@
         if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) {
             synchronized (mServiceConnectionLock) {
                 if (mServiceConnection != null) {
-                    return mServiceConnection.mAppData;
+                    return mServiceConnection.getAppData();
                 }
             }
         } else {
@@ -1020,7 +1025,9 @@
         mReqRecommendationCallerRef.set(new RequestRecommendationCaller(timeoutMs));
     }
 
-    private static class ScoringServiceConnection implements ServiceConnection {
+    // The class and methods need to be public for Mockito to work.
+    @VisibleForTesting
+    public static class ScoringServiceConnection implements ServiceConnection {
         private final NetworkScorerAppData mAppData;
         private volatile boolean mBound = false;
         private volatile boolean mConnected = false;
@@ -1030,7 +1037,8 @@
             mAppData = appData;
         }
 
-        void connect(Context context) {
+        @VisibleForTesting
+        public void bind(Context context) {
             if (!mBound) {
                 Intent service = new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS);
                 service.setComponent(mAppData.getRecommendationServiceComponent());
@@ -1039,13 +1047,15 @@
                         UserHandle.SYSTEM);
                 if (!mBound) {
                     Log.w(TAG, "Bind call failed for " + service);
+                    context.unbindService(this);
                 } else {
                     if (DBG) Log.d(TAG, "ScoringServiceConnection bound.");
                 }
             }
         }
 
-        void disconnect(Context context) {
+        @VisibleForTesting
+        public void unbind(Context context) {
             try {
                 if (mBound) {
                     mBound = false;
@@ -1056,17 +1066,30 @@
                 Log.e(TAG, "Unbind failed.", e);
             }
 
+            mConnected = false;
             mRecommendationProvider = null;
         }
 
-        INetworkRecommendationProvider getRecommendationProvider() {
+        @VisibleForTesting
+        public NetworkScorerAppData getAppData() {
+            return mAppData;
+        }
+
+        @VisibleForTesting
+        public INetworkRecommendationProvider getRecommendationProvider() {
             return mRecommendationProvider;
         }
 
-        String getPackageName() {
+        @VisibleForTesting
+        public String getPackageName() {
             return mAppData.getRecommendationServiceComponent().getPackageName();
         }
 
+        @VisibleForTesting
+        public boolean isAlive() {
+            return mBound && mConnected;
+        }
+
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DBG) Log.d(TAG, "ScoringServiceConnection: " + name.flattenToString());
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d796098..452fe1d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3272,6 +3272,8 @@
         try {
             return mContext.getSystemService(StorageStatsManager.class)
                     .queryStatsForUid(volumeUuid, uid).getCacheBytes();
+        } catch (IOException e) {
+            throw new ParcelableException(e);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -3312,6 +3314,8 @@
                     return Math.max(0, path.getUsableSpace() - storage.getStorageLowBytes(path));
                 }
             }
+        } catch (IOException e) {
+            throw new ParcelableException(e);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -3329,13 +3333,13 @@
                     + " because only " + allocatableBytes + " allocatable"));
         }
 
-        // Free up enough disk space to satisfy both the requested allocation
-        // and our low disk warning space.
-        final File path = storage.findPathForUuid(volumeUuid);
-        bytes += storage.getStorageLowBytes(path);
-
         final long token = Binder.clearCallingIdentity();
         try {
+            // Free up enough disk space to satisfy both the requested allocation
+            // and our low disk warning space.
+            final File path = storage.findPathForUuid(volumeUuid);
+            bytes += storage.getStorageLowBytes(path);
+
             mPms.freeStorage(volumeUuid, bytes, flags);
         } catch (IOException e) {
             throw new ParcelableException(e);
diff --git a/services/core/java/com/android/server/SyntheticPasswordManager.java b/services/core/java/com/android/server/SyntheticPasswordManager.java
index 2517613..d7e0c85 100644
--- a/services/core/java/com/android/server/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/SyntheticPasswordManager.java
@@ -17,12 +17,20 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.hardware.weaver.V1_0.IWeaver;
+import android.hardware.weaver.V1_0.WeaverConfig;
+import android.hardware.weaver.V1_0.WeaverReadResponse;
+import android.hardware.weaver.V1_0.WeaverReadStatus;
+import android.hardware.weaver.V1_0.WeaverStatus;
 import android.os.RemoteException;
+import android.security.GateKeeper;
 import android.service.gatekeeper.GateKeeperResponse;
 import android.service.gatekeeper.IGateKeeperService;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.VerifyCredentialResponse;
@@ -30,11 +38,15 @@
 import libcore.util.HexEncoding;
 
 import java.nio.ByteBuffer;
-import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 
 
@@ -48,6 +60,23 @@
  *   The SP has an associated password handle, which binds to the SID for that user. The password
  *   handle is persisted by SyntheticPasswordManager internally.
  *   If the user credential is null, it's treated as if the credential is DEFAULT_PASSWORD
+ *
+ * Information persisted on disk:
+ *   for each user (stored under DEFAULT_HANDLE):
+ *     SP_HANDLE_NAME: GateKeeper password handle of synthetic password. Only available if user
+ *                     credential exists, cleared when user clears their credential.
+ *     SP_E0_NAME, SP_P1_NAME: Secret to derive synthetic password when combining with escrow
+ *                     tokens. Destroyed when escrow support is turned off for the given user.
+ *
+ *     for each SP blob under the user (stored under the corresponding handle):
+ *       SP_BLOB_NAME: The encrypted synthetic password. Always exists.
+ *       PASSWORD_DATA_NAME: Metadata about user credential. Only exists for password based SP.
+ *       SECDISCARDABLE_NAME: Part of the necessary ingredient to decrypt SP_BLOB_NAME in order
+ *                            to facilitate secure deletion. Exists if this is a non-weaver SP
+ *                            (both password and token based), or it's a token-based SP under weaver.
+ *       WEAVER_SLOT: Metadata about the weaver slot used. Only exists if this is a SP under weaver.
+ *
+ *
  */
 public class SyntheticPasswordManager {
     private static final String SP_BLOB_NAME = "spblob";
@@ -57,10 +86,14 @@
     private static final String SECDISCARDABLE_NAME = "secdis";
     private static final int SECDISCARDABLE_LENGTH = 16 * 1024;
     private static final String PASSWORD_DATA_NAME = "pwd";
+    private static final String WEAVER_SLOT_NAME = "weaver";
 
-    public static final long DEFAULT_HANDLE = 0;
+    public static final long DEFAULT_HANDLE = 0L;
     private static final String DEFAULT_PASSWORD = "default-password";
 
+    private static final byte WEAVER_VERSION = 1;
+    private static final int INVALID_WEAVER_SLOT = -1;
+
     private static final byte SYNTHETIC_PASSWORD_VERSION = 1;
     private static final byte SYNTHETIC_PASSWORD_PASSWORD_BASED = 0;
     private static final byte SYNTHETIC_PASSWORD_TOKEN_BASED = 1;
@@ -82,6 +115,9 @@
     private static final byte[] PERSONALIZATION_FBE_KEY = "fbe-key".getBytes();
     private static final byte[] PERSONALIZATION_SP_SPLIT = "sp-split".getBytes();
     private static final byte[] PERSONALIZATION_E0 = "e0-encryption".getBytes();
+    private static final byte[] PERSONALISATION_WEAVER_PASSWORD = "weaver-pwd".getBytes();
+    private static final byte[] PERSONALISATION_WEAVER_KEY = "weaver-key".getBytes();
+    private static final byte[] PERSONALISATION_WEAVER_TOKEN = "weaver-token".getBytes();
 
     static class AuthenticationResult {
         public AuthenticationToken authToken;
@@ -149,6 +185,8 @@
         byte scryptP;
         public int passwordType;
         byte[] salt;
+        // For GateKeeper-based credential, this is the password handle returned by GK,
+        // for weaver-based credential, this is empty.
         public byte[] passwordHandle;
 
         public static PasswordData create(int passwordType) {
@@ -174,32 +212,176 @@
             result.salt = new byte[saltLen];
             buffer.get(result.salt);
             int handleLen = buffer.getInt();
-            result.passwordHandle = new byte[handleLen];
-            buffer.get(result.passwordHandle);
+            if (handleLen > 0) {
+                result.passwordHandle = new byte[handleLen];
+                buffer.get(result.passwordHandle);
+            } else {
+                result.passwordHandle = null;
+            }
             return result;
         }
 
         public byte[] toBytes() {
+
             ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES + 3 * Byte.BYTES
-                    + Integer.BYTES + salt.length + Integer.BYTES + passwordHandle.length);
+                    + Integer.BYTES + salt.length + Integer.BYTES +
+                    (passwordHandle != null ? passwordHandle.length : 0));
             buffer.putInt(passwordType);
             buffer.put(scryptN);
             buffer.put(scryptR);
             buffer.put(scryptP);
             buffer.putInt(salt.length);
             buffer.put(salt);
-            buffer.putInt(passwordHandle.length);
-            buffer.put(passwordHandle);
+            if (passwordHandle != null && passwordHandle.length > 0) {
+                buffer.putInt(passwordHandle.length);
+                buffer.put(passwordHandle);
+            } else {
+                buffer.putInt(0);
+            }
             return buffer.array();
         }
     }
 
+    static class TokenData {
+        byte[] secdiscardableOnDisk;
+        byte[] weaverSecret;
+        byte[] aggregatedSecret;
+    }
+
     private LockSettingsStorage mStorage;
+    private IWeaver mWeaver;
+    private WeaverConfig mWeaverConfig;
 
     public SyntheticPasswordManager(LockSettingsStorage storage) {
         mStorage = storage;
     }
 
+    @VisibleForTesting
+    protected IWeaver getWeaverService() throws RemoteException {
+        try {
+            return IWeaver.getService();
+        } catch (NoSuchElementException e) {
+            Slog.i(TAG, "Device does not support weaver");
+            return null;
+        }
+    }
+
+    public synchronized void initWeaverService() {
+        if (mWeaver != null) {
+            return;
+        }
+        try {
+            mWeaverConfig = null;
+            mWeaver = getWeaverService();
+            if (mWeaver != null) {
+                mWeaver.getConfig((int status, WeaverConfig config) -> {
+                    if (status == WeaverStatus.OK && config.slots > 0) {
+                        mWeaverConfig = config;
+                    } else {
+                        Slog.e(TAG, "Failed to get weaver config, status " + status
+                                + " slots: " + config.slots);
+                        mWeaver = null;
+                    }
+                });
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to get weaver service", e);
+        }
+    }
+
+    private synchronized boolean isWeaverAvailable() {
+        if (mWeaver == null) {
+            //Re-initializing weaver in case there was a transient error preventing access to it.
+            initWeaverService();
+        }
+        return mWeaver != null && mWeaverConfig.slots > 0;
+    }
+
+    /**
+     * Enroll the given key value pair into the specified weaver slot. if the given key is null,
+     * a default all-zero key is used. If the value is not specified, a fresh random secret is
+     * generated as the value.
+     *
+     * @return the value stored in the weaver slot
+     * @throws RemoteException
+     */
+    private byte[] weaverEnroll(int slot, byte[] key, @Nullable byte[] value)
+            throws RemoteException {
+        if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) {
+            throw new RuntimeException("Invalid slot for weaver");
+        }
+        if (key == null) {
+            key = new byte[mWeaverConfig.keySize];
+        } else if (key.length != mWeaverConfig.keySize) {
+            throw new RuntimeException("Invalid key size for weaver");
+        }
+        if (value == null) {
+            value = secureRandom(mWeaverConfig.valueSize);
+        }
+        int writeStatus = mWeaver.write(slot, toByteArrayList(key), toByteArrayList(value));
+        if (writeStatus != WeaverStatus.OK) {
+            Log.e(TAG, "weaver write failed, slot: " + slot + " status: " + writeStatus);
+            return null;
+        }
+        return value;
+    }
+
+    /**
+     * Verify the supplied key against a weaver slot, returning a response indicating whether
+     * the verification is successful, throttled or failed. If successful, the bound secret
+     * is also returned.
+     * @throws RemoteException
+     */
+    private VerifyCredentialResponse weaverVerify(int slot, byte[] key) throws RemoteException {
+        if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) {
+            throw new RuntimeException("Invalid slot for weaver");
+        }
+        if (key == null) {
+            key = new byte[mWeaverConfig.keySize];
+        } else if (key.length != mWeaverConfig.keySize) {
+            throw new RuntimeException("Invalid key size for weaver");
+        }
+        final VerifyCredentialResponse[] response = new VerifyCredentialResponse[1];
+        mWeaver.read(slot, toByteArrayList(key), (int status, WeaverReadResponse readResponse) -> {
+            switch (status) {
+                case WeaverReadStatus.OK:
+                    response[0] = new VerifyCredentialResponse(
+                            fromByteArrayList(readResponse.value));
+                    break;
+                case WeaverReadStatus.THROTTLE:
+                    response[0] = new VerifyCredentialResponse(readResponse.timeout);
+                    Log.e(TAG, "weaver read failed (THROTTLE), slot: " + slot);
+                    break;
+                case WeaverReadStatus.INCORRECT_KEY:
+                    if (readResponse.timeout == 0) {
+                        response[0] = VerifyCredentialResponse.ERROR;
+                        Log.e(TAG, "weaver read failed (INCORRECT_KEY), slot: " + slot);
+                    } else {
+                        response[0] = new VerifyCredentialResponse(readResponse.timeout);
+                        Log.e(TAG, "weaver read failed (INCORRECT_KEY/THROTTLE), slot: " + slot);
+                    }
+                    break;
+                case WeaverReadStatus.FAILED:
+                    response[0] = VerifyCredentialResponse.ERROR;
+                    Log.e(TAG, "weaver read failed (FAILED), slot: " + slot);
+                    break;
+               default:
+                   response[0] = VerifyCredentialResponse.ERROR;
+                   Log.e(TAG, "weaver read unknown status " + status + ", slot: " + slot);
+                   break;
+            }
+        });
+        return response[0];
+    }
+
+    public void removeUser(int userId) {
+        if (isWeaverAvailable()) {
+            for (long handle : mStorage.listSyntheticPasswordHandlesForUser(WEAVER_SLOT_NAME,
+                    userId)) {
+                destroyWeaverSlot(handle, userId);
+            }
+        }
+    }
 
     public int getCredentialType(long handle, int userId) {
         byte[] passwordData = loadState(PASSWORD_DATA_NAME, handle, userId);
@@ -221,7 +403,7 @@
      * If the existing credential hash is non-null, the existing SID mill be migrated so
      * the synthetic password in the authentication token will produce the same SID
      * (the corresponding synthetic password handle is persisted by SyntheticPasswordManager
-     * in a per-user data storage.
+     * in a per-user data storage.)
      *
      * If the existing credential hash is null, it means the given user should have no SID so
      * SyntheticPasswordManager will nuke any SP handle previously persisted. In this case,
@@ -308,6 +490,59 @@
         destroyState(SP_P1_NAME, true, DEFAULT_HANDLE, userId);
     }
 
+    private int loadWeaverSlot(long handle, int userId) {
+        final int LENGTH = Byte.BYTES + Integer.BYTES;
+        byte[] data = loadState(WEAVER_SLOT_NAME, handle, userId);
+        if (data == null || data.length != LENGTH) {
+            return INVALID_WEAVER_SLOT;
+        }
+        ByteBuffer buffer = ByteBuffer.allocate(LENGTH);
+        buffer.put(data, 0, data.length);
+        buffer.flip();
+        if (buffer.get() != WEAVER_VERSION) {
+            Log.e(TAG, "Invalid weaver slot version of handle " + handle);
+            return INVALID_WEAVER_SLOT;
+        }
+        return buffer.getInt();
+    }
+
+    private void saveWeaverSlot(int slot, long handle, int userId) {
+        ByteBuffer buffer = ByteBuffer.allocate(Byte.BYTES + Integer.BYTES);
+        buffer.put(WEAVER_VERSION);
+        buffer.putInt(slot);
+        saveState(WEAVER_SLOT_NAME, buffer.array(), handle, userId);
+    }
+
+    private void destroyWeaverSlot(long handle, int userId) {
+        int slot = loadWeaverSlot(handle, userId);
+        if (slot != INVALID_WEAVER_SLOT) {
+            try {
+                weaverEnroll(slot, null, null);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to destroy slot", e);
+            }
+        }
+        destroyState(WEAVER_SLOT_NAME, true, handle, userId);
+    }
+
+    private int getNextAvailableWeaverSlot() {
+        Map<Integer, List<Long>> slotHandles = mStorage.listSyntheticPasswordHandlesForAllUsers(
+                WEAVER_SLOT_NAME);
+        HashSet<Integer> slots = new HashSet<>();
+        for (Map.Entry<Integer, List<Long>> entry : slotHandles.entrySet()) {
+            for (Long handle : entry.getValue()) {
+                int slot = loadWeaverSlot(handle, entry.getKey());
+                slots.add(slot);
+            }
+        }
+        for (int i = 0; i < mWeaverConfig.slots; i++) {
+            if (!slots.contains(i)) {
+                return i;
+            }
+        }
+        throw new RuntimeException("Run out of weaver slots.");
+    }
+
     /**
      * Create a new password based SP blob based on the supplied authentication token, such that
      * a future successful authentication with unwrapPasswordBasedSyntheticPassword() would result
@@ -331,34 +566,62 @@
         long handle = generateHandle();
         PasswordData pwd = PasswordData.create(credentialType);
         byte[] pwdToken = computePasswordToken(credential, pwd);
+        final long sid;
+        final byte[] applicationId;
 
-        GateKeeperResponse response = gatekeeper.enroll(fakeUid(userId), null, null,
-                passwordTokenToGkInput(pwdToken));
-        if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
-            Log.e(TAG, "Fail to enroll user password when creating SP for user " + userId);
-            return 0;
+        if (isWeaverAvailable()) {
+            // Weaver based user password
+            int weaverSlot = getNextAvailableWeaverSlot();
+            byte[] weaverSecret = weaverEnroll(weaverSlot, passwordTokenToWeaverKey(pwdToken), null);
+            if (weaverSecret == null) {
+                Log.e(TAG, "Fail to enroll user password under weaver " + userId);
+                return DEFAULT_HANDLE;
+            }
+            saveWeaverSlot(weaverSlot, handle, userId);
+
+            pwd.passwordHandle = null;
+            sid = GateKeeper.INVALID_SECURE_USER_ID;
+            applicationId = transformUnderWeaverSecret(pwdToken, weaverSecret);
+        } else {
+            // GateKeeper based user password
+            GateKeeperResponse response = gatekeeper.enroll(fakeUid(userId), null, null,
+                    passwordTokenToGkInput(pwdToken));
+            if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
+                Log.e(TAG, "Fail to enroll user password when creating SP for user " + userId);
+                return DEFAULT_HANDLE;
+            }
+            pwd.passwordHandle = response.getPayload();
+            sid = sidFromPasswordHandle(pwd.passwordHandle);
+            applicationId = transformUnderSecdiscardable(pwdToken,
+                    createSecdiscardable(handle, userId));
         }
-        pwd.passwordHandle = response.getPayload();
-        long sid = sidFromPasswordHandle(pwd.passwordHandle);
         saveState(PASSWORD_DATA_NAME, pwd.toBytes(), handle, userId);
 
-        byte[] applicationId = transformUnderSecdiscardable(pwdToken,
-                createSecdiscardable(handle, userId));
         createSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED, authToken,
                 applicationId, sid, userId);
         return handle;
     }
 
-    private ArrayMap<Integer, ArrayMap<Long, byte[]>> tokenMap = new ArrayMap<>();
+    private ArrayMap<Integer, ArrayMap<Long, TokenData>> tokenMap = new ArrayMap<>();
 
     public long createTokenBasedSyntheticPassword(byte[] token, int userId) {
         long handle = generateHandle();
-        byte[] applicationId = transformUnderSecdiscardable(token,
-                createSecdiscardable(handle, userId));
         if (!tokenMap.containsKey(userId)) {
             tokenMap.put(userId, new ArrayMap<>());
         }
-        tokenMap.get(userId).put(handle, applicationId);
+        TokenData tokenData = new TokenData();
+        final byte[] secdiscardable = secureRandom(SECDISCARDABLE_LENGTH);
+        if (isWeaverAvailable()) {
+            tokenData.weaverSecret = secureRandom(mWeaverConfig.valueSize);
+            tokenData.secdiscardableOnDisk = SyntheticPasswordCrypto.encrypt(tokenData.weaverSecret,
+                            PERSONALISATION_WEAVER_TOKEN, secdiscardable);
+        } else {
+            tokenData.secdiscardableOnDisk = secdiscardable;
+            tokenData.weaverSecret = null;
+        }
+        tokenData.aggregatedSecret = transformUnderSecdiscardable(token, secdiscardable);
+
+        tokenMap.get(userId).put(handle, tokenData);
         return handle;
     }
 
@@ -381,16 +644,27 @@
         if (!tokenMap.containsKey(userId)) {
             return false;
         }
-        byte[] applicationId = tokenMap.get(userId).get(handle);
-        if (applicationId == null) {
+        TokenData tokenData = tokenMap.get(userId).get(handle);
+        if (tokenData == null) {
             return false;
         }
         if (!loadEscrowData(authToken, userId)) {
             Log.w(TAG, "User is not escrowable");
             return false;
         }
+        if (isWeaverAvailable()) {
+            int slot = getNextAvailableWeaverSlot();
+            try {
+                weaverEnroll(slot, null, tokenData.weaverSecret);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to enroll weaver secret when activating token", e);
+                return false;
+            }
+            saveWeaverSlot(slot, handle, userId);
+        }
+        saveSecdiscardable(handle, tokenData.secdiscardableOnDisk, userId);
         createSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_TOKEN_BASED, authToken,
-                applicationId, 0L, userId);
+                tokenData.aggregatedSecret, 0L, userId);
         tokenMap.get(userId).remove(handle);
         return true;
     }
@@ -424,35 +698,50 @@
         AuthenticationResult result = new AuthenticationResult();
         PasswordData pwd = PasswordData.fromBytes(loadState(PASSWORD_DATA_NAME, handle, userId));
         byte[] pwdToken = computePasswordToken(credential, pwd);
-        byte[] gkPwdToken = passwordTokenToGkInput(pwdToken);
 
-        GateKeeperResponse response = gatekeeper.verifyChallenge(fakeUid(userId), 0L,
-                pwd.passwordHandle, gkPwdToken);
-        int responseCode = response.getResponseCode();
-        if (responseCode == GateKeeperResponse.RESPONSE_OK) {
-            result.gkResponse = VerifyCredentialResponse.OK;
-            if (response.getShouldReEnroll()) {
-                GateKeeperResponse reenrollResponse = gatekeeper.enroll(fakeUid(userId),
-                        pwd.passwordHandle, gkPwdToken, gkPwdToken);
-                if (reenrollResponse.getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
-                    pwd.passwordHandle = reenrollResponse.getPayload();
-                    saveState(PASSWORD_DATA_NAME, pwd.toBytes(), handle, userId);
-                } else {
-                    Log.w(TAG, "Fail to re-enroll user password for user " + userId);
-                    // continue the flow anyway
-                }
+        final byte[] applicationId;
+        int weaverSlot = loadWeaverSlot(handle, userId);
+        if (weaverSlot != INVALID_WEAVER_SLOT) {
+            // Weaver based user password
+            if (!isWeaverAvailable()) {
+                Log.e(TAG, "No weaver service to unwrap password based SP");
+                result.gkResponse = VerifyCredentialResponse.ERROR;
+                return result;
             }
-        } else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
-            result.gkResponse = new VerifyCredentialResponse(response.getTimeout());
-            return result;
-        } else  {
-            result.gkResponse = VerifyCredentialResponse.ERROR;
-            return result;
+            result.gkResponse = weaverVerify(weaverSlot, passwordTokenToWeaverKey(pwdToken));
+            if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
+                return result;
+            }
+            applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload());
+        } else {
+            byte[] gkPwdToken = passwordTokenToGkInput(pwdToken);
+            GateKeeperResponse response = gatekeeper.verifyChallenge(fakeUid(userId), 0L,
+                    pwd.passwordHandle, gkPwdToken);
+            int responseCode = response.getResponseCode();
+            if (responseCode == GateKeeperResponse.RESPONSE_OK) {
+                result.gkResponse = VerifyCredentialResponse.OK;
+                if (response.getShouldReEnroll()) {
+                    GateKeeperResponse reenrollResponse = gatekeeper.enroll(fakeUid(userId),
+                            pwd.passwordHandle, gkPwdToken, gkPwdToken);
+                    if (reenrollResponse.getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
+                        pwd.passwordHandle = reenrollResponse.getPayload();
+                        saveState(PASSWORD_DATA_NAME, pwd.toBytes(), handle, userId);
+                    } else {
+                        Log.w(TAG, "Fail to re-enroll user password for user " + userId);
+                        // continue the flow anyway
+                    }
+                }
+            } else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
+                result.gkResponse = new VerifyCredentialResponse(response.getTimeout());
+                return result;
+            } else  {
+                result.gkResponse = VerifyCredentialResponse.ERROR;
+                return result;
+            }
+            applicationId = transformUnderSecdiscardable(pwdToken,
+                    loadSecdiscardable(handle, userId));
         }
 
-
-        byte[] applicationId = transformUnderSecdiscardable(pwdToken,
-                loadSecdiscardable(handle, userId));
         result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED,
                 applicationId, userId);
 
@@ -470,8 +759,25 @@
             IGateKeeperService gatekeeper, long handle, byte[] token, int userId)
                     throws RemoteException {
         AuthenticationResult result = new AuthenticationResult();
-        byte[] applicationId = transformUnderSecdiscardable(token,
-                loadSecdiscardable(handle, userId));
+        byte[] secdiscardable = loadSecdiscardable(handle, userId);
+        int slotId = loadWeaverSlot(handle, userId);
+        if (slotId != INVALID_WEAVER_SLOT) {
+            if (!isWeaverAvailable()) {
+                Log.e(TAG, "No weaver service to unwrap token based SP");
+                result.gkResponse = VerifyCredentialResponse.ERROR;
+                return result;
+            }
+            VerifyCredentialResponse response = weaverVerify(slotId, null);
+            if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK ||
+                    response.getPayload() == null) {
+                Log.e(TAG, "Failed to retrieve weaver secret when unwrapping token");
+                result.gkResponse = VerifyCredentialResponse.ERROR;
+                return result;
+            }
+            secdiscardable = SyntheticPasswordCrypto.decrypt(response.getPayload(),
+                    PERSONALISATION_WEAVER_TOKEN, secdiscardable);
+        }
+        byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable);
         result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_TOKEN_BASED,
                 applicationId, userId);
         if (result.authToken != null) {
@@ -578,9 +884,19 @@
 
     private void destroySyntheticPassword(long handle, int userId) {
         destroyState(SP_BLOB_NAME, true, handle, userId);
-        destroyState(SP_E0_NAME, true, handle, userId);
-        destroyState(SP_P1_NAME, true, handle, userId);
         destroySPBlobKey(getHandleName(handle));
+        if (hasState(WEAVER_SLOT_NAME, handle, userId)) {
+            destroyWeaverSlot(handle, userId);
+        }
+    }
+
+    private byte[] transformUnderWeaverSecret(byte[] data, byte[] secret) {
+        byte[] weaverSecret = SyntheticPasswordCrypto.personalisedHash(
+                PERSONALISATION_WEAVER_PASSWORD, secret);
+        byte[] result = new byte[data.length + weaverSecret.length];
+        System.arraycopy(data, 0, result, 0, data.length);
+        System.arraycopy(weaverSecret, 0, result, data.length, weaverSecret.length);
+        return result;
     }
 
     private byte[] transformUnderSecdiscardable(byte[] data, byte[] rawSecdiscardable) {
@@ -594,10 +910,14 @@
 
     private byte[] createSecdiscardable(long handle, int userId) {
         byte[] data = secureRandom(SECDISCARDABLE_LENGTH);
-        saveState(SECDISCARDABLE_NAME, data, handle, userId);
+        saveSecdiscardable(handle, data, userId);
         return data;
     }
 
+    private void saveSecdiscardable(long handle, byte[] secdiscardable, int userId) {
+        saveState(SECDISCARDABLE_NAME, secdiscardable, handle, userId);
+    }
+
     private byte[] loadSecdiscardable(long handle, int userId) {
         return loadState(SECDISCARDABLE_NAME, handle, userId);
     }
@@ -665,6 +985,14 @@
         return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_USER_GK_AUTH, token);
     }
 
+    private byte[] passwordTokenToWeaverKey(byte[] token) {
+        byte[] key = SyntheticPasswordCrypto.personalisedHash(PERSONALISATION_WEAVER_KEY, token);
+        if (key.length < mWeaverConfig.keySize) {
+            throw new RuntimeException("weaver key length too small");
+        }
+        return Arrays.copyOf(key, mWeaverConfig.keySize);
+    }
+
     protected long sidFromPasswordHandle(byte[] handle) {
         return nativeSidFromPasswordHandle(handle);
     }
@@ -676,6 +1004,22 @@
     native long nativeSidFromPasswordHandle(byte[] handle);
     native byte[] nativeScrypt(byte[] password, byte[] salt, int N, int r, int p, int outLen);
 
+    protected static ArrayList<Byte> toByteArrayList(byte[] data) {
+        ArrayList<Byte> result = new ArrayList<Byte>(data.length);
+        for (int i = 0; i < data.length; i++) {
+            result.add(data[i]);
+        }
+        return result;
+    }
+
+    protected static byte[] fromByteArrayList(ArrayList<Byte> data) {
+        byte[] result = new byte[data.size()];
+        for (int i = 0; i < data.size(); i++) {
+            result[i] = data.get(i);
+        }
+        return result;
+    }
+
     final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
     public static String bytesToHex(byte[] bytes) {
         if (bytes == null) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 5f585cc..eb58e4c 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -959,6 +959,12 @@
         mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
     }
 
+    private void sendAccountRemovedBroadcast(int userId) {
+        Intent intent = new Intent(AccountManager.ACTION_ACCOUNT_REMOVED);
+        intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        mContext.sendBroadcastAsUser(intent, new UserHandle(userId));
+    }
+
     @Override
     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
             throws RemoteException {
@@ -1111,6 +1117,7 @@
                                     notifyPackage(packageToVisibility.getKey(), accounts);
                                 }
                             }
+                            sendAccountRemovedBroadcast(accounts.userId);
                         } else {
                             ArrayList<String> accountNames = accountNamesByType.get(account.type);
                             if (accountNames == null) {
@@ -1971,6 +1978,7 @@
 
                 sendNotificationAccountUpdated(resultAccount, accounts);
                 sendAccountsChangedBroadcast(accounts.userId);
+                sendAccountRemovedBroadcast(accounts.userId);
             }
         }
         return resultAccount;
@@ -2206,6 +2214,7 @@
 
                     // Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occurred.
                     sendAccountsChangedBroadcast(accounts.userId);
+                    sendAccountRemovedBroadcast(accounts.userId);
                     String action = userUnlocked ? AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE
                             : AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE_DE;
                     logRecord(action, AccountsDb.TABLE_ACCOUNTS, accountId, accounts);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index c77820b..2cd14e9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -312,8 +312,7 @@
     }
 
     ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
-            int id, Notification notification, int callingPid, int callingUid,
-            boolean fgRequired, String callingPackage, final int userId)
+            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
             throws TransactionTooLargeException {
         if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
                 + " type=" + resolvedType + " args=" + service.getExtras());
@@ -464,10 +463,6 @@
         }
 
         ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
-        // STOPSHIP deprecated; remove when NotificationManager.startServiceInForeground is retired
-        if (notification != null) {
-            setServiceForegroundInnerLocked(r, id, notification, 0);
-        }
         return cmp;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index df250b1..55ee183 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -32,16 +32,10 @@
  */
 final class ActivityManagerConstants extends ContentObserver {
     // Key names stored in the settings value.
-    private static final String KEY_ENFORCE_BG_CHECK = "enforce_bg_check";
     private static final String KEY_MAX_CACHED_PROCESSES = "max_cached_processes";
 
-    private static final boolean DEFAULT_ENFORCE_BG_CHECK = SystemProperties.getBoolean(
-            "debug.bgcheck", true);
     private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
 
-    // Enforce background check on apps targeting O?
-    public boolean ENFORCE_BG_CHECK = DEFAULT_ENFORCE_BG_CHECK;
-
     // Maximum number of cached processes we will allow.
     public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
 
@@ -115,7 +109,6 @@
                 // with defaults.
                 Slog.e("ActivityManagerConstants", "Bad activity manager config settings", e);
             }
-            ENFORCE_BG_CHECK = mParser.getBoolean(KEY_ENFORCE_BG_CHECK, DEFAULT_ENFORCE_BG_CHECK);
             MAX_CACHED_PROCESSES = mParser.getInt(KEY_MAX_CACHED_PROCESSES,
                     DEFAULT_MAX_CACHED_PROCESSES);
             updateMaxCachedProcesses();
@@ -139,9 +132,6 @@
         pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
                 + Settings.Global.ACTIVITY_MANAGER_CONSTANTS + ":");
 
-        pw.print("  "); pw.print(KEY_ENFORCE_BG_CHECK); pw.print("=");
-        pw.println(ENFORCE_BG_CHECK);
-
         pw.print("  "); pw.print(KEY_MAX_CACHED_PROCESSES); pw.print("=");
         pw.println(MAX_CACHED_PROCESSES);
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3094f1a..7903c44 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -71,7 +71,6 @@
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
 import static android.os.Process.getFreeMemory;
-import static android.os.Process.getThreadPriority;
 import static android.os.Process.getTotalMemory;
 import static android.os.Process.isThreadInProcess;
 import static android.os.Process.killProcess;
@@ -1231,6 +1230,20 @@
      */
     int[] mDeviceIdleTempWhitelist = new int[0];
 
+    static final class PendingTempWhitelist {
+        final int targetUid;
+        final long duration;
+        final String tag;
+
+        PendingTempWhitelist(int _targetUid, long _duration, String _tag) {
+            targetUid = _targetUid;
+            duration = _duration;
+            tag = _tag;
+        }
+    }
+
+    final SparseArray<PendingTempWhitelist> mPendingTempWhitelist = new SparseArray<>();
+
     /**
      * Information about and control over application operations
      */
@@ -1688,6 +1701,8 @@
     static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 64;
     static final int NOTIFY_VR_SLEEPING_MSG = 65;
     static final int SERVICE_FOREGROUND_TIMEOUT_MSG = 66;
+    static final int DISPATCH_PENDING_INTENT_CANCEL_MSG = 67;
+    static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
     static final int START_USER_SWITCH_FG_MSG = 712;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -1921,6 +1936,9 @@
             case DISPATCH_UIDS_CHANGED_UI_MSG: {
                 dispatchUidsChanged();
             } break;
+            case PUSH_TEMP_WHITELIST_UI_MSG: {
+                pushTempWhitelist();
+            } break;
             }
         }
     }
@@ -1956,6 +1974,18 @@
             case SERVICE_FOREGROUND_TIMEOUT_MSG: {
                 mServices.serviceForegroundTimeout((ServiceRecord)msg.obj);
             } break;
+            case DISPATCH_PENDING_INTENT_CANCEL_MSG: {
+                RemoteCallbackList<IResultReceiver> callbacks
+                        = (RemoteCallbackList<IResultReceiver>)msg.obj;
+                int N = callbacks.beginBroadcast();
+                for (int i = 0; i < N; i++) {
+                    try {
+                        callbacks.getBroadcastItem(i).send(Activity.RESULT_CANCELED, null);
+                    } catch (RemoteException e) {
+                    }
+                }
+                callbacks.finishBroadcast();
+            } break;
             case UPDATE_TIME_ZONE: {
                 synchronized (ActivityManagerService.this) {
                     for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
@@ -2705,17 +2735,6 @@
 
         mConstants = new ActivityManagerConstants(this, mHandler);
 
-        if (DEBUG_BACKGROUND_CHECK) {
-            Slog.d(TAG, "Enforcing O+ bg restrictions: " + mConstants.ENFORCE_BG_CHECK);
-            StringBuilder sb = new StringBuilder(200);
-            sb.append("  ");
-            for (String a : getBackgroundLaunchBroadcasts()) {
-                sb.append(' '); sb.append(a);
-            }
-            Slog.d(TAG, "Background implicit broadcasts:");
-            Slog.d(TAG, sb.toString());
-        }
-
         /* static; one-time init here */
         if (sKillHandler == null) {
             sKillThread = new ServiceThread(TAG + ":kill",
@@ -3878,7 +3897,8 @@
             // the per-user SELinux context must be set
             if (TextUtils.isEmpty(app.info.seInfoUser)) {
                 Slog.wtf(TAG, "SELinux tag not defined",
-                        new IllegalStateException("SELinux tag not defined"));
+                        new IllegalStateException("SELinux tag not defined for "
+                        + app.info.packageName + " (uid " + app.uid + ")"));
             }
             final String seInfo = app.info.seInfo
                     + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
@@ -6422,7 +6442,7 @@
                     }
                     didSomething = true;
                     it.remove();
-                    pir.canceled = true;
+                    makeIntentSenderCanceledLocked(pir);
                     if (pir.key.activity != null && pir.key.activity.pendingResults != null) {
                         pir.key.activity.pendingResults.remove(pir.ref);
                     }
@@ -6491,7 +6511,8 @@
             // This is the first appearance of the uid, report it now!
             if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                     "Creating new process uid: " + uidRec);
-            if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0) {
+            if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0
+                    || mPendingTempWhitelist.indexOfKey(proc.uid) >= 0) {
                 uidRec.setWhitelist = uidRec.curWhitelist = true;
             }
             uidRec.updateHasInternetPermission();
@@ -7432,7 +7453,7 @@
                 }
                 return rec;
             }
-            rec.canceled = true;
+            makeIntentSenderCanceledLocked(rec);
             mIntentSenderRecords.remove(key);
         }
         if (noCreate) {
@@ -7485,43 +7506,6 @@
         }
     }
 
-    /**
-     * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
-     */
-    void tempWhitelistAppForPowerSave(int callerPid, int callerUid, int targetUid, long duration) {
-        if (DEBUG_WHITELISTS) {
-            Slog.d(TAG, "tempWhitelistAppForPowerSave(" + callerPid + ", " + callerUid + ", "
-                    + targetUid + ", " + duration + ")");
-        }
-
-        if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
-                != PackageManager.PERMISSION_GRANTED) {
-            synchronized (mPidsSelfLocked) {
-                final ProcessRecord pr = mPidsSelfLocked.get(callerPid);
-                if (pr == null) {
-                    Slog.w(TAG, "tempWhitelistAppForPowerSave() no ProcessRecord for pid "
-                            + callerPid);
-                    return;
-                }
-                if (!pr.whitelistManager) {
-                    if (DEBUG_WHITELISTS) {
-                        Slog.d(TAG, "tempWhitelistAppForPowerSave() for target " + targetUid
-                                + ": pid " + callerPid + " is not allowed");
-                    }
-                    return;
-                }
-            }
-        }
-
-        final long token = Binder.clearCallingIdentity();
-        try {
-            mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(targetUid, duration,
-                    true, "pe from uid:" + callerUid);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
     @Override
     public void cancelIntentSender(IIntentSender sender) {
         if (!(sender instanceof PendingIntentRecord)) {
@@ -7536,7 +7520,7 @@
                     String msg = "Permission Denial: cancelIntentSender() from pid="
                         + Binder.getCallingPid()
                         + ", uid=" + Binder.getCallingUid()
-                        + " is not allowed to cancel packges "
+                        + " is not allowed to cancel package "
                         + rec.key.packageName;
                     Slog.w(TAG, msg);
                     throw new SecurityException(msg);
@@ -7549,13 +7533,21 @@
     }
 
     void cancelIntentSenderLocked(PendingIntentRecord rec, boolean cleanActivity) {
-        rec.canceled = true;
+        makeIntentSenderCanceledLocked(rec);
         mIntentSenderRecords.remove(rec.key);
         if (cleanActivity && rec.key.activity != null) {
             rec.key.activity.pendingResults.remove(rec.ref);
         }
     }
 
+    void makeIntentSenderCanceledLocked(PendingIntentRecord rec) {
+        rec.canceled = true;
+        RemoteCallbackList<IResultReceiver> callbacks = rec.detachCancelListenersLocked();
+        if (callbacks != null) {
+            mHandler.obtainMessage(DISPATCH_PENDING_INTENT_CANCEL_MSG, callbacks).sendToTarget();
+        }
+    }
+
     @Override
     public String getPackageForIntentSender(IIntentSender pendingResult) {
         if (!(pendingResult instanceof PendingIntentRecord)) {
@@ -7570,6 +7562,27 @@
     }
 
     @Override
+    public void registerIntentSenderCancelListener(IIntentSender sender, IResultReceiver receiver) {
+        if (!(sender instanceof PendingIntentRecord)) {
+            return;
+        }
+        synchronized(this) {
+            ((PendingIntentRecord)sender).registerCancelListenerLocked(receiver);
+        }
+    }
+
+    @Override
+    public void unregisterIntentSenderCancelListener(IIntentSender sender,
+            IResultReceiver receiver) {
+        if (!(sender instanceof PendingIntentRecord)) {
+            return;
+        }
+        synchronized(this) {
+            ((PendingIntentRecord)sender).unregisterCancelListenerLocked(receiver);
+        }
+    }
+
+    @Override
     public int getUidForIntentSender(IIntentSender sender) {
         if (sender instanceof PendingIntentRecord) {
             try {
@@ -7832,10 +7845,15 @@
                     r.pictureInPictureArgs.copyOnlySet(args);
                     final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
                     final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
-                    final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint();
-                    final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
-                            aspectRatio);
-                    mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, destBounds,
+                    // Adjust the source bounds by the insets for the transition down
+                    final Rect sourceBounds = new Rect(r.pictureInPictureArgs.getSourceRectHint());
+                    final Rect insets = r.pictureInPictureArgs.getSourceRectHintInsets();
+                    if (insets != null) {
+                        sourceBounds.offsetTo(Math.max(0, sourceBounds.left - insets.left),
+                                Math.max(0, sourceBounds.top - insets.top));
+                    }
+
+                    mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio,
                             true /* moveHomeStackToFront */, "enterPictureInPictureMode");
                     final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
                     stack.setPictureInPictureAspectRatio(aspectRatio);
@@ -7896,7 +7914,7 @@
                     // if it is not already expanding to fullscreen. Otherwise, the arguments will
                     // be used the next time the activity enters PiP
                     final PinnedActivityStack stack = r.getStack();
-                    if (!stack.isBoundsAnimatingToFullscreen()) {
+                    if (!stack.isAnimatingBoundsToFullscreen()) {
                         stack.setPictureInPictureAspectRatio(
                                 r.pictureInPictureArgs.getAspectRatio());
                         stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
@@ -8267,7 +8285,7 @@
     // Unified app-op and target sdk check
     int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
         // Apps that target O+ are always subject to background check
-        if (mConstants.ENFORCE_BG_CHECK && packageTargetSdk >= Build.VERSION_CODES.O) {
+        if (packageTargetSdk >= Build.VERSION_CODES.O) {
             if (DEBUG_BACKGROUND_CHECK) {
                 Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
             }
@@ -8383,7 +8401,8 @@
     boolean isOnDeviceIdleWhitelistLocked(int uid) {
         final int appId = UserHandle.getAppId(uid);
         return Arrays.binarySearch(mDeviceIdleWhitelist, appId) >= 0
-                || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0;
+                || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0
+                || mPendingTempWhitelist.indexOfKey(uid) >= 0;
     }
 
     private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) {
@@ -10505,8 +10524,11 @@
                     if (stackId == PINNED_STACK_ID) {
                         final PinnedActivityStack pinnedStack =
                                 mStackSupervisor.getStack(PINNED_STACK_ID);
-                        pinnedStack.animateResizePinnedStack(null /* sourceBounds */, destBounds,
-                                animationDuration);
+                        if (pinnedStack != null) {
+                            pinnedStack.animateResizePinnedStack(null /* sourceHintBounds */,
+                                    destBounds, animationDuration,
+                                    false /* schedulePipModeChangedOnAnimationEnd */);
+                        }
                     } else {
                         throw new IllegalArgumentException("Stack: " + stackId
                                 + " doesn't support animated resize.");
@@ -10663,6 +10685,13 @@
             return;
         }
 
+        // When a task is locked, dismiss the pinned stack if it exists
+        final PinnedActivityStack pinnedStack = mStackSupervisor.getStack(
+                PINNED_STACK_ID);
+        if (pinnedStack != null) {
+            mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
+        }
+
         // isSystemInitiated is used to distinguish between locked and pinned mode, as pinned mode
         // is initiated by system after the pinning request was shown and locked mode is initiated
         // by an authorized app directly
@@ -14376,6 +14405,7 @@
         // concurrently during execution of this method)
         synchronized (this) {
             sb.append("Process: ").append(processName).append("\n");
+            sb.append("PID: ").append(process.pid).append("\n");
             int flags = process.info.flags;
             IPackageManager pm = AppGlobals.getPackageManager();
             sb.append("Flags: 0x").append(Integer.toHexString(flags)).append("\n");
@@ -15556,6 +15586,18 @@
             }
             pw.println("  mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
             pw.println("  mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
+            if (mPendingTempWhitelist.size() > 0) {
+                pw.println("  mPendingTempWhitelist:");
+                for (int i = 0; i < mPendingTempWhitelist.size(); i++) {
+                    PendingTempWhitelist ptw = mPendingTempWhitelist.valueAt(i);
+                    pw.print("    ");
+                    UserHandle.formatUid(pw, ptw.targetUid);
+                    pw.print(": ");
+                    TimeUtils.formatDuration(ptw.duration, pw);
+                    pw.print(" ");
+                    pw.println(ptw.tag);
+                }
+            }
         }
         if (dumpPackage == null) {
             pw.println("  mWakefulness="
@@ -16211,23 +16253,45 @@
         pw.println("ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)");
 
         if (mIntentSenderRecords.size() > 0) {
-            Iterator<WeakReference<PendingIntentRecord>> it
+            // Organize these by package name, so they are easier to read.
+            final ArrayMap<String, ArrayList<PendingIntentRecord>> byPackage = new ArrayMap<>();
+            final ArrayList<WeakReference<PendingIntentRecord>> weakRefs = new ArrayList<>();
+            final Iterator<WeakReference<PendingIntentRecord>> it
                     = mIntentSenderRecords.values().iterator();
             while (it.hasNext()) {
                 WeakReference<PendingIntentRecord> ref = it.next();
-                PendingIntentRecord rec = ref != null ? ref.get(): null;
-                if (dumpPackage != null && (rec == null
-                        || !dumpPackage.equals(rec.key.packageName))) {
+                PendingIntentRecord rec = ref != null ? ref.get() : null;
+                if (rec == null) {
+                    weakRefs.add(ref);
                     continue;
                 }
+                if (dumpPackage != null && !dumpPackage.equals(rec.key.packageName)) {
+                    continue;
+                }
+                ArrayList<PendingIntentRecord> list = byPackage.get(rec.key.packageName);
+                if (list == null) {
+                    list = new ArrayList<>();
+                    byPackage.put(rec.key.packageName, list);
+                }
+                list.add(rec);
+            }
+            for (int i = 0; i < byPackage.size(); i++) {
+                ArrayList<PendingIntentRecord> intents = byPackage.valueAt(i);
                 printed = true;
-                if (rec != null) {
-                    pw.print("  * "); pw.println(rec);
+                pw.print("  * "); pw.print(byPackage.keyAt(i));
+                pw.print(": "); pw.print(intents.size()); pw.println(" items");
+                for (int j = 0; j < intents.size(); j++) {
+                    pw.print("    #"); pw.print(j); pw.print(": "); pw.println(intents.get(j));
                     if (dumpAll) {
-                        rec.dump(pw, "    ");
+                        intents.get(j).dump(pw, "      ");
                     }
-                } else {
-                    pw.print("  * "); pw.println(ref);
+                }
+            }
+            if (weakRefs.size() > 0) {
+                printed = true;
+                pw.println("  * WEAK REFS:");
+                for (int i = 0; i < weakRefs.size(); i++) {
+                    pw.print("    #"); pw.print(i); pw.print(": "); pw.println(weakRefs.get(i));
                 }
             }
         }
@@ -17875,8 +17939,7 @@
 
     @Override
     public ComponentName startService(IApplicationThread caller, Intent service,
-            String resolvedType, int id, Notification notification, boolean requireForeground,
-            String callingPackage, int userId)
+            String resolvedType, boolean requireForeground, String callingPackage, int userId)
             throws TransactionTooLargeException {
         enforceNotIsolatedCaller("startService");
         // Refuse possible leaked file descriptors
@@ -17897,7 +17960,7 @@
             ComponentName res;
             try {
                 res = mServices.startServiceLocked(caller, service,
-                        resolvedType, id, notification, callingPid, callingUid,
+                        resolvedType, callingPid, callingUid,
                         requireForeground, callingPackage, userId);
             } finally {
                 Binder.restoreCallingIdentity(origId);
@@ -17916,7 +17979,7 @@
             ComponentName res;
             try {
                 res = mServices.startServiceLocked(null, service,
-                        resolvedType, 0, null, -1, uid, fgRequired, callingPackage, userId);
+                        resolvedType, -1, uid, fgRequired, callingPackage, userId);
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
@@ -22646,6 +22709,80 @@
         enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE);
     }
 
+    /**
+     * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
+     */
+    void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid,
+            long duration, String tag) {
+        if (DEBUG_WHITELISTS) {
+            Slog.d(TAG, "tempWhitelistForPendingIntentLocked(" + callerPid + ", " + callerUid + ", "
+                    + targetUid + ", " + duration + ")");
+        }
+
+        synchronized (mPidsSelfLocked) {
+            final ProcessRecord pr = mPidsSelfLocked.get(callerPid);
+            if (pr == null) {
+                Slog.w(TAG, "tempWhitelistForPendingIntentLocked() no ProcessRecord for pid "
+                        + callerPid);
+                return;
+            }
+            if (!pr.whitelistManager) {
+                if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    if (DEBUG_WHITELISTS) {
+                        Slog.d(TAG, "tempWhitelistForPendingIntentLocked() for target " + targetUid
+                                + ": pid " + callerPid + " is not allowed");
+                    }
+                    return;
+                }
+            }
+        }
+
+        tempWhitelistUidLocked(targetUid, duration, tag);
+    }
+
+    /**
+     * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
+     */
+    void tempWhitelistUidLocked(int targetUid, long duration, String tag) {
+        mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag));
+        setUidTempWhitelistStateLocked(targetUid, true);
+        mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget();
+    }
+
+    void pushTempWhitelist() {
+        final int N;
+        final PendingTempWhitelist[] list;
+
+        // First copy out the pending changes...  we need to leave them in the map for now,
+        // in case someone needs to check what is coming up while we don't have the lock held.
+        synchronized(this) {
+            N = mPendingTempWhitelist.size();
+            list = new PendingTempWhitelist[N];
+            for (int i = 0; i < N; i++) {
+                list[i] = mPendingTempWhitelist.valueAt(i);
+            }
+        }
+
+        // Now safely dispatch changes to device idle controller.
+        for (int i = 0; i < N; i++) {
+            PendingTempWhitelist ptw = list[i];
+            mLocalDeviceIdleController.addPowerSaveTempWhitelistAppDirect(ptw.targetUid,
+                    ptw.duration, true, ptw.tag);
+        }
+
+        // And now we can safely remove them from the map.
+        synchronized(this) {
+            for (int i = 0; i < N; i++) {
+                PendingTempWhitelist ptw = list[i];
+                int index = mPendingTempWhitelist.indexOfKey(ptw.targetUid);
+                if (index >= 0 && mPendingTempWhitelist.valueAt(index) == ptw) {
+                    mPendingTempWhitelist.removeAt(index);
+                }
+            }
+        }
+    }
+
     final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) {
         boolean changed = false;
         for (int i=mActiveUids.size()-1; i>=0; i--) {
@@ -22660,6 +22797,15 @@
         }
     }
 
+    final void setUidTempWhitelistStateLocked(int uid, boolean onWhitelist) {
+        boolean changed = false;
+        final UidRecord uidRec = mActiveUids.get(uid);
+        if (uidRec != null && uidRec.curWhitelist != onWhitelist) {
+            uidRec.curWhitelist = onWhitelist;
+            updateOomAdjLocked();
+        }
+    }
+
     final void trimApplications() {
         synchronized (this) {
             int i;
@@ -23356,7 +23502,7 @@
                 Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
                 return;
             }
-            ((PendingIntentRecord) target).setWhitelistDuration(duration);
+            ((PendingIntentRecord) target).setWhitelistDurationLocked(duration);
         }
 
         @Override
@@ -23832,6 +23978,15 @@
         }
     }
 
+    @Override
+    public long getActivityStartInitiatedTime(IBinder token) {
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+        if (r != null) {
+            return r.mStartInitiatedTimeMs;
+        }
+        return 0;
+    }
+
     void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
         final PackageManagerInternal packageManager = getPackageManagerInternalLocked();
         final boolean updateFrameworkRes = packagesToUpdate.contains("android");
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 0fcf3e6..b6bfb00 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -524,7 +524,7 @@
         pw.println("Starting service: " + intent);
         pw.flush();
         ComponentName cn = mInterface.startService(null, intent, intent.getType(),
-                -1, null, asForeground, SHELL_PACKAGE_NAME, mUserId);
+                asForeground, SHELL_PACKAGE_NAME, mUserId);
         if (cn == null) {
             err.println("Error: Not found; no service started.");
             return -1;
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 2881787..494aaa7 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -314,7 +314,8 @@
             builder.setPackageName(info.launchedActivity.packageName);
             builder.setType(type);
             builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
-            if (info.launchedActivity.launchedFromPackage != null) {
+            final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp();
+            if (isInstantApp && info.launchedActivity.launchedFromPackage != null) {
                 builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
                         info.launchedActivity.launchedFromPackage);
             }
@@ -323,8 +324,7 @@
                         info.launchedActivity.info.launchToken);
                 info.launchedActivity.info.launchToken = null;
             }
-            builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL,
-                    info.launchedActivity.info.applicationInfo.isInstantApp() ? 1 : 0);
+            builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0);
             builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS,
                     mCurrentTransitionDeviceUptime);
             builder.addTaggedData(APP_TRANSITION_DELAY_MS, mCurrentTransitionDelayMs);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 276b267..7cdddc0 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -341,6 +341,12 @@
     private final Rect mBounds = new Rect();
 
     /**
+     * Denotes the timestamp at which this activity start was last initiated in the
+     * {@link SystemClock#uptimeMillis()} time base.
+     */
+    long mStartInitiatedTimeMs;
+
+    /**
      * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
      */
     private final Configuration mTmpConfig1 = new Configuration();
@@ -498,6 +504,8 @@
                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
         pw.print(prefix); pw.print("mActivityType=");
                 pw.println(activityTypeToString(mActivityType));
+        pw.print(prefix); pw.print("mStartInitiatedTimeMs=");
+                TimeUtils.formatDuration(mStartInitiatedTimeMs, now, pw);
         if (requestedVrComponent != null) {
             pw.print(prefix);
             pw.print("requestedVrComponent=");
@@ -1170,6 +1178,10 @@
      *         the activity is not currently visible and {@param noThrow} is not set.
      */
     boolean checkEnterPictureInPictureState(String caller, boolean noThrow, boolean beforeStopping) {
+        if (!supportsPictureInPicture()) {
+            return false;
+        }
+
         // Check app-ops and see if PiP is supported for this package
         if (!checkEnterPictureInPictureAppOpsState()) {
             return false;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 0c28aaf..1f896e3 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -65,6 +65,8 @@
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
 import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
@@ -589,6 +591,13 @@
     }
 
     /**
+     * Returns whether to defer the scheduling of the multi-window mode.
+     */
+    boolean deferScheduleMultiWindowModeChanged() {
+        return false;
+    }
+
+    /**
      * Defers updating the bounds of the stack. If the stack was resized/repositioned while
      * deferring, the bounds will update in {@link #continueUpdateBounds()}.
      */
@@ -646,9 +655,13 @@
     }
 
     final ActivityRecord topRunningActivityLocked() {
+        return topRunningActivityLocked(false /* focusableOnly */);
+    }
+
+    final ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
-            if (r != null) {
+            if (r != null && (!focusableOnly || r.isFocusable())) {
                 return r;
             }
         }
@@ -1168,7 +1181,7 @@
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 final ActivityRecord r = activities.get(activityNdx);
-                if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED
+                if (r.state == STOPPING || r.state == STOPPED
                         || r.state == ActivityState.PAUSED || r.state == ActivityState.PAUSING) {
                     r.setSleeping(true);
                 }
@@ -1323,7 +1336,7 @@
                         + (timeout ? " (due to timeout)" : " (pause complete)"));
                 mService.mWindowManager.deferSurfaceLayout();
                 try {
-                    completePauseLocked(true, null);
+                    completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
                 } finally {
                     mService.mWindowManager.continueSurfaceLayout();
                 }
@@ -1351,7 +1364,7 @@
         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
 
         if (prev != null) {
-            final boolean wasStopping = prev.state == ActivityState.STOPPING;
+            final boolean wasStopping = prev.state == STOPPING;
             prev.state = ActivityState.PAUSED;
             if (prev.finishing) {
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
@@ -1372,7 +1385,7 @@
                     // We are also stopping, the stop request must have gone soon after the pause.
                     // We can't clobber it, because the stop confirmation will not be handled.
                     // We don't need to schedule another stop, we only need to let it happen.
-                    prev.state = ActivityState.STOPPING;
+                    prev.state = STOPPING;
                 } else if ((!prev.visible && !hasVisibleBehindActivity())
                         || mService.isSleepingOrShuttingDownLocked()) {
                     // If we were visible then resumeTopActivities will release resources before
@@ -1991,10 +2004,17 @@
         // keeping the screen frozen.
         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.state);
         try {
+            final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
+                    "makeInvisible", true /* noThrow */, true /* beforeStopping */);
+            // We don't want to call setVisible(false) to avoid notifying the client of this
+            // intermittent invisible state if it can enter Pip and isn't stopped or stopping.
+            if (!canEnterPictureInPicture || r.state == STOPPING || r.state == STOPPED) {
+                r.setVisible(false);
+            }
+
             switch (r.state) {
                 case STOPPING:
                 case STOPPED:
-                    r.setVisible(false);
                     if (r.app != null && r.app.thread != null) {
                         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                                 "Scheduling invisibility: " + r);
@@ -2013,25 +2033,16 @@
                     // This case created for transitioning activities from
                     // translucent to opaque {@link Activity#convertToOpaque}.
                     if (visibleBehind == r) {
-                        r.setVisible(false);
                         releaseBackgroundResources(r);
                     } else {
                         // If this activity is in a state where it can currently enter
                         // picture-in-picture, then don't immediately schedule the idle now in case
                         // the activity tries to enterPictureInPictureMode() later. Otherwise,
                         // we will try and stop the activity next time idle is processed.
-                        final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
-                                "makeInvisible", true /* noThrow */, true /* beforeStopping */);
 
                         if (canEnterPictureInPicture) {
-                            // We set r.visible=false so that Stop will later
-                            // call setVisible for us. In this case
-                            // we don't want to call setVisible(false) to avoid
-                            // notifying the client of this intermittent invisible
-                            // state.
+                            // We set r.visible=false so that Stop will later call setVisible for us
                             r.visible = false;
-                        } else {
-                            r.setVisible(false);
                         }
                         addToStopping(r, true /* scheduleIdle */,
                                 canEnterPictureInPicture /* idleDelayed */);
@@ -2200,8 +2211,10 @@
             return false;
         }
 
-        // Find the topmost activity in this stack that is not finishing.
-        final ActivityRecord next = topRunningActivityLocked();
+        // Find the next top-most activity to resume in this stack that is not finishing and is
+        // focusable. If it is not focusable, we will fall into the case below to resume the
+        // top activity in the next focusable task.
+        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
 
         final boolean hasRunningActivity = next != null;
 
@@ -2305,9 +2318,20 @@
 
         mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
 
+        final boolean prevCanPip = prev != null && prev.checkEnterPictureInPictureState(
+                "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
         // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
-        // to be paused, while at the same time resuming the new resume activity
+        // to be paused, while at the same time resuming the new resume activity only if the
+        // previous activity can't go into Pip since we want to give Pip activities a chance to
+        // enter Pip before resuming the next activity.
         final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
+        // TODO: This would be go to have however, the various call points that pass in
+        // prev need to be corrected first. In some cases the prev is equal to the next e.g. launch
+        // an app from home. And, is come other cases it is null e.g. press home button after
+        // launching an app. The doc on the method says prev. is null expect for the case we are
+        // coming from pause. We need to see if that is a valid thing and also if all the code in
+        // this method using prev. are setup to function like that.
+        //&& !prevCanPip;
         boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
         if (mResumedActivity != null) {
             if (DEBUG_STATES) Slog.d(TAG_STATES,
@@ -3347,11 +3371,11 @@
                 r.stopped = false;
                 if (DEBUG_STATES) Slog.v(TAG_STATES,
                         "Moving to STOPPING: " + r + " (stop requested)");
-                r.state = ActivityState.STOPPING;
+                r.state = STOPPING;
                 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
                         "Stopping visible=" + r.visible + " for " + r);
                 if (!r.visible) {
-                    r.setVisibility(false);
+                    r.setVisible(false);
                 }
                 EventLogTags.writeAmStopActivity(
                         r.userId, System.identityHashCode(r), r.shortComponentName);
@@ -3369,7 +3393,7 @@
                 // Just in case, assume it to be stopped.
                 r.stopped = true;
                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r);
-                r.state = ActivityState.STOPPED;
+                r.state = STOPPED;
                 if (r.deferRelaunchUntilPaused) {
                     destroyActivityLocked(r, true, "stop-except");
                 }
@@ -3674,7 +3698,7 @@
             }
             if (DEBUG_STATES) Slog.v(TAG_STATES,
                     "Moving to STOPPING: "+ r + " (finish requested)");
-            r.state = ActivityState.STOPPING;
+            r.state = STOPPING;
             if (oomAdj) {
                 mService.updateOomAdjLocked();
             }
@@ -3699,8 +3723,8 @@
                 || (prevState == ActivityState.PAUSED
                     && (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
                 || finishingActivityInNonFocusedStack
-                || prevState == ActivityState.STOPPING
-                || prevState == ActivityState.STOPPED
+                || prevState == STOPPING
+                || prevState == STOPPED
                 || prevState == ActivityState.INITIALIZING) {
             r.makeFinishingLocked();
             boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 68e25c3..152d5f4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -174,6 +174,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.wm.PinnedStackWindowController;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.FileDescriptor;
@@ -2492,11 +2493,21 @@
     }
 
     void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
-        final ActivityStack stack = getStack(PINNED_STACK_ID);
+        final PinnedActivityStack stack = getStack(PINNED_STACK_ID);
         if (stack == null) {
             Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
             return;
         }
+
+        // It is possible for the bounds animation from the WM to call this but be delayed by
+        // another AM call that is holding the AMS lock. In such a case, the pinnedBounds may be
+        // incorrect if AMS.resizeStackWithBoundsFromWindowManager() is already called while waiting
+        // for the AMS lock to be freed. So check and make sure these bounds are still good.
+        final PinnedStackWindowController stackController = stack.getWindowContainerController();
+        if (stackController.pinnedStackResizeDisallowed()) {
+            return;
+        }
+
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack");
         mWindowManager.deferSurfaceLayout();
         try {
@@ -2857,16 +2868,20 @@
             return false;
         }
 
-        moveActivityToPinnedStackLocked(r, null /* sourceBounds */, destBounds,
+        moveActivityToPinnedStackLocked(r, null /* sourceBounds */, 0f /* aspectRatio */,
                 true /* moveHomeStackToFront */, "moveTopActivityToPinnedStack");
         return true;
     }
 
-    void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, Rect destBounds,
+    void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceHintBounds, float aspectRatio,
             boolean moveHomeStackToFront, String reason) {
 
         mWindowManager.deferSurfaceLayout();
 
+        // This will clear the pinned stack by moving an existing task to the full screen stack,
+        // ensuring only one task is present.
+        moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP);
+
         // Need to make sure the pinned stack exist so we can resize it below...
         final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
 
@@ -2932,11 +2947,13 @@
         ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
         resumeFocusedStackTopActivityLocked();
 
-        // TODO(b/36099777): Schedule the PiP mode change here immediately until we can defer all
-        // callbacks until after the bounds animation
-        scheduleUpdatePictureInPictureModeIfNeeded(r.getTask(), destBounds, true /* immediate */);
+        // Calculate the default bounds (don't use existing stack bounds as we may have just created
+        // the stack
+        final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
+                aspectRatio, false /* useExistingStackBounds */);
 
-        stack.animateResizePinnedStack(sourceBounds, destBounds, -1 /* animationDuration */);
+        stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
+                true /* schedulePipModeChangedOnAnimationEnd */);
         mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName);
     }
 
@@ -4163,6 +4180,12 @@
     }
 
     void scheduleUpdateMultiWindowMode(TaskRecord task) {
+        // If the stack is animating in a way where we will be forcing a multi-mode change at the
+        // end, then ensure that we defer all in between multi-window mode changes
+        if (task.getStack().deferScheduleMultiWindowModeChanged()) {
+            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) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 56594d3..8f1c203 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -244,6 +244,7 @@
             ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
             ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
             TaskRecord inTask) {
+        final long activityStartTime = SystemClock.uptimeMillis();
         int err = ActivityManager.START_SUCCESS;
 
         ProcessRecord callerApp = null;
@@ -478,6 +479,7 @@
                 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                 mSupervisor, container, options, sourceRecord);
+        r.mStartInitiatedTimeMs = activityStartTime;
         if (outActivity != null) {
             outActivity[0] = r;
         }
@@ -1029,6 +1031,7 @@
                         // so make sure the task now has the identity of the new intent.
                         top.getTask().setIntent(mStartActivity);
                     }
+                    top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
                     ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
                     top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                             mStartActivity.launchedFromPackage);
@@ -1052,6 +1055,7 @@
             setTaskFromIntentActivity(reusedActivity);
 
             if (!mAddingToTask && mReuseTask == null) {
+                reusedActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
                 // We didn't do anything...  but it was needed (a.k.a., client don't use that
                 // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
                 resumeTargetStackIfNeeded();
@@ -1084,6 +1088,7 @@
                 || mLaunchSingleTop || mLaunchSingleTask);
         if (dontStart) {
             ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
+            top.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
             // For paranoia, make sure we have correctly resumed the top activity.
             topStack.mLastPausedActivity = null;
             if (mDoResume) {
@@ -1664,6 +1669,7 @@
             // desires.
             if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
                     && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
+                intentActivity.mStartInitiatedTimeMs = mStartActivity.mStartInitiatedTimeMs;
                 ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity,
                         intentActivity.getTask());
                 if (intentActivity.frontOfTask) {
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 646f6ce..c9c1d00 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -106,7 +106,7 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        final FrameLayout frame = (FrameLayout) findViewById(android.R.id.custom);
+        final FrameLayout frame = findViewById(android.R.id.custom);
         final Context context = getContext();
         LayoutInflater.from(context).inflate(
                 com.android.internal.R.layout.app_error_dialog, frame, true);
@@ -114,19 +114,19 @@
         boolean hasRestart = !mRepeating && mIsRestartable;
         final boolean hasReceiver = mProc.errorReportReceiver != null;
 
-        final TextView restart = (TextView) findViewById(com.android.internal.R.id.aerr_restart);
+        final TextView restart = findViewById(com.android.internal.R.id.aerr_restart);
         restart.setOnClickListener(this);
         restart.setVisibility(hasRestart ? View.VISIBLE : View.GONE);
-        final TextView report = (TextView) findViewById(com.android.internal.R.id.aerr_report);
+        final TextView report = findViewById(com.android.internal.R.id.aerr_report);
         report.setOnClickListener(this);
         report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);
-        final TextView close = (TextView) findViewById(com.android.internal.R.id.aerr_close);
+        final TextView close = findViewById(com.android.internal.R.id.aerr_close);
         close.setVisibility(!hasRestart ? View.VISIBLE : View.GONE);
         close.setOnClickListener(this);
 
         boolean showMute = !IS_USER_BUILD && Settings.Global.getInt(context.getContentResolver(),
                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
-        final TextView mute = (TextView) findViewById(com.android.internal.R.id.aerr_mute);
+        final TextView mute = findViewById(com.android.internal.R.id.aerr_mute);
         mute.setOnClickListener(this);
         mute.setVisibility(showMute ? View.VISIBLE : View.GONE);
 
@@ -148,18 +148,7 @@
 
     private final Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
-            final int result = msg.what;
-
-            synchronized (mService) {
-                if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
-                    mProc.crashDialog = null;
-                }
-            }
-            mResult.set(result);
-
-            // Make sure we don't have time timeout still hanging around.
-            removeMessages(TIMEOUT);
-
+            setResult(msg.what);
             dismiss();
         }
     };
@@ -168,11 +157,23 @@
     public void dismiss() {
         if (!mResult.mHasResult) {
             // We are dismissing and the result has not been set...go ahead and set.
-            mResult.set(FORCE_QUIT);
+            setResult(FORCE_QUIT);
         }
         super.dismiss();
     }
 
+    private void setResult(int result) {
+        synchronized (mService) {
+            if (mProc != null && mProc.crashDialog == AppErrorDialog.this) {
+                mProc.crashDialog = null;
+            }
+        }
+        mResult.set(result);
+
+        // Make sure we don't have time timeout still hanging around.
+        mHandler.removeMessages(TIMEOUT);
+    }
+
     @Override
     public void onClick(View v) {
         switch (v.getId()) {
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 9e29725..a3a6778 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -104,18 +104,18 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        final FrameLayout frame = (FrameLayout) findViewById(android.R.id.custom);
+        final FrameLayout frame = findViewById(android.R.id.custom);
         final Context context = getContext();
         LayoutInflater.from(context).inflate(
                 com.android.internal.R.layout.app_anr_dialog, frame, true);
 
-        final TextView report = (TextView) findViewById(com.android.internal.R.id.aerr_report);
+        final TextView report = findViewById(com.android.internal.R.id.aerr_report);
         report.setOnClickListener(this);
         final boolean hasReceiver = mProc.errorReportReceiver != null;
         report.setVisibility(hasReceiver ? View.VISIBLE : View.GONE);
-        final TextView close = (TextView) findViewById(com.android.internal.R.id.aerr_close);
+        final TextView close = findViewById(com.android.internal.R.id.aerr_close);
         close.setOnClickListener(this);
-        final TextView wait = (TextView) findViewById(com.android.internal.R.id.aerr_wait);
+        final TextView wait = findViewById(com.android.internal.R.id.aerr_wait);
         wait.setOnClickListener(this);
 
         findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index baa71d7..349180f 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -155,8 +155,6 @@
 
     static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
     static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;
-    static final int SCHEDULE_TEMP_WHITELIST_MSG
-            = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 2;
 
     final BroadcastHandler mHandler;
 
@@ -178,13 +176,6 @@
                         broadcastTimeoutLocked(true);
                     }
                 } break;
-                case SCHEDULE_TEMP_WHITELIST_MSG: {
-                    DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
-                    if (dic != null) {
-                        dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
-                                msg.arg2, true, (String)msg.obj);
-                    }
-                } break;
             }
         }
     }
@@ -789,12 +780,11 @@
         if (r.intent.getAction() != null) {
             b.append(r.intent.getAction());
         } else if (r.intent.getComponent() != null) {
-            b.append(r.intent.getComponent().flattenToShortString());
+            r.intent.getComponent().appendShortString(b);
         } else if (r.intent.getData() != null) {
             b.append(r.intent.getData());
         }
-        mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration, b.toString())
-                .sendToTarget();
+        mService.tempWhitelistUidLocked(uid, duration, b.toString());
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
index 4a87941..c2f1890 100644
--- a/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
+++ b/services/core/java/com/android/server/am/HealthStatsBatteryStatsWriter.java
@@ -46,6 +46,7 @@
     /**
      * Writes the contents of a BatteryStats.Uid into a HealthStatsWriter.
      */
+    @SuppressWarnings("deprecation")
     public void writeUid(HealthStatsWriter uidWriter, BatteryStats bs, BatteryStats.Uid uid) {
         int N;
         BatteryStats.Timer timer;
@@ -365,8 +366,7 @@
                 uid.getSystemCpuTimeUs(STATS_SINCE_UNPLUGGED)/1000);
 
         // MEASUREMENT_CPU_POWER_MAMS
-        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS,
-                uid.getCpuPowerMaUs(STATS_SINCE_UNPLUGGED)/1000);
+        uidWriter.addMeasurement(UidHealthStats.MEASUREMENT_CPU_POWER_MAMS, 0);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index f05bfb6..a580d4b 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -28,12 +28,14 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.TransactionTooLargeException;
 import android.os.UserHandle;
 import android.util.Slog;
 import android.util.TimeUtils;
 
+import com.android.internal.os.IResultReceiver;
 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
 
 import java.io.PrintWriter;
@@ -50,6 +52,7 @@
     boolean sent = false;
     boolean canceled = false;
     private long whitelistDuration = 0;
+    private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
 
     String stringName;
     String lastTagPrefix;
@@ -191,11 +194,31 @@
         ref = new WeakReference<PendingIntentRecord>(this);
     }
 
-    void setWhitelistDuration(long duration) {
+    void setWhitelistDurationLocked(long duration) {
         this.whitelistDuration = duration;
         this.stringName = null;
     }
 
+    public void registerCancelListenerLocked(IResultReceiver receiver) {
+        if (mCancelCallbacks == null) {
+            mCancelCallbacks = new RemoteCallbackList<>();
+        }
+        mCancelCallbacks.register(receiver);
+    }
+
+    public void unregisterCancelListenerLocked(IResultReceiver receiver) {
+        mCancelCallbacks.unregister(receiver);
+        if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
+            mCancelCallbacks = null;
+        }
+    }
+
+    public RemoteCallbackList<IResultReceiver> detachCancelListenersLocked() {
+        RemoteCallbackList<IResultReceiver> listeners = mCancelCallbacks;
+        mCancelCallbacks = null;
+        return listeners;
+    }
+
     public void send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
             String requiredPermission, Bundle options) {
         sendInner(code, intent, resolvedType, finishedReceiver,
@@ -214,14 +237,6 @@
         if (intent != null) intent.setDefusable(true);
         if (options != null) options.setDefusable(true);
 
-        if (whitelistDuration > 0 && !canceled) {
-            // Must call before acquiring the lock. It's possible the method return before sending
-            // the intent due to some validations inside the lock, in which case the UID shouldn't
-            // be whitelisted, but since the whitelist is temporary, that would be ok.
-            owner.tempWhitelistAppForPowerSave(Binder.getCallingPid(), Binder.getCallingUid(), uid,
-                    whitelistDuration);
-        }
-
         synchronized (owner) {
             final ActivityContainer activityContainer = (ActivityContainer)container;
             if (activityContainer != null && activityContainer.mParentActivity != null &&
@@ -234,7 +249,6 @@
                 sent = true;
                 if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
                     owner.cancelIntentSenderLocked(this, true);
-                    canceled = true;
                 }
 
                 Intent finalIntent = key.requestIntent != null
@@ -257,6 +271,22 @@
                     resolvedType = key.requestResolvedType;
                 }
 
+                if (whitelistDuration > 0) {
+                    StringBuilder tag = new StringBuilder(64);
+                    tag.append("pendingintent:");
+                    UserHandle.formatUid(tag, Binder.getCallingUid());
+                    tag.append(":");
+                    if (finalIntent.getAction() != null) {
+                        tag.append(finalIntent.getAction());
+                    } else if (finalIntent.getComponent() != null) {
+                        finalIntent.getComponent().appendShortString(tag);
+                    } else if (finalIntent.getData() != null) {
+                        tag.append(finalIntent.getData());
+                    }
+                    owner.tempWhitelistForPendingIntentLocked(Binder.getCallingPid(),
+                            Binder.getCallingUid(), uid, whitelistDuration, tag.toString());
+                }
+
                 final long origId = Binder.clearCallingIdentity();
 
                 boolean sendFinish = finishedReceiver != null;
@@ -398,6 +428,13 @@
             TimeUtils.formatDuration(whitelistDuration, pw);
             pw.println();
         }
+        if (mCancelCallbacks != null) {
+            pw.print(prefix); pw.println("mCancelCallbacks:");
+            for (int i = 0; i < mCancelCallbacks.getRegisteredCallbackCount(); i++) {
+                pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": ");
+                pw.println(mCancelCallbacks.getRegisteredCallbackItem(i));
+            }
+        }
     }
 
     public String toString() {
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 394e902..a4932bb 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -21,7 +21,7 @@
 
 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
 import com.android.server.wm.PinnedStackWindowController;
-import com.android.server.wm.StackWindowController;
+import com.android.server.wm.PinnedStackWindowListener;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -29,7 +29,8 @@
 /**
  * State and management of the pinned stack of activities.
  */
-class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> {
+class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
+        implements PinnedStackWindowListener {
 
     PinnedActivityStack(ActivityContainer activityContainer,
             RecentTasks recentTasks, boolean onTop) {
@@ -42,9 +43,10 @@
         return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds);
     }
 
-    void animateResizePinnedStack(Rect sourceBounds, Rect destBounds, int animationDuration) {
-        getWindowContainerController().animateResizePinnedStack(sourceBounds, destBounds,
-                animationDuration);
+    void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
+            boolean schedulePipModeChangedOnAnimationEnd) {
+        getWindowContainerController().animateResizePinnedStack(toBounds, sourceHintBounds,
+                animationDuration, schedulePipModeChangedOnAnimationEnd);
     }
 
     void setPictureInPictureAspectRatio(float aspectRatio) {
@@ -55,11 +57,22 @@
         getWindowContainerController().setPictureInPictureActions(actions);
     }
 
-    boolean isBoundsAnimatingToFullscreen() {
-        return getWindowContainerController().isBoundsAnimatingToFullscreen();
+    boolean isAnimatingBoundsToFullscreen() {
+        return getWindowContainerController().isAnimatingBoundsToFullscreen();
     }
 
-    @Override
+    /**
+     * Returns whether to defer the scheduling of the multi-window mode.
+     */
+    boolean deferScheduleMultiWindowModeChanged() {
+        // For the pinned stack, the deferring of the multi-window mode changed is tied to the
+        // transition animation into picture-in-picture, and is called once the animation completes,
+        // or is interrupted in a way that would leave the stack in a non-fullscreen state.
+        // @see BoundsAnimationController
+        // @see BoundsAnimationControllerTests
+        return mWindowContainerController.deferScheduleMultiWindowModeChanged();
+    }
+
     public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
         // It is guaranteed that the activities requiring the update will be in the pinned stack at
         // this point (either reparented before the animation into PiP, or before reparenting after
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 22f4c22..9670a2e 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -48,6 +48,7 @@
 import android.util.DisplayMetrics;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.util.XmlUtils;
 
@@ -445,10 +446,23 @@
 
         final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
         final Configuration overrideConfig = getOverrideConfiguration();
-        mWindowContainerController = new TaskWindowContainerController(taskId, this,
+        setWindowContainerController(new TaskWindowContainerController(taskId, this,
                 getStack().getWindowContainerController(), userId, bounds, overrideConfig,
                 mResizeMode, mSupportsPictureInPicture, isHomeTask(), onTop, showForAllUsers,
-                lastTaskDescription);
+                lastTaskDescription));
+    }
+
+    /**
+     * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
+     */
+    @VisibleForTesting
+    protected void setWindowContainerController(TaskWindowContainerController controller) {
+        if (mWindowContainerController != null) {
+            throw new IllegalArgumentException("Window container=" + mWindowContainerController
+                    + " already created for task=" + this);
+        }
+
+        mWindowContainerController = controller;
     }
 
     void removeWindowContainer() {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c11f531..d2d69cb 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -23,6 +23,7 @@
 import static android.os.Process.FIRST_APPLICATION_UID;
 
 import android.Manifest;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
@@ -519,7 +520,11 @@
     private int mPrevVolDirection = AudioManager.ADJUST_SAME;
     // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
     // is controlled by Vol keys.
-    private int  mVolumeControlStream = -1;
+    private int mVolumeControlStream = -1;
+    // interpretation of whether the volume stream has been selected by the user by clicking on a
+    // volume slider to change which volume is controlled by the volume keys. Is false
+    // when mVolumeControlStream is -1.
+    private boolean mUserSelectedVolumeControlStream = false;
     private final Object mForceControlStreamLock = new Object();
     // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
     // server process so in theory it is not necessary to monitor the client death.
@@ -928,11 +933,8 @@
         synchronized (VolumeStreamState.class) {
             int numStreamTypes = AudioSystem.getNumStreamTypes();
             for (int streamType = 0; streamType < numStreamTypes; streamType++) {
-                if (streamType != mStreamVolumeAlias[streamType]) {
-                    mStreamStates[streamType].
-                                    setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]],
-                                            TAG);
-                }
+                mStreamStates[streamType]
+                        .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
                 // apply stream volume
                 if (!mStreamStates[streamType].mIsMuted) {
                     mStreamStates[streamType].applyAllVolumes();
@@ -968,7 +970,8 @@
         VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
 
         for (int i = 0; i < numStreamTypes; i++) {
-            streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i);
+            streams[i] =
+                    new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
         }
 
         checkAllFixedVolumeDevices();
@@ -1025,8 +1028,16 @@
         if (updateVolumes) {
             mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias],
                     caller);
+
+            mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
+                    System.VOLUME_SETTINGS_INT[a11yStreamAlias];
             mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
                     mStreamStates[a11yStreamAlias], caller);
+            if (sIndependentA11yVolume) {
+                // restore the a11y values from the settings
+                mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
+            }
+
             // apply stream mute states according to new value of mRingerModeAffectedStreams
             setRingerModeInt(getRingerModeInternal(), false);
             sendMsg(mAudioHandler,
@@ -1217,14 +1228,29 @@
     private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
             String callingPackage, String caller, int uid) {
         if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
-                + ", flags=" + flags + ", caller=" + caller);
-        int streamType;
-        boolean isMute = isMuteAdjust(direction);
-        if (mVolumeControlStream != -1) {
+                + ", flags=" + flags + ", caller=" + caller
+                + ", volControlStream=" + mVolumeControlStream
+                + ", userSelect=" + mUserSelectedVolumeControlStream);
+        final int streamType;
+        if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
             streamType = mVolumeControlStream;
         } else {
-            streamType = getActiveStreamType(suggestedStreamType);
+            final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
+            final boolean activeForReal;
+            if (maybeActiveStreamType == AudioSystem.STREAM_MUSIC) {
+                activeForReal = isAfMusicActiveRecently(0);
+            } else {
+                activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
+            }
+            if (activeForReal || mVolumeControlStream == -1) {
+                streamType = maybeActiveStreamType;
+            } else {
+                streamType = mVolumeControlStream;
+            }
         }
+
+        final boolean isMute = isMuteAdjust(direction);
+
         ensureValidStreamType(streamType);
         final int resolvedStream = mStreamVolumeAlias[streamType];
 
@@ -1700,13 +1726,18 @@
 
     /** @see AudioManager#forceVolumeControlStream(int) */
     public void forceVolumeControlStream(int streamType, IBinder cb) {
+        if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
         synchronized(mForceControlStreamLock) {
+            if (mVolumeControlStream != -1 && streamType != -1) {
+                mUserSelectedVolumeControlStream = true;
+            }
             mVolumeControlStream = streamType;
             if (mVolumeControlStream == -1) {
                 if (mForceControlStreamClient != null) {
                     mForceControlStreamClient.release();
                     mForceControlStreamClient = null;
                 }
+                mUserSelectedVolumeControlStream = false;
             } else {
                 mForceControlStreamClient = new ForceControlStreamClient(cb);
             }
@@ -1737,6 +1768,7 @@
                 } else {
                     mForceControlStreamClient = null;
                     mVolumeControlStream = -1;
+                    mUserSelectedVolumeControlStream = false;
                 }
             }
         }
@@ -3992,13 +4024,19 @@
             return devices;
         }
 
-        public String getSettingNameForDevice(int device) {
-            String name = mVolumeIndexSettingName;
-            String suffix = AudioSystem.getOutputDeviceName(device);
-            if (suffix.isEmpty()) {
-                return name;
+        public @Nullable String getSettingNameForDevice(int device) {
+            if (!hasValidSettingsName()) {
+                return null;
             }
-            return name + "_" + suffix;
+            final String suffix = AudioSystem.getOutputDeviceName(device);
+            if (suffix.isEmpty()) {
+                return mVolumeIndexSettingName;
+            }
+            return mVolumeIndexSettingName + "_" + suffix;
+        }
+
+        private boolean hasValidSettingsName() {
+            return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
         }
 
         public void readSettings() {
@@ -4033,13 +4071,18 @@
                     remainingDevices &= ~device;
 
                     // retrieve current volume for device
-                    String name = getSettingNameForDevice(device);
                     // if no volume stored for current stream and device, use default volume if default
                     // device, continue otherwise
                     int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
                             AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
-                    int index = Settings.System.getIntForUser(
-                            mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
+                    int index;
+                    if (!hasValidSettingsName()) {
+                        index = defaultIndex;
+                    } else {
+                        String name = getSettingNameForDevice(device);
+                        index = Settings.System.getIntForUser(
+                                mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
+                    }
                     if (index == -1) {
                         continue;
                     }
@@ -4208,7 +4251,17 @@
             return mIndexMin;
         }
 
+        /**
+         * Copies all device/index pairs from the given VolumeStreamState after initializing
+         * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
+         * has the same stream type as this instance.
+         * @param srcStream
+         * @param caller
+         */
         public void setAllIndexes(VolumeStreamState srcStream, String caller) {
+            if (mStreamType == srcStream.mStreamType) {
+                return;
+            }
             synchronized (VolumeStreamState.class) {
                 int srcStreamType = srcStream.getStreamType();
                 // apply default device volume from source stream to all devices first in case
@@ -4420,10 +4473,12 @@
             if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
                 return;
             }
-            System.putIntForUser(mContentResolver,
-                      streamState.getSettingNameForDevice(device),
-                      (streamState.getIndex(device) + 5)/ 10,
-                      UserHandle.USER_CURRENT);
+            if (streamState.hasValidSettingsName()) {
+                System.putIntForUser(mContentResolver,
+                        streamState.getSettingNameForDevice(device),
+                        (streamState.getIndex(device) + 5)/ 10,
+                        UserHandle.USER_CURRENT);
+            }
         }
 
         private void persistRingerMode(int ringerMode) {
@@ -6043,9 +6098,7 @@
 
     // implementation of AccessibilityServicesStateChangeListener
     @Override
-    public void onAccessibilityServicesStateChanged() {
-        final AccessibilityManager accessibilityManager =
-                (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+    public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
         updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
     }
 
@@ -6059,6 +6112,7 @@
             mVolumeController.setA11yMode(sIndependentA11yVolume ?
                     VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
                         VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
+            mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index ad66faa..5dee91d 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -23,9 +23,6 @@
 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
 
 import android.net.ConnectivityMetricsEvent;
 import android.net.metrics.ApfProgramEvent;
@@ -34,6 +31,7 @@
 import android.net.metrics.DhcpClientEvent;
 import android.net.metrics.DhcpErrorEvent;
 import android.net.metrics.DnsEvent;
+import android.net.metrics.ConnectStats;
 import android.net.metrics.IpManagerEvent;
 import android.net.metrics.IpReachabilityEvent;
 import android.net.metrics.NetworkEvent;
@@ -41,7 +39,12 @@
 import android.net.metrics.ValidationProbeEvent;
 import android.os.Parcelable;
 import android.util.SparseArray;
+import android.util.SparseIntArray;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.Pair;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -77,20 +80,51 @@
     }
 
     public static IpConnectivityEvent toProto(ConnectivityMetricsEvent ev) {
-        final IpConnectivityEvent out = new IpConnectivityEvent();
+        final IpConnectivityEvent out = buildEvent(ev.netId, ev.transports, ev.ifname);
+        out.timeMs = ev.timestamp;
         if (!setEvent(out, ev.data)) {
             return null;
         }
-        out.timeMs = ev.timestamp;
-        out.networkId = ev.netId;
-        out.transports = ev.transports;
-        if (ev.ifname != null) {
-          out.ifName = ev.ifname;
-        }
-        inferLinkLayer(out);
         return out;
     }
 
+    public static IpConnectivityEvent toProto(ConnectStats in) {
+        IpConnectivityLogClass.ConnectStatistics stats =
+                new IpConnectivityLogClass.ConnectStatistics();
+        stats.connectCount = in.connectCount;
+        stats.connectBlockingCount = in.connectBlockingCount;
+        stats.ipv6AddrCount = in.ipv6ConnectCount;
+        stats.latenciesMs = in.latencies.toArray();
+        stats.errnosCounters = toPairArray(in.errnos);
+        final IpConnectivityEvent out = buildEvent(in.netId, in.transports, null);
+        out.setConnectStatistics(stats);
+        return out;
+    }
+
+
+    public static IpConnectivityEvent toProto(DnsEvent in) {
+        IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch =
+                new IpConnectivityLogClass.DNSLookupBatch();
+        in.resize(in.eventCount);
+        dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
+        dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
+        dnsLookupBatch.latenciesMs = in.latenciesMs;
+        final IpConnectivityEvent out = buildEvent(in.netId, in.transports, null);
+        out.setDnsLookupBatch(dnsLookupBatch);
+        return out;
+    }
+
+    private static IpConnectivityEvent buildEvent(int netId, long transports, String ifname) {
+        final IpConnectivityEvent ev = new IpConnectivityEvent();
+        ev.networkId = netId;
+        ev.transports = transports;
+        if (ifname != null) {
+            ev.ifName = ifname;
+        }
+        inferLinkLayer(ev);
+        return ev;
+    }
+
     private static boolean setEvent(IpConnectivityEvent out, Parcelable in) {
         if (in instanceof DhcpErrorEvent) {
             setDhcpErrorEvent(out, (DhcpErrorEvent) in);
@@ -102,11 +136,6 @@
             return true;
         }
 
-        if (in instanceof DnsEvent) {
-            setDnsEvent(out, (DnsEvent) in);
-            return true;
-        }
-
         if (in instanceof IpManagerEvent) {
             setIpManagerEvent(out, (IpManagerEvent) in);
             return true;
@@ -163,16 +192,6 @@
         out.setDhcpEvent(dhcpEvent);
     }
 
-    private static void setDnsEvent(IpConnectivityEvent out, DnsEvent in) {
-        IpConnectivityLogClass.DNSLookupBatch dnsLookupBatch =
-                new IpConnectivityLogClass.DNSLookupBatch();
-        dnsLookupBatch.networkId = netIdOf(in.netId);
-        dnsLookupBatch.eventTypes = bytesToInts(in.eventTypes);
-        dnsLookupBatch.returnCodes = bytesToInts(in.returnCodes);
-        dnsLookupBatch.latenciesMs = in.latenciesMs;
-        out.setDnsLookupBatch(dnsLookupBatch);
-    }
-
     private static void setIpManagerEvent(IpConnectivityEvent out, IpManagerEvent in) {
         IpConnectivityLogClass.IpProvisioningEvent ipProvisioningEvent =
                 new IpConnectivityLogClass.IpProvisioningEvent();
@@ -268,6 +287,18 @@
         return out;
     }
 
+    private static Pair[] toPairArray(SparseIntArray counts) {
+        final int s = counts.size();
+        Pair[] pairs = new Pair[s];
+        for (int i = 0; i < s; i++) {
+            Pair p = new Pair();
+            p.key = counts.keyAt(i);
+            p.value = counts.valueAt(i);
+            pairs[i] = p;
+        }
+        return pairs;
+    }
+
     private static NetworkId netIdOf(int netid) {
         final NetworkId ni = new NetworkId();
         ni.networkId = netid;
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index da56a07..475d786 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -76,7 +76,8 @@
 
     @VisibleForTesting
     public final Impl impl = new Impl();
-    private NetdEventListenerService mNetdListener;
+    @VisibleForTesting
+    NetdEventListenerService mNetdListener;
 
     @GuardedBy("mLock")
     private ArrayList<ConnectivityMetricsEvent> mBuffer;
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 7b9c60c..214cfce 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -18,10 +18,9 @@
 
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
 import android.net.INetdEventCallback;
 import android.net.Network;
-import android.net.NetworkRequest;
+import android.net.NetworkCapabilities;
 import android.net.metrics.ConnectStats;
 import android.net.metrics.DnsEvent;
 import android.net.metrics.INetdEventListener;
@@ -29,17 +28,17 @@
 import android.os.RemoteException;
 import android.text.format.DateUtils;
 import android.util.Log;
+import android.util.SparseArray;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.BitUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.TokenBucket;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.ConnectStatistics;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
 import java.io.PrintWriter;
-import java.util.Arrays;
 import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import java.util.function.Function;
+import java.util.function.IntFunction;
 
 /**
  * Implementation of the INetdEventListener interface.
@@ -52,8 +51,7 @@
     private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
-    // TODO: read this constant from system property
-    private static final int MAX_LOOKUPS_PER_DNS_EVENT = 100;
+    private static final int INITIAL_DNS_BATCH_SIZE = 100;
 
     // Rate limit connect latency logging to 1 measurement per 15 seconds (5760 / day) with maximum
     // bursts of 5000 measurements.
@@ -61,81 +59,17 @@
     private static final int CONNECT_LATENCY_FILL_RATE    = 15 * (int) DateUtils.SECOND_IN_MILLIS;
     private static final int CONNECT_LATENCY_MAXIMUM_RECORDS = 20000;
 
-    // Stores the results of a number of consecutive DNS lookups on the same network.
-    // This class is not thread-safe and it is the responsibility of the service to call its methods
-    // on one thread at a time.
-    private class DnsEventBatch {
-        private final int mNetId;
-
-        private final byte[] mEventTypes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
-        private final byte[] mReturnCodes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
-        private final int[] mLatenciesMs = new int[MAX_LOOKUPS_PER_DNS_EVENT];
-        private int mEventCount;
-
-        public DnsEventBatch(int netId) {
-            mNetId = netId;
-        }
-
-        public void addResult(byte eventType, byte returnCode, int latencyMs) {
-            mEventTypes[mEventCount] = eventType;
-            mReturnCodes[mEventCount] = returnCode;
-            mLatenciesMs[mEventCount] = latencyMs;
-            mEventCount++;
-            if (mEventCount == MAX_LOOKUPS_PER_DNS_EVENT) {
-                logAndClear();
-            }
-        }
-
-        public void logAndClear() {
-            // Did we lose a race with addResult?
-            if (mEventCount == 0) {
-                return;
-            }
-
-            // Only log as many events as we actually have.
-            byte[] eventTypes = Arrays.copyOf(mEventTypes, mEventCount);
-            byte[] returnCodes = Arrays.copyOf(mReturnCodes, mEventCount);
-            int[] latenciesMs = Arrays.copyOf(mLatenciesMs, mEventCount);
-            mMetricsLog.log(new DnsEvent(mNetId, eventTypes, returnCodes, latenciesMs));
-            maybeLog("Logging %d results for netId %d", mEventCount, mNetId);
-            mEventCount = 0;
-        }
-
-        // For debugging and unit tests only.
-        public String toString() {
-            return String.format("%s %d %d", getClass().getSimpleName(), mNetId, mEventCount);
-        }
-    }
-
-    // Only sorted for ease of debugging. Because we only typically have a handful of networks up
-    // at any given time, performance is not a concern.
+    // Sparse arrays of DNS and connect events, grouped by net id.
     @GuardedBy("this")
-    private final SortedMap<Integer, DnsEventBatch> mEventBatches = new TreeMap<>();
+    private final SparseArray<DnsEvent> mDnsEvents = new SparseArray<>();
+    @GuardedBy("this")
+    private final SparseArray<ConnectStats> mConnectEvents = new SparseArray<>();
 
-    // We register a NetworkCallback to ensure that when a network disconnects, we flush the DNS
-    // queries we've logged on that network. Because we do not do this periodically, we might lose
-    // up to MAX_LOOKUPS_PER_DNS_EVENT lookup stats on each network when the system is shutting
-    // down. We believe this to be sufficient for now.
     private final ConnectivityManager mCm;
-    private final IpConnectivityLog mMetricsLog;
-    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
-        @Override
-        public void onLost(Network network) {
-            synchronized (NetdEventListenerService.this) {
-                DnsEventBatch batch = mEventBatches.remove(network.netId);
-                if (batch != null) {
-                    batch.logAndClear();
-                }
-            }
-        }
-    };
 
     @GuardedBy("this")
     private final TokenBucket mConnectTb =
             new TokenBucket(CONNECT_LATENCY_FILL_RATE, CONNECT_LATENCY_BURST_LIMIT);
-    @GuardedBy("this")
-    private ConnectStats mConnectStats = makeConnectStats();
-
     // Callback should only be registered/unregistered when logging is being enabled/disabled in DPM
     // by the device owner. It's DevicePolicyManager's responsibility to ensure that.
     @GuardedBy("this")
@@ -152,16 +86,13 @@
     }
 
     public NetdEventListenerService(Context context) {
-        this(context.getSystemService(ConnectivityManager.class), new IpConnectivityLog());
+        this(context.getSystemService(ConnectivityManager.class));
     }
 
     @VisibleForTesting
-    public NetdEventListenerService(ConnectivityManager cm, IpConnectivityLog log) {
+    public NetdEventListenerService(ConnectivityManager cm) {
         // We are started when boot is complete, so ConnectivityService should already be running.
         mCm = cm;
-        mMetricsLog = log;
-        final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
-        mCm.registerNetworkCallback(request, mNetworkCallback);
     }
 
     @Override
@@ -172,16 +103,16 @@
             throws RemoteException {
         maybeVerboseLog("onDnsEvent(%d, %d, %d, %dms)", netId, eventType, returnCode, latencyMs);
 
-        DnsEventBatch batch = mEventBatches.get(netId);
-        if (batch == null) {
-            batch = new DnsEventBatch(netId);
-            mEventBatches.put(netId, batch);
+        DnsEvent dnsEvent = mDnsEvents.get(netId);
+        if (dnsEvent == null) {
+            dnsEvent = makeDnsEvent(netId);
+            mDnsEvents.put(netId, dnsEvent);
         }
-        batch.addResult((byte) eventType, (byte) returnCode, latencyMs);
+        dnsEvent.addResult((byte) eventType, (byte) returnCode, latencyMs);
 
         if (mNetdEventCallback != null) {
-            mNetdEventCallback.onDnsEvent(hostname, ipAddresses, ipAddressesCount,
-                    System.currentTimeMillis(), uid);
+            long timestamp = System.currentTimeMillis();
+            mNetdEventCallback.onDnsEvent(hostname, ipAddresses, ipAddressesCount, timestamp, uid);
         }
     }
 
@@ -192,7 +123,12 @@
             int port, int uid) throws RemoteException {
         maybeVerboseLog("onConnectEvent(%d, %d, %dms)", netId, error, latencyMs);
 
-        mConnectStats.addEvent(error, latencyMs, ipAddr);
+        ConnectStats connectStats = mConnectEvents.get(netId);
+        if (connectStats == null) {
+            connectStats = makeConnectStats(netId);
+            mConnectEvents.put(netId, connectStats);
+        }
+        connectStats.addEvent(error, latencyMs, ipAddr);
 
         if (mNetdEventCallback != null) {
             mNetdEventCallback.onConnectEvent(ipAddr, port, System.currentTimeMillis(), uid);
@@ -200,21 +136,8 @@
     }
 
     public synchronized void flushStatistics(List<IpConnectivityEvent> events) {
-        events.add(flushConnectStats());
-        // TODO: migrate DnsEventBatch to IpConnectivityLogClass.DNSLatencies
-    }
-
-    private IpConnectivityEvent connectStatsProto() {
-        // TODO: add transport information
-        IpConnectivityEvent ev = new IpConnectivityEvent();
-        ev.setConnectStatistics(mConnectStats.toProto());
-        return ev;
-    }
-
-    private IpConnectivityEvent flushConnectStats() {
-        IpConnectivityEvent ev = connectStatsProto();
-        mConnectStats = makeConnectStats();
-        return ev;
+        flushProtos(events, mConnectEvents, IpConnectivityEventBuilder::toProto);
+        flushProtos(events, mDnsEvents, IpConnectivityEventBuilder::toProto);
     }
 
     public synchronized void dump(PrintWriter writer) {
@@ -226,18 +149,47 @@
     }
 
     public synchronized void list(PrintWriter pw) {
-        for (DnsEventBatch batch : mEventBatches.values()) {
-            pw.println(batch.toString());
-        }
-        pw.println(mConnectStats.toString());
+        listEvents(pw, mConnectEvents, (x) -> x);
+        listEvents(pw, mDnsEvents, (x) -> x);
     }
 
     public synchronized void listAsProtos(PrintWriter pw) {
-        pw.println(connectStatsProto().toString());
+        listEvents(pw, mConnectEvents, IpConnectivityEventBuilder::toProto);
+        listEvents(pw, mDnsEvents, IpConnectivityEventBuilder::toProto);
     }
 
-    private ConnectStats makeConnectStats() {
-        return new ConnectStats(mConnectTb, CONNECT_LATENCY_MAXIMUM_RECORDS);
+    private static <T> void flushProtos(List<IpConnectivityEvent> out, SparseArray<T> in,
+            Function<T, IpConnectivityEvent> mapper) {
+        for (int i = 0; i < in.size(); i++) {
+            out.add(mapper.apply(in.valueAt(i)));
+        }
+        in.clear();
+    }
+
+    public static <T> void listEvents(
+            PrintWriter pw, SparseArray<T> events, Function<T, Object> mapper) {
+        for (int i = 0; i < events.size(); i++) {
+            pw.println(mapper.apply(events.valueAt(i)).toString());
+        }
+    }
+
+    private ConnectStats makeConnectStats(int netId) {
+        long transports = getTransports(netId);
+        return new ConnectStats(netId, transports, mConnectTb, CONNECT_LATENCY_MAXIMUM_RECORDS);
+    }
+
+    private DnsEvent makeDnsEvent(int netId) {
+        long transports = getTransports(netId);
+        return new DnsEvent(netId, transports, INITIAL_DNS_BATCH_SIZE);
+    }
+
+    private long getTransports(int netId) {
+        // TODO: directly query ConnectivityService instead of going through Binder interface.
+        NetworkCapabilities nc = mCm.getNetworkCapabilities(new Network(netId));
+        if (nc == null) {
+            return 0;
+        }
+        return BitUtils.packBits(nc.getTransportTypes());
     }
 
     private static void maybeLog(String s, Object... args) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 3e53aca..b3d2e30 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -70,6 +70,7 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.UnknownHostException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
 import java.util.concurrent.CountDownLatch;
@@ -90,6 +91,8 @@
     private static final String DEFAULT_HTTP_URL      =
             "http://connectivitycheck.gstatic.com/generate_204";
     private static final String DEFAULT_FALLBACK_URL  = "http://www.google.com/gen_204";
+    private static final String DEFAULT_OTHER_FALLBACK_URLS =
+            "http://play.googleapis.com/generate_204";
     private static final String DEFAULT_USER_AGENT    = "Mozilla/5.0 (X11; Linux x86_64) "
                                                       + "AppleWebKit/537.36 (KHTML, like Gecko) "
                                                       + "Chrome/52.0.2743.82 Safari/537.36";
@@ -263,7 +266,8 @@
     private final String mCaptivePortalUserAgent;
     private final URL mCaptivePortalHttpsUrl;
     private final URL mCaptivePortalHttpUrl;
-    private final URL mCaptivePortalFallbackUrl;
+    private final URL[] mCaptivePortalFallbackUrls;
+    private int mNextFallbackUrlIndex = 0;
 
     public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
             NetworkRequest defaultRequest) {
@@ -302,7 +306,7 @@
         mCaptivePortalUserAgent = getCaptivePortalUserAgent(context);
         mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl(context));
         mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(context));
-        mCaptivePortalFallbackUrl = makeURL(getCaptivePortalFallbackUrl(context));
+        mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls(context);
 
         start();
     }
@@ -450,7 +454,7 @@
                     intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL,
                             mLastPortalProbeResult.detectUrl);
                     intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT,
-                            getCaptivePortalUserAgent(mContext));
+                            mCaptivePortalUserAgent);
                     intent.setFlags(
                             Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
                     mContext.startActivityAsUser(intent, UserHandle.CURRENT);
@@ -474,7 +478,11 @@
      */
     @VisibleForTesting
     public static final class CaptivePortalProbeResult {
-        static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(599);
+        static final int SUCCESS_CODE = 204;
+        static final int FAILED_CODE = 599;
+
+        static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE);
+        static final CaptivePortalProbeResult SUCCESS = new CaptivePortalProbeResult(SUCCESS_CODE);
 
         private final int mHttpResponseCode;  // HTTP response code returned from Internet probe.
         final String redirectUrl;             // Redirect destination returned from Internet probe.
@@ -492,9 +500,16 @@
             this(httpResponseCode, null, null);
         }
 
-        boolean isSuccessful() { return mHttpResponseCode == 204; }
+        boolean isSuccessful() {
+            return mHttpResponseCode == SUCCESS_CODE;
+        }
+
         boolean isPortal() {
-            return !isSuccessful() && mHttpResponseCode >= 200 && mHttpResponseCode <= 399;
+            return !isSuccessful() && (mHttpResponseCode >= 200) && (mHttpResponseCode <= 399);
+        }
+
+        boolean isFailed() {
+            return !isSuccessful() && !isPortal();
         }
     }
 
@@ -666,9 +681,24 @@
         return getSetting(context, Settings.Global.CAPTIVE_PORTAL_HTTP_URL, DEFAULT_HTTP_URL);
     }
 
-    private static String getCaptivePortalFallbackUrl(Context context) {
-        return getSetting(context,
+    private URL[] makeCaptivePortalFallbackUrls(Context context) {
+        String separator = ",";
+        String firstUrl = getSetting(context,
                 Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL);
+        String joinedUrls = firstUrl + separator + getSetting(context,
+                Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, DEFAULT_OTHER_FALLBACK_URLS);
+        List<URL> urls = new ArrayList<>();
+        for (String s : joinedUrls.split(separator)) {
+            URL u = makeURL(s);
+            if (u == null) {
+                continue;
+            }
+            urls.add(u);
+        }
+        if (urls.isEmpty()) {
+            Log.e(TAG, String.format("could not create any url from %s", joinedUrls));
+        }
+        return urls.toArray(new URL[urls.size()]);
     }
 
     private static String getCaptivePortalUserAgent(Context context) {
@@ -680,17 +710,25 @@
         return value != null ? value : defaultValue;
     }
 
+    private URL nextFallbackUrl() {
+        if (mCaptivePortalFallbackUrls.length == 0) {
+            return null;
+        }
+        int idx = Math.abs(mNextFallbackUrlIndex) % mCaptivePortalFallbackUrls.length;
+        mNextFallbackUrlIndex += new Random().nextInt(); // randomely change url without memory.
+        return mCaptivePortalFallbackUrls[idx];
+    }
+
     @VisibleForTesting
     protected CaptivePortalProbeResult isCaptivePortal() {
         if (!mIsCaptivePortalCheckEnabled) {
             validationLog("Validation disabled.");
-            return new CaptivePortalProbeResult(204);
+            return CaptivePortalProbeResult.SUCCESS;
         }
 
         URL pacUrl = null;
         URL httpsUrl = mCaptivePortalHttpsUrl;
         URL httpUrl = mCaptivePortalHttpUrl;
-        URL fallbackUrl = mCaptivePortalFallbackUrl;
 
         // On networks with a PAC instead of fetching a URL that should result in a 204
         // response, we instead simply fetch the PAC script.  This is done for a few reasons:
@@ -727,7 +765,7 @@
         if (pacUrl != null) {
             result = sendDnsAndHttpProbes(null, pacUrl, ValidationProbeEvent.PROBE_PAC);
         } else if (mUseHttps) {
-            result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl, fallbackUrl);
+            result = sendParallelHttpProbes(proxyInfo, httpsUrl, httpUrl);
         } else {
             result = sendDnsAndHttpProbes(proxyInfo, httpUrl, ValidationProbeEvent.PROBE_HTTP);
         }
@@ -789,7 +827,7 @@
     @VisibleForTesting
     protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) {
         HttpURLConnection urlConnection = null;
-        int httpResponseCode = 599;
+        int httpResponseCode = CaptivePortalProbeResult.FAILED_CODE;
         String redirectUrl = null;
         final Stopwatch probeTimer = new Stopwatch().start();
         final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
@@ -828,7 +866,7 @@
                 if (probeType == ValidationProbeEvent.PROBE_PAC) {
                     validationLog(
                             probeType, url, "PAC fetch 200 response interpreted as 204 response.");
-                    httpResponseCode = 204;
+                    httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE;
                 } else if (urlConnection.getContentLengthLong() == 0) {
                     // Consider 200 response with "Content-length=0" to not be a captive portal.
                     // There's no point in considering this a captive portal as the user cannot
@@ -836,20 +874,20 @@
                     // See http://b/9972012.
                     validationLog(probeType, url,
                         "200 response with Content-length=0 interpreted as 204 response.");
-                    httpResponseCode = 204;
+                    httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE;
                 } else if (urlConnection.getContentLengthLong() == -1) {
                     // When no Content-length (default value == -1), attempt to read a byte from the
                     // response. Do not use available() as it is unreliable. See http://b/33498325.
                     if (urlConnection.getInputStream().read() == -1) {
                         validationLog(
                                 probeType, url, "Empty 200 response interpreted as 204 response.");
-                        httpResponseCode = 204;
+                        httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE;
                     }
                 }
             }
         } catch (IOException e) {
-            validationLog(probeType, url, "Probably not a portal: exception " + e);
-            if (httpResponseCode == 599) {
+            validationLog(probeType, url, "Probe failed with exception " + e);
+            if (httpResponseCode == CaptivePortalProbeResult.FAILED_CODE) {
                 // TODO: Ping gateway and DNS server and log results.
             }
         } finally {
@@ -863,7 +901,7 @@
     }
 
     private CaptivePortalProbeResult sendParallelHttpProbes(
-            ProxyInfo proxy, URL httpsUrl, URL httpUrl, URL fallbackUrl) {
+            ProxyInfo proxy, URL httpsUrl, URL httpUrl) {
         // Number of probes to wait for. If a probe completes with a conclusive answer
         // it shortcuts the latch immediately by forcing the count to 0.
         final CountDownLatch latch = new CountDownLatch(2);
@@ -922,7 +960,8 @@
         if (httpsResult.isPortal() || httpsResult.isSuccessful()) {
             return httpsResult;
         }
-        // If a fallback url is specified, use a fallback probe to try again portal detection.
+        // If a fallback url exists, use a fallback probe to try again portal detection.
+        URL fallbackUrl = nextFallbackUrl();
         if (fallbackUrl != null) {
             CaptivePortalProbeResult result =
                     sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK);
@@ -1061,7 +1100,7 @@
     }
 
     private void logValidationProbe(long durationMs, int probeType, int probeResult) {
-        long transports = mNetworkAgentInfo.networkCapabilities.getTransports();
+        int[] transports = mNetworkAgentInfo.networkCapabilities.getTransportTypes();
         boolean isFirstValidation = validationStage().isFirstValidation;
         ValidationProbeEvent ev = new ValidationProbeEvent();
         ev.probeType = ValidationProbeEvent.makeProbeType(probeType, isFirstValidation);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index dad969c..4bc6189 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -80,6 +80,7 @@
 import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
 import com.android.server.connectivity.tethering.IPv6TetheringInterfaceServices;
 import com.android.server.connectivity.tethering.OffloadController;
+import com.android.server.connectivity.tethering.SimChangeListener;
 import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
 import com.android.server.connectivity.tethering.TetheringConfiguration;
 import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
@@ -160,6 +161,7 @@
     private final OffloadController mOffloadController;
     private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
     private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams;
+    private final SimChangeListener mSimChange;
 
     private volatile TetheringConfiguration mConfig;
     private String mCurrentUpstreamIface;
@@ -193,6 +195,8 @@
         mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
                 mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
         mForwardedDownstreams = new HashSet<>();
+        mSimChange = new SimChangeListener(
+                mContext, mTetherMasterSM.getHandler(), () -> reevaluateSimCardProvisioning());
 
         mStateReceiver = new StateReceiver();
         IntentFilter filter = new IntentFilter();
@@ -355,6 +359,20 @@
         return (provisionApp.length == 2);
     }
 
+    // Used by the SIM card change observation code.
+    // TODO: De-duplicate above code.
+    private boolean hasMobileHotspotProvisionApp() {
+        try {
+            if (!mContext.getResources().getString(com.android.internal.R.string.
+                    config_mobile_hotspot_provision_app_no_ui).isEmpty()) {
+                Log.d(TAG, "re-evaluate provisioning");
+                return true;
+            }
+        } catch (Resources.NotFoundException e) {}
+        Log.d(TAG, "no prov-check needed for new SIM");
+        return false;
+    }
+
     /**
      * Enables or disables tethering for the given type. This should only be called once
      * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks
@@ -529,6 +547,16 @@
         }
     }
 
+    // Used by the SIM card change observation code.
+    // TODO: De-duplicate with above code, where possible.
+    private void startProvisionIntent(int tetherType) {
+        final Intent startProvIntent = new Intent();
+        startProvIntent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
+        startProvIntent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
+        startProvIntent.setComponent(TETHER_SERVICE);
+        mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
+    }
+
     public int tether(String iface) {
         return tether(iface, IControlsTethering.STATE_TETHERED);
     }
@@ -1012,6 +1040,29 @@
         return false;
     }
 
+    private void reevaluateSimCardProvisioning() {
+        if (!hasMobileHotspotProvisionApp()) return;
+
+        ArrayList<Integer> tethered = new ArrayList<>();
+        synchronized (mPublicSync) {
+            for (int i = 0; i < mTetherStates.size(); i++) {
+                TetherState tetherState = mTetherStates.valueAt(i);
+                if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
+                    continue;  // Skip interfaces that aren't tethered.
+                }
+                String iface = mTetherStates.keyAt(i);
+                int interfaceType = ifaceNameToType(iface);
+                if (interfaceType != ConnectivityManager.TETHERING_INVALID) {
+                    tethered.add(interfaceType);
+                }
+            }
+        }
+
+        for (int tetherType : tethered) {
+            startProvisionIntent(tetherType);
+        }
+    }
+
     class TetherMasterSM extends StateMachine {
         private static final int BASE_MASTER                    = Protocol.BASE_TETHERING;
         // an interface SM has requested Tethering/Local Hotspot
@@ -1285,127 +1336,6 @@
             }
         }
 
-        private class SimChangeListener {
-            private final Context mContext;
-            private final AtomicInteger mSimBcastGenerationNumber;
-            private BroadcastReceiver mBroadcastReceiver;
-
-            SimChangeListener(Context ctx) {
-                mContext = ctx;
-                mSimBcastGenerationNumber = new AtomicInteger(0);
-            }
-
-            public int generationNumber() {
-                return mSimBcastGenerationNumber.get();
-            }
-
-            public void startListening() {
-                if (DBG) Log.d(TAG, "startListening for SIM changes");
-
-                if (mBroadcastReceiver != null) return;
-
-                mBroadcastReceiver = new SimChangeBroadcastReceiver(
-                        mSimBcastGenerationNumber.incrementAndGet());
-                final IntentFilter filter = new IntentFilter();
-                filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
-
-                mContext.registerReceiver(mBroadcastReceiver, filter, null,
-                        mTetherMasterSM.getHandler());
-            }
-
-            public void stopListening() {
-                if (DBG) Log.d(TAG, "stopListening for SIM changes");
-
-                if (mBroadcastReceiver == null) return;
-
-                mSimBcastGenerationNumber.incrementAndGet();
-                mContext.unregisterReceiver(mBroadcastReceiver);
-                mBroadcastReceiver = null;
-            }
-
-            public boolean hasMobileHotspotProvisionApp() {
-                try {
-                    if (!mContext.getResources().getString(com.android.internal.R.string.
-                            config_mobile_hotspot_provision_app_no_ui).isEmpty()) {
-                        Log.d(TAG, "re-evaluate provisioning");
-                        return true;
-                    }
-                } catch (Resources.NotFoundException e) {}
-                Log.d(TAG, "no prov-check needed for new SIM");
-                return false;
-            }
-
-            private boolean isSimCardLoaded(String state) {
-                return IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state);
-            }
-
-            private void startProvisionIntent(int tetherType) {
-                final Intent startProvIntent = new Intent();
-                startProvIntent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
-                startProvIntent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
-                startProvIntent.setComponent(TETHER_SERVICE);
-                mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
-            }
-
-            private class SimChangeBroadcastReceiver extends BroadcastReceiver {
-                // used to verify this receiver is still current
-                final private int mGenerationNumber;
-
-                // used to check the sim state transition from non-loaded to loaded
-                private boolean mSimNotLoadedSeen = false;
-
-                public SimChangeBroadcastReceiver(int generationNumber) {
-                    mGenerationNumber = generationNumber;
-                }
-
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    final int currentGenerationNumber = mSimBcastGenerationNumber.get();
-
-                    if (DBG) {
-                        Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber +
-                                ", current generationNumber=" + currentGenerationNumber);
-                    }
-                    if (mGenerationNumber != currentGenerationNumber) return;
-
-                    final String state = intent.getStringExtra(
-                            IccCardConstants.INTENT_KEY_ICC_STATE);
-                    Log.d(TAG, "got Sim changed to state " + state + ", mSimNotLoadedSeen=" +
-                            mSimNotLoadedSeen);
-
-                    if (!isSimCardLoaded(state)) {
-                        if (!mSimNotLoadedSeen) mSimNotLoadedSeen = true;
-                        return;
-                    }
-
-                    if (isSimCardLoaded(state) && mSimNotLoadedSeen) {
-                        mSimNotLoadedSeen = false;
-
-                        if (!hasMobileHotspotProvisionApp()) return;
-
-                        ArrayList<Integer> tethered = new ArrayList<Integer>();
-                        synchronized (mPublicSync) {
-                            for (int i = 0; i < mTetherStates.size(); i++) {
-                                TetherState tetherState = mTetherStates.valueAt(i);
-                                if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
-                                    continue;  // Skip interfaces that aren't tethered.
-                                }
-                                String iface = mTetherStates.keyAt(i);
-                                int interfaceType = ifaceNameToType(iface);
-                                if (interfaceType != ConnectivityManager.TETHERING_INVALID) {
-                                    tethered.add(new Integer(interfaceType));
-                                }
-                            }
-                        }
-
-                        for (int tetherType : tethered) {
-                            startProvisionIntent(tetherType);
-                        }
-                    }
-                }
-            }
-        }
-
         private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) {
             if (mNotifyList.indexOf(who) < 0) {
                 mNotifyList.add(who);
@@ -1451,7 +1381,6 @@
         }
 
         class TetherModeAliveState extends TetherMasterUtilState {
-            final SimChangeListener simChange = new SimChangeListener(mContext);
             boolean mUpstreamWanted = false;
             boolean mTryCell = true;
 
@@ -1459,7 +1388,7 @@
             public void enter() {
                 // TODO: examine if we should check the return value.
                 turnOnMasterTetherSettings(); // may transition us out
-                simChange.startListening();
+                mSimChange.startListening();
                 mUpstreamNetworkMonitor.start();
                 mOffloadController.start();
 
@@ -1475,7 +1404,7 @@
                 mOffloadController.stop();
                 unrequestUpstreamMobileConnection();
                 mUpstreamNetworkMonitor.stop();
-                simChange.stopListening();
+                mSimChange.stopListening();
                 notifyTetheredOfNewUpstreamIface(null);
                 handleNewUpstreamNetworkState(null);
             }
diff --git a/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java b/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java
new file mode 100644
index 0000000..3e60f9f
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/SimChangeListener.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.tethering;
+
+import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_LOADED;
+import static com.android.internal.telephony.IccCardConstants.INTENT_KEY_ICC_STATE;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.util.Log;
+
+import com.android.internal.telephony.TelephonyIntents;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+/**
+ * A utility class that runs the provided callback on the provided handler when
+ * observing a new SIM card having been loaded.
+ *
+ * @hide
+ */
+public class SimChangeListener {
+    private static final String TAG = SimChangeListener.class.getSimpleName();
+    private static final boolean DBG = false;
+
+    private final Context mContext;
+    private final Handler mTarget;
+    private final AtomicInteger mSimBcastGenerationNumber;
+    private final Runnable mCallback;
+    private BroadcastReceiver mBroadcastReceiver;
+
+    public SimChangeListener(Context ctx, Handler handler, Runnable onSimCardLoadedCallback) {
+        mContext = ctx;
+        mTarget = handler;
+        mCallback = onSimCardLoadedCallback;
+        mSimBcastGenerationNumber = new AtomicInteger(0);
+    }
+
+    public int generationNumber() {
+        return mSimBcastGenerationNumber.get();
+    }
+
+    public void startListening() {
+        if (DBG) Log.d(TAG, "startListening for SIM changes");
+
+        if (mBroadcastReceiver != null) return;
+
+        mBroadcastReceiver = new SimChangeBroadcastReceiver(
+                mSimBcastGenerationNumber.incrementAndGet());
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+
+        mContext.registerReceiver(mBroadcastReceiver, filter, null, mTarget);
+    }
+
+    public void stopListening() {
+        if (DBG) Log.d(TAG, "stopListening for SIM changes");
+
+        if (mBroadcastReceiver == null) return;
+
+        mSimBcastGenerationNumber.incrementAndGet();
+        mContext.unregisterReceiver(mBroadcastReceiver);
+        mBroadcastReceiver = null;
+    }
+
+    private boolean isSimCardLoaded(String state) {
+        return INTENT_VALUE_ICC_LOADED.equals(state);
+    }
+
+    private class SimChangeBroadcastReceiver extends BroadcastReceiver {
+        // used to verify this receiver is still current
+        final private int mGenerationNumber;
+
+        // used to check the sim state transition from non-loaded to loaded
+        private boolean mSimNotLoadedSeen = false;
+
+        public SimChangeBroadcastReceiver(int generationNumber) {
+            mGenerationNumber = generationNumber;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final int currentGenerationNumber = mSimBcastGenerationNumber.get();
+
+            if (DBG) {
+                Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber +
+                        ", current generationNumber=" + currentGenerationNumber);
+            }
+            if (mGenerationNumber != currentGenerationNumber) return;
+
+            final String state = intent.getStringExtra(INTENT_KEY_ICC_STATE);
+            Log.d(TAG, "got Sim changed to state " + state + ", mSimNotLoadedSeen=" +
+                    mSimNotLoadedSeen);
+
+            if (!isSimCardLoaded(state)) {
+                mSimNotLoadedSeen = true;
+                return;
+            }
+
+            if (mSimNotLoadedSeen) {
+                mSimNotLoadedSeen = false;
+                mCallback.run();
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index 1ffa864..601ed01 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -78,7 +78,6 @@
     public static final int CMD_IPV6_TETHER_UPDATE          = BASE_IFACE + 13;
 
     private final State mInitialState;
-    private final State mServingState;
     private final State mLocalHotspotState;
     private final State mTetheredState;
     private final State mUnavailableState;
@@ -107,14 +106,12 @@
         mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
 
         mInitialState = new InitialState();
-        mServingState = new ServingState();
         mLocalHotspotState = new LocalHotspotState();
         mTetheredState = new TetheredState();
         mUnavailableState = new UnavailableState();
         addState(mInitialState);
-        addState(mServingState);
-            addState(mLocalHotspotState, mServingState);
-            addState(mTetheredState, mServingState);
+        addState(mLocalHotspotState);
+        addState(mTetheredState);
         addState(mUnavailableState);
 
         setInitialState(mInitialState);
@@ -222,12 +219,11 @@
         }
     }
 
-    class ServingState extends State {
+    class BaseServingState extends State {
         @Override
         public void enter() {
             if (!configureIfaceIp(true)) {
                 mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR;
-                transitionTo(mInitialState);
                 return;
             }
 
@@ -236,12 +232,13 @@
             } catch (Exception e) {
                 Log.e(TAG, "Error Tethering: " + e.toString());
                 mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
-                transitionTo(mInitialState);
                 return;
             }
 
             if (!mIPv6TetherSvc.start()) {
                 Log.e(TAG, "Failed to start IPv6TetheringInterfaceServices");
+                // TODO: Make this a fatal error once Bluetooth IPv6 is sorted.
+                return;
             }
         }
 
@@ -254,9 +251,9 @@
 
             try {
                 mNMService.untetherInterface(mIfaceName);
-            } catch (Exception ee) {
+            } catch (Exception e) {
                 mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
-                Log.e(TAG, "Failed to untether interface: " + ee.toString());
+                Log.e(TAG, "Failed to untether interface: " + e.toString());
             }
 
             configureIfaceIp(false);
@@ -293,15 +290,27 @@
         }
     }
 
-    class LocalHotspotState extends State {
+    // Handling errors in BaseServingState.enter() by transitioning is
+    // problematic because transitioning during a multi-state jump yields
+    // a Log.wtf(). Ultimately, there should be only one ServingState,
+    // and forwarding and NAT rules should be handled by a coordinating
+    // functional element outside of TetherInterfaceStateMachine.
+    class LocalHotspotState extends BaseServingState {
         @Override
         public void enter() {
+            super.enter();
+            if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+                transitionTo(mInitialState);
+            }
+
             if (DBG) Log.d(TAG, "Local hotspot " + mIfaceName);
             sendInterfaceState(IControlsTethering.STATE_LOCAL_HOTSPOT);
         }
 
         @Override
         public boolean processMessage(Message message) {
+            if (super.processMessage(message)) return true;
+
             maybeLogMessage(this, message.what);
             switch (message.what) {
                 case CMD_TETHER_REQUESTED:
@@ -317,9 +326,19 @@
         }
     }
 
-    class TetheredState extends State {
+    // Handling errors in BaseServingState.enter() by transitioning is
+    // problematic because transitioning during a multi-state jump yields
+    // a Log.wtf(). Ultimately, there should be only one ServingState,
+    // and forwarding and NAT rules should be handled by a coordinating
+    // functional element outside of TetherInterfaceStateMachine.
+    class TetheredState extends BaseServingState {
         @Override
         public void enter() {
+            super.enter();
+            if (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+                transitionTo(mInitialState);
+            }
+
             if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
             sendInterfaceState(IControlsTethering.STATE_TETHERED);
         }
@@ -327,6 +346,7 @@
         @Override
         public void exit() {
             cleanupUpstream();
+            super.exit();
         }
 
         private void cleanupUpstream() {
@@ -361,6 +381,8 @@
 
         @Override
         public boolean processMessage(Message message) {
+            if (super.processMessage(message)) return true;
+
             maybeLogMessage(this, message.what);
             boolean retValue = true;
             switch (message.what) {
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index 552f0d1..fe49813 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -36,6 +36,7 @@
 
     public abstract boolean handleFailedAttempt();
     public abstract void resetFailedAttempts();
+    private boolean mAlreadyCancelled;
 
     public AuthenticationClient(Context context, long halDeviceId, IBinder token,
             IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId,
@@ -129,6 +130,10 @@
 
     @Override
     public int stop(boolean initiatedByClient) {
+        if (mAlreadyCancelled) {
+            Slog.w(TAG, "stopAuthentication: already cancelled!");
+            return 0;
+        }
         IBiometricsFingerprint daemon = getFingerprintDaemon();
         if (daemon == null) {
             Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
@@ -145,6 +150,7 @@
             Slog.e(TAG, "stopAuthentication failed", e);
             return ERROR_ESRCH;
         }
+        mAlreadyCancelled = true;
         return 0; // success
     }
 
diff --git a/services/core/java/com/android/server/job/GrantedUriPermissions.java b/services/core/java/com/android/server/job/GrantedUriPermissions.java
new file mode 100644
index 0000000..e413d8d
--- /dev/null
+++ b/services/core/java/com/android/server/job/GrantedUriPermissions.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.job;
+
+import android.app.IActivityManager;
+import android.content.ClipData;
+import android.content.ContentProvider;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+public class GrantedUriPermissions {
+    private final int mGrantFlags;
+    private final int mSourceUserId;
+    private final String mTag;
+    private final IBinder mPermissionOwner;
+    private final ArrayList<Uri> mUris = new ArrayList<>();
+
+    private GrantedUriPermissions(IActivityManager am, int grantFlags, int uid, String tag)
+            throws RemoteException {
+        mGrantFlags = grantFlags;
+        mSourceUserId = UserHandle.getUserId(uid);
+        mTag = tag;
+        mPermissionOwner = am.newUriPermissionOwner("job: " + tag);
+    }
+
+    public void revoke(IActivityManager am) {
+        for (int i = mUris.size()-1; i >= 0; i--) {
+            try {
+                am.revokeUriPermissionFromOwner(mPermissionOwner, mUris.get(i),
+                        mGrantFlags, mSourceUserId);
+            } catch (RemoteException e) {
+            }
+        }
+        mUris.clear();
+    }
+
+    public static boolean checkGrantFlags(int grantFlags) {
+        return (grantFlags & (Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                |Intent.FLAG_GRANT_READ_URI_PERMISSION)) != 0;
+    }
+
+    public static GrantedUriPermissions createFromIntent(IActivityManager am, Intent intent,
+            int sourceUid, String targetPackage, int targetUserId, String tag) {
+        int grantFlags = intent.getFlags();
+        if (!checkGrantFlags(grantFlags)) {
+            return null;
+        }
+
+        GrantedUriPermissions perms = null;
+
+        Uri data = intent.getData();
+        if (data != null) {
+            perms = grantUri(am, data, sourceUid, targetPackage, targetUserId, grantFlags, tag,
+                    perms);
+        }
+
+        ClipData clip = intent.getClipData();
+        if (clip != null) {
+            perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags, tag,
+                    perms);
+        }
+
+        return perms;
+    }
+
+    public static GrantedUriPermissions createFromClip(IActivityManager am, ClipData clip,
+            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag) {
+        if (!checkGrantFlags(grantFlags)) {
+            return null;
+        }
+        GrantedUriPermissions perms = null;
+        if (clip != null) {
+            perms = grantClip(am, clip, sourceUid, targetPackage, targetUserId, grantFlags,
+                    tag, perms);
+        }
+        return perms;
+    }
+
+    private static GrantedUriPermissions grantClip(IActivityManager am, ClipData clip,
+            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
+            GrantedUriPermissions curPerms) {
+        final int N = clip.getItemCount();
+        for (int i = 0; i < N; i++) {
+            curPerms = grantItem(am, clip.getItemAt(i), sourceUid, targetPackage, targetUserId,
+                    grantFlags, tag, curPerms);
+        }
+        return curPerms;
+    }
+
+    private static GrantedUriPermissions grantUri(IActivityManager am, Uri uri,
+            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
+            GrantedUriPermissions curPerms) {
+        try {
+            int sourceUserId = ContentProvider.getUserIdFromUri(uri,
+                    UserHandle.getUserId(sourceUid));
+            uri = ContentProvider.getUriWithoutUserId(uri);
+            if (curPerms == null) {
+                curPerms = new GrantedUriPermissions(am, grantFlags, sourceUid, tag);
+            }
+            am.grantUriPermissionFromOwner(curPerms.mPermissionOwner, sourceUid, targetPackage,
+                    uri, grantFlags, sourceUserId, targetUserId);
+            curPerms.mUris.add(uri);
+        } catch (RemoteException e) {
+            Slog.e("JobScheduler", "AM dead");
+        }
+        return curPerms;
+    }
+
+    private static GrantedUriPermissions grantItem(IActivityManager am, ClipData.Item item,
+            int sourceUid, String targetPackage, int targetUserId, int grantFlags, String tag,
+            GrantedUriPermissions curPerms) {
+        if (item.getUri() != null) {
+            curPerms = grantUri(am, item.getUri(), sourceUid, targetPackage, targetUserId,
+                    grantFlags, tag, curPerms);
+        }
+        Intent intent = item.getIntent();
+        if (intent != null && intent.getData() != null) {
+            curPerms = grantUri(am, intent.getData(), sourceUid, targetPackage, targetUserId,
+                    grantFlags, tag, curPerms);
+        }
+        return curPerms;
+    }
+
+    // Dumpsys infrastructure
+    public void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("mGrantFlags=0x"); pw.print(Integer.toHexString(mGrantFlags));
+        pw.print(" mSourceUserId="); pw.println(mSourceUserId);
+        pw.print(prefix); pw.print("mTag="); pw.println(mTag);
+        pw.print(prefix); pw.print("mPermissionOwner="); pw.println(mPermissionOwner);
+        for (int i = 0; i < mUris.size(); i++) {
+            pw.print(prefix); pw.print("#"); pw.print(i); pw.print(": ");
+            pw.println(mUris.get(i));
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index a0d0d77..c8bfa34 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -601,7 +601,7 @@
                 // Fast path: we are adding work to an existing job, and the JobInfo is not
                 // changing.  We can just directly enqueue this work in to the job.
                 if (toCancel.getJob().equals(job)) {
-                    toCancel.enqueueWorkLocked(work);
+                    toCancel.enqueueWorkLocked(ActivityManager.getService(), work);
                     return JobScheduler.RESULT_SUCCESS;
                 }
             }
@@ -625,7 +625,7 @@
             }
             if (work != null) {
                 // If work has been supplied, enqueue it into the new job.
-                jobStatus.enqueueWorkLocked(work);
+                jobStatus.enqueueWorkLocked(ActivityManager.getService(), work);
             }
             startTrackingJobLocked(jobStatus, toCancel);
             mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
@@ -758,7 +758,7 @@
                     final JobStatus executing = jsc.getRunningJob();
                     if (executing != null
                             && (executing.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0) {
-                        jsc.cancelExecutingJob(JobParameters.REASON_DEVICE_IDLE);
+                        jsc.cancelExecutingJobLocked(JobParameters.REASON_DEVICE_IDLE);
                     }
                 }
             } else {
@@ -921,7 +921,7 @@
     private boolean stopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
             boolean writeBack) {
         // Deal with any remaining work items in the old job.
-        jobStatus.stopTrackingJobLocked(incomingJob);
+        jobStatus.stopTrackingJobLocked(ActivityManager.getService(), incomingJob);
 
         // Remove from store as well as controllers.
         final boolean removed = mJobs.remove(jobStatus, writeBack);
@@ -939,7 +939,7 @@
             JobServiceContext jsc = mActiveServices.get(i);
             final JobStatus executing = jsc.getRunningJob();
             if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
-                jsc.cancelExecutingJob(reason);
+                jsc.cancelExecutingJobLocked(reason);
                 return true;
             }
         }
@@ -1071,9 +1071,16 @@
         if (DEBUG) {
             Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
         }
+
+        // If the job wants to be rescheduled, we first need to make the next upcoming
+        // job so we can transfer any appropriate state over from the previous job when
+        // we stop it.
+        final JobStatus rescheduledJob = needsReschedule
+                ? getRescheduleJobForFailureLocked(jobStatus) : null;
+
         // Do not write back immediately if this is a periodic job. The job may get lost if system
         // shuts down before it is added back.
-        if (!stopTrackingJobLocked(jobStatus, null, !jobStatus.getJob().isPeriodic())) {
+        if (!stopTrackingJobLocked(jobStatus, rescheduledJob, !jobStatus.getJob().isPeriodic())) {
             if (DEBUG) {
                 Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
             }
@@ -1082,18 +1089,14 @@
             mHandler.obtainMessage(MSG_CHECK_JOB_GREEDY).sendToTarget();
             return;
         }
-        // Note: there is a small window of time in here where, when rescheduling a job,
-        // we will stop monitoring its content providers.  This should be fixed by stopping
-        // the old job after scheduling the new one, but since we have no lock held here
-        // that may cause ordering problems if the app removes jobStatus while in here.
-        if (needsReschedule) {
-            JobStatus rescheduled = getRescheduleJobForFailureLocked(jobStatus);
+
+        if (rescheduledJob != null) {
             try {
-                rescheduled.prepareLocked(ActivityManager.getService());
+                rescheduledJob.prepareLocked(ActivityManager.getService());
             } catch (SecurityException e) {
-                Slog.w(TAG, "Unable to regrant job permissions for " + rescheduled);
+                Slog.w(TAG, "Unable to regrant job permissions for " + rescheduledJob);
             }
-            startTrackingJobLocked(rescheduled, jobStatus);
+            startTrackingJobLocked(rescheduledJob, jobStatus);
         } else if (jobStatus.getJob().isPeriodic()) {
             JobStatus rescheduledPeriodic = getRescheduleJobForPeriodic(jobStatus);
             try {
@@ -1271,8 +1274,7 @@
                     if (job.hasIdleConstraint()) {
                         idleCount++;
                     }
-                    if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()
-                            || job.hasNotRoamingConstraint()) {
+                    if (job.hasConnectivityConstraint()) {
                         connectivityCount++;
                     }
                     if (job.hasChargingConstraint()) {
@@ -1562,7 +1564,7 @@
                         Slog.d(TAG, "preempting job: " + mActiveServices.get(i).getRunningJob());
                     }
                     // preferredUid will be set to uid of currently running job.
-                    mActiveServices.get(i).preemptExecutingJob();
+                    mActiveServices.get(i).preemptExecutingJobLocked();
                     preservePreferredUid = true;
                 } else {
                     final JobStatus pendingJob = contextIdToJobMap[i];
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index c7ef0e2..9144966 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -44,8 +44,6 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.server.job.controllers.JobStatus;
 
-import java.util.concurrent.atomic.AtomicBoolean;
-
 /**
  * Handles client binding and lifecycle of a job. Jobs execute one at a time on an instance of this
  * class.
@@ -56,19 +54,15 @@
  * job lands, and again when it is complete.
  * - Cancelling is trickier, because there are also interactions from the client. It's possible
  * the {@link com.android.server.job.JobServiceContext.JobServiceHandler} tries to process a
- * {@link #MSG_CANCEL} after the client has already finished. This is handled by having
- * {@link com.android.server.job.JobServiceContext.JobServiceHandler#handleCancelH} check whether
+ * {@link #doCancelLocked(int)} after the client has already finished. This is handled by having
+ * {@link com.android.server.job.JobServiceContext.JobServiceHandler#handleCancelLocked} check whether
  * the context is still valid.
- * To mitigate this, tearing down the context removes all messages from the handler, including any
- * tardy {@link #MSG_CANCEL}s. Additionally, we avoid sending duplicate onStopJob()
+ * To mitigate this, we avoid sending duplicate onStopJob()
  * calls to the client after they've specified jobFinished().
  */
 public class JobServiceContext extends IJobCallback.Stub implements ServiceConnection {
     private static final boolean DEBUG = JobSchedulerService.DEBUG;
     private static final String TAG = "JobServiceContext";
-    /** Define the maximum # of jobs allowed to run on a service at once. */
-    private static final int defaultMaxActiveJobsPerService =
-            ActivityManager.isLowRamDeviceStatic() ? 1 : 3;
     /** Amount of time a job is allowed to execute for before being considered timed-out. */
     private static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000;  // 10mins.
     /** Amount of time the JobScheduler waits for the initial service launch+bind. */
@@ -90,14 +84,6 @@
     // Messages that result from interactions with the client service.
     /** System timed out waiting for a response. */
     private static final int MSG_TIMEOUT = 0;
-    /** Received a callback from client. */
-    private static final int MSG_CALLBACK = 1;
-    /** Run through list and start any ready jobs.*/
-    private static final int MSG_SERVICE_BOUND = 2;
-    /** Cancel a job. */
-    private static final int MSG_CANCEL = 3;
-    /** Shutdown the job. Used when the client crashes and we can't die gracefully.*/
-    private static final int MSG_SHUTDOWN_EXECUTION = 4;
 
     public static final int NO_PREFERRED_UID = -1;
 
@@ -115,7 +101,7 @@
     private JobParameters mParams;
     @VisibleForTesting
     int mVerb;
-    private AtomicBoolean mCancelled = new AtomicBoolean();
+    private boolean mCancelled;
 
     /**
      * All the information maintained about the job currently being executed.
@@ -245,14 +231,12 @@
     }
 
     /** Called externally when a job that was scheduled for execution should be cancelled. */
-    void cancelExecutingJob(int reason) {
-        mCallbackHandler.obtainMessage(MSG_CANCEL, reason, 0 /* unused */).sendToTarget();
+    void cancelExecutingJobLocked(int reason) {
+        doCancelLocked(reason);
     }
 
-    void preemptExecutingJob() {
-        Message m = mCallbackHandler.obtainMessage(MSG_CANCEL);
-        m.arg1 = JobParameters.REASON_PREEMPT;
-        m.sendToTarget();
+    void preemptExecutingJobLocked() {
+        doCancelLocked(JobParameters.REASON_PREEMPT);
     }
 
     int getPreferredUid() {
@@ -273,59 +257,54 @@
 
     @Override
     public void jobFinished(int jobId, boolean reschedule) {
-        if (!verifyCallingUid()) {
-            return;
-        }
-        mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0)
-                .sendToTarget();
+        doCallback(reschedule);
     }
 
     @Override
     public void acknowledgeStopMessage(int jobId, boolean reschedule) {
-        if (!verifyCallingUid()) {
-            return;
-        }
-        mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, reschedule ? 1 : 0)
-                .sendToTarget();
+        doCallback(reschedule);
     }
 
     @Override
     public void acknowledgeStartMessage(int jobId, boolean ongoing) {
-        if (!verifyCallingUid()) {
-            return;
-        }
-        mCallbackHandler.obtainMessage(MSG_CALLBACK, jobId, ongoing ? 1 : 0).sendToTarget();
+        doCallback(ongoing);
     }
 
     @Override
     public JobWorkItem dequeueWork(int jobId) {
-        if (!verifyCallingUid()) {
-            throw new SecurityException("Bad calling uid: " + Binder.getCallingUid());
-        }
-        JobWorkItem work = null;
-        boolean stillWorking = false;
-        synchronized (mLock) {
-            if (mRunningJob != null) {
-                work = mRunningJob.dequeueWorkLocked();
-                stillWorking = mRunningJob.hasExecutingWorkLocked();
+        final int callingUid = Binder.getCallingUid();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                if (!verifyCallingUidLocked(callingUid)) {
+                    throw new SecurityException("Bad calling uid: " + callingUid);
+                }
+
+                final JobWorkItem work = mRunningJob.dequeueWorkLocked();
+                if (work == null && !mRunningJob.hasExecutingWorkLocked()) {
+                    // This will finish the job.
+                    doCallbackLocked(false);
+                }
+                return work;
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
-        if (work == null && !stillWorking) {
-            jobFinished(jobId, false);
-        }
-        return work;
     }
 
     @Override
     public boolean completeWork(int jobId, int workId) {
-        if (!verifyCallingUid()) {
-            throw new SecurityException("Bad calling uid: " + Binder.getCallingUid());
-        }
-        synchronized (mLock) {
-            if (mRunningJob != null) {
-                return mRunningJob.completeWorkLocked(workId);
+        final int callingUid = Binder.getCallingUid();
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                if (!verifyCallingUidLocked(callingUid)) {
+                    throw new SecurityException("Bad calling uid: " + callingUid);
+                }
+                return mRunningJob.completeWorkLocked(ActivityManager.getService(), workId);
             }
-            return false;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -344,20 +323,20 @@
             // looper and at this point we can't get any binder callbacks from the client. Better
             // safe than sorry.
             runningJob = mRunningJob;
-        }
-        if (runningJob == null || !name.equals(runningJob.getServiceComponent())) {
-            mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget();
-            return;
-        }
-        this.service = IJobService.Stub.asInterface(service);
-        final PowerManager pm =
-                (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
-                runningJob.getTag());
-        wl.setWorkSource(new WorkSource(runningJob.getSourceUid()));
-        wl.setReferenceCounted(false);
-        wl.acquire();
-        synchronized (mLock) {
+
+            if (runningJob == null || !name.equals(runningJob.getServiceComponent())) {
+                closeAndCleanupJobLocked(true /* needsReschedule */);
+                return;
+            }
+            this.service = IJobService.Stub.asInterface(service);
+            final PowerManager pm =
+                    (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+            PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+                    runningJob.getTag());
+            wl.setWorkSource(new WorkSource(runningJob.getSourceUid()));
+            wl.setReferenceCounted(false);
+            wl.acquire();
+
             // We use a new wakelock instance per job.  In rare cases there is a race between
             // teardown following job completion/cancellation and new job service spin-up
             // such that if we simply assign mWakeLock to be the new instance, we orphan
@@ -369,14 +348,16 @@
                 mWakeLock.release();
             }
             mWakeLock = wl;
+            doServiceBoundLocked();
         }
-        mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget();
     }
 
     /** If the client service crashes we reschedule this job and clean up. */
     @Override
     public void onServiceDisconnected(ComponentName name) {
-        mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget();
+        synchronized (mLock) {
+            closeAndCleanupJobLocked(true /* needsReschedule */);
+        }
     }
 
     /**
@@ -384,22 +365,18 @@
      * whether the client exercising the callback is the client we expect.
      * @return True if the binder calling is coming from the client we expect.
      */
-    private boolean verifyCallingUid() {
-        synchronized (mLock) {
-            if (mRunningJob == null || Binder.getCallingUid() != mRunningJob.getUid()) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Stale callback received, ignoring.");
-                }
-                return false;
+    private boolean verifyCallingUidLocked(final int callingUid) {
+        if (mRunningJob == null || callingUid != mRunningJob.getUid()) {
+            if (DEBUG) {
+                Slog.d(TAG, "Stale callback received, ignoring.");
             }
-            return true;
+            return false;
         }
+        return true;
     }
 
     /**
-     * Handles the lifecycle of the JobService binding/callbacks, etc. The convention within this
-     * class is to append 'H' to each function name that can only be called on this handler. This
-     * isn't strictly necessary because all of these functions are private, but helps clarity.
+     * Scheduling of async messages (basically timeouts at this point).
      */
     private class JobServiceHandler extends Handler {
         JobServiceHandler(Looper looper) {
@@ -409,296 +386,280 @@
         @Override
         public void handleMessage(Message message) {
             switch (message.what) {
-                case MSG_SERVICE_BOUND:
-                    doServiceBound();
-                    break;
-                case MSG_CALLBACK:
-                    doCallback(message.arg2);
-                    break;
-                case MSG_CANCEL:
-                    doCancel(message.arg1);
-                    break;
                 case MSG_TIMEOUT:
                     synchronized (mLock) {
-                        handleOpTimeoutH();
+                        handleOpTimeoutLocked();
                     }
                     break;
-                case MSG_SHUTDOWN_EXECUTION:
-                    closeAndCleanupJobH(true /* needsReschedule */);
-                    break;
                 default:
                     Slog.e(TAG, "Unrecognised message: " + message);
             }
         }
+    }
 
-        void doServiceBound() {
+    void doServiceBoundLocked() {
+        removeOpTimeOutLocked();
+        handleServiceBoundLocked();
+    }
+
+    void doCallback(boolean reschedule) {
+        final int callingUid = Binder.getCallingUid();
+        final long ident = Binder.clearCallingIdentity();
+        try {
             synchronized (mLock) {
-                removeOpTimeOutLocked();
-                handleServiceBoundH();
-            }
-        }
-
-        void doCallback(int arg2) {
-            synchronized (mLock) {
-                if (DEBUG) {
-                    Slog.d(TAG, "MSG_CALLBACK of : " + mRunningJob
-                            + " v:" + VERB_STRINGS[mVerb]);
-                }
-                removeOpTimeOutLocked();
-
-                if (mVerb == VERB_STARTING) {
-                    final boolean workOngoing = arg2 == 1;
-                    handleStartedH(workOngoing);
-                } else if (mVerb == VERB_EXECUTING ||
-                        mVerb == VERB_STOPPING) {
-                    final boolean reschedule = arg2 == 1;
-                    handleFinishedH(reschedule);
-                } else {
-                    if (DEBUG) {
-                        Slog.d(TAG, "Unrecognised callback: " + mRunningJob);
-                    }
-                }
-            }
-        }
-
-        void doCancel(int arg1) {
-            synchronized (mLock) {
-                if (mVerb == VERB_FINISHED) {
-                    if (DEBUG) {
-                        Slog.d(TAG,
-                                "Trying to process cancel for torn-down context, ignoring.");
-                    }
+                if (!verifyCallingUidLocked(callingUid)) {
                     return;
                 }
-                mParams.setStopReason(arg1);
-                if (arg1 == JobParameters.REASON_PREEMPT) {
-                    mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
-                            NO_PREFERRED_UID;
-                }
-                handleCancelH();
+                doCallbackLocked(reschedule);
             }
-
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
+    }
 
-        /** Start the job on the service. */
-        private void handleServiceBoundH() {
+    void doCallbackLocked(boolean reschedule) {
+        if (DEBUG) {
+            Slog.d(TAG, "doCallback of : " + mRunningJob
+                    + " v:" + VERB_STRINGS[mVerb]);
+        }
+        removeOpTimeOutLocked();
+
+        if (mVerb == VERB_STARTING) {
+            handleStartedLocked(reschedule);
+        } else if (mVerb == VERB_EXECUTING ||
+                mVerb == VERB_STOPPING) {
+            handleFinishedLocked(reschedule);
+        } else {
             if (DEBUG) {
-                Slog.d(TAG, "MSG_SERVICE_BOUND for " + mRunningJob.toShortString());
-            }
-            if (mVerb != VERB_BINDING) {
-                Slog.e(TAG, "Sending onStartJob for a job that isn't pending. "
-                        + VERB_STRINGS[mVerb]);
-                closeAndCleanupJobH(false /* reschedule */);
-                return;
-            }
-            if (mCancelled.get()) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Job cancelled while waiting for bind to complete. "
-                            + mRunningJob);
-                }
-                closeAndCleanupJobH(true /* reschedule */);
-                return;
-            }
-            try {
-                mVerb = VERB_STARTING;
-                scheduleOpTimeOutLocked();
-                service.startJob(mParams);
-            } catch (Exception e) {
-                // We catch 'Exception' because client-app malice or bugs might induce a wide
-                // range of possible exception-throw outcomes from startJob() and its handling
-                // of the client's ParcelableBundle extras.
-                Slog.e(TAG, "Error sending onStart message to '" +
-                        mRunningJob.getServiceComponent().getShortClassName() + "' ", e);
+                Slog.d(TAG, "Unrecognised callback: " + mRunningJob);
             }
         }
+    }
 
-        /**
-         * State behaviours.
-         * VERB_STARTING   -> Successful start, change job to VERB_EXECUTING and post timeout.
-         *     _PENDING    -> Error
-         *     _EXECUTING  -> Error
-         *     _STOPPING   -> Error
-         */
-        private void handleStartedH(boolean workOngoing) {
-            switch (mVerb) {
-                case VERB_STARTING:
-                    mVerb = VERB_EXECUTING;
-                    if (!workOngoing) {
-                        // Job is finished already so fast-forward to handleFinished.
-                        handleFinishedH(false);
-                        return;
-                    }
-                    if (mCancelled.get()) {
-                        if (DEBUG) {
-                            Slog.d(TAG, "Job cancelled while waiting for onStartJob to complete.");
-                        }
-                        // Cancelled *while* waiting for acknowledgeStartMessage from client.
-                        handleCancelH();
-                        return;
-                    }
-                    scheduleOpTimeOutLocked();
-                    break;
-                default:
-                    Slog.e(TAG, "Handling started job but job wasn't starting! Was "
-                            + VERB_STRINGS[mVerb] + ".");
-                    return;
+    void doCancelLocked(int arg1) {
+        if (mVerb == VERB_FINISHED) {
+            if (DEBUG) {
+                Slog.d(TAG,
+                        "Trying to process cancel for torn-down context, ignoring.");
             }
+            return;
         }
-
-        /**
-         * VERB_EXECUTING  -> Client called jobFinished(), clean up and notify done.
-         *     _STOPPING   -> Successful finish, clean up and notify done.
-         *     _STARTING   -> Error
-         *     _PENDING    -> Error
-         */
-        private void handleFinishedH(boolean reschedule) {
-            switch (mVerb) {
-                case VERB_EXECUTING:
-                case VERB_STOPPING:
-                    closeAndCleanupJobH(reschedule);
-                    break;
-                default:
-                    Slog.e(TAG, "Got an execution complete message for a job that wasn't being" +
-                            "executed. Was " + VERB_STRINGS[mVerb] + ".");
-            }
+        mParams.setStopReason(arg1);
+        if (arg1 == JobParameters.REASON_PREEMPT) {
+            mPreferredUid = mRunningJob != null ? mRunningJob.getUid() :
+                    NO_PREFERRED_UID;
         }
+        handleCancelLocked();
+    }
 
-        /**
-         * A job can be in various states when a cancel request comes in:
-         * VERB_BINDING    -> Cancelled before bind completed. Mark as cancelled and wait for
-         *                    {@link #onServiceConnected(android.content.ComponentName, android.os.IBinder)}
-         *     _STARTING   -> Mark as cancelled and wait for
-         *                    {@link JobServiceContext#acknowledgeStartMessage(int, boolean)}
-         *     _EXECUTING  -> call {@link #sendStopMessageH}}, but only if there are no callbacks
-         *                      in the message queue.
-         *     _ENDING     -> No point in doing anything here, so we ignore.
-         */
-        private void handleCancelH() {
-            if (JobSchedulerService.DEBUG) {
-                Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " "
-                        + VERB_STRINGS[mVerb]);
-            }
-            switch (mVerb) {
-                case VERB_BINDING:
-                case VERB_STARTING:
-                    mCancelled.set(true);
-                    break;
-                case VERB_EXECUTING:
-                    if (hasMessages(MSG_CALLBACK)) {
-                        // If the client has called jobFinished, ignore this cancel.
-                        return;
-                    }
-                    sendStopMessageH();
-                    break;
-                case VERB_STOPPING:
-                    // Nada.
-                    break;
-                default:
-                    Slog.e(TAG, "Cancelling a job without a valid verb: " + mVerb);
-                    break;
-            }
+    /** Start the job on the service. */
+    private void handleServiceBoundLocked() {
+        if (DEBUG) {
+            Slog.d(TAG, "handleServiceBound for " + mRunningJob.toShortString());
         }
-
-        /** Process MSG_TIMEOUT here. */
-        private void handleOpTimeoutH() {
-            switch (mVerb) {
-                case VERB_BINDING:
-                    Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
-                            ", dropping.");
-                    closeAndCleanupJobH(false /* needsReschedule */);
-                    break;
-                case VERB_STARTING:
-                    // Client unresponsive - wedged or failed to respond in time. We don't really
-                    // know what happened so let's log it and notify the JobScheduler
-                    // FINISHED/NO-RETRY.
-                    Slog.e(TAG, "No response from client for onStartJob '" +
-                            mRunningJob.toShortString());
-                    closeAndCleanupJobH(false /* needsReschedule */);
-                    break;
-                case VERB_STOPPING:
-                    // At least we got somewhere, so fail but ask the JobScheduler to reschedule.
-                    Slog.e(TAG, "No response from client for onStopJob, '" +
-                            mRunningJob.toShortString());
-                    closeAndCleanupJobH(true /* needsReschedule */);
-                    break;
-                case VERB_EXECUTING:
-                    // Not an error - client ran out of time.
-                    Slog.i(TAG, "Client timed out while executing (no jobFinished received)." +
-                            " sending onStop. "  + mRunningJob.toShortString());
-                    mParams.setStopReason(JobParameters.REASON_TIMEOUT);
-                    sendStopMessageH();
-                    break;
-                default:
-                    Slog.e(TAG, "Handling timeout for an invalid job state: " +
-                            mRunningJob.toShortString() + ", dropping.");
-                    closeAndCleanupJobH(false /* needsReschedule */);
-            }
+        if (mVerb != VERB_BINDING) {
+            Slog.e(TAG, "Sending onStartJob for a job that isn't pending. "
+                    + VERB_STRINGS[mVerb]);
+            closeAndCleanupJobLocked(false /* reschedule */);
+            return;
         }
-
-        /**
-         * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING ->
-         * VERB_STOPPING.
-         */
-        private void sendStopMessageH() {
-            removeOpTimeOutLocked();
-            if (mVerb != VERB_EXECUTING) {
-                Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob);
-                closeAndCleanupJobH(false /* reschedule */);
-                return;
+        if (mCancelled) {
+            if (DEBUG) {
+                Slog.d(TAG, "Job cancelled while waiting for bind to complete. "
+                        + mRunningJob);
             }
-            try {
-                mVerb = VERB_STOPPING;
-                scheduleOpTimeOutLocked();
-                service.stopJob(mParams);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Error sending onStopJob to client.", e);
-                // The job's host app apparently crashed during the job, so we should reschedule.
-                closeAndCleanupJobH(true /* reschedule */);
-            }
+            closeAndCleanupJobLocked(true /* reschedule */);
+            return;
         }
+        try {
+            mVerb = VERB_STARTING;
+            scheduleOpTimeOutLocked();
+            service.startJob(mParams);
+        } catch (Exception e) {
+            // We catch 'Exception' because client-app malice or bugs might induce a wide
+            // range of possible exception-throw outcomes from startJob() and its handling
+            // of the client's ParcelableBundle extras.
+            Slog.e(TAG, "Error sending onStart message to '" +
+                    mRunningJob.getServiceComponent().getShortClassName() + "' ", e);
+        }
+    }
 
-        /**
-         * The provided job has finished, either by calling
-         * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)}
-         * or from acknowledging the stop message we sent. Either way, we're done tracking it and
-         * we want to clean up internally.
-         */
-        private void closeAndCleanupJobH(boolean reschedule) {
-            final JobStatus completedJob;
-            synchronized (mLock) {
-                if (mVerb == VERB_FINISHED) {
+    /**
+     * State behaviours.
+     * VERB_STARTING   -> Successful start, change job to VERB_EXECUTING and post timeout.
+     *     _PENDING    -> Error
+     *     _EXECUTING  -> Error
+     *     _STOPPING   -> Error
+     */
+    private void handleStartedLocked(boolean workOngoing) {
+        switch (mVerb) {
+            case VERB_STARTING:
+                mVerb = VERB_EXECUTING;
+                if (!workOngoing) {
+                    // Job is finished already so fast-forward to handleFinished.
+                    handleFinishedLocked(false);
                     return;
                 }
-                completedJob = mRunningJob;
-                mJobPackageTracker.noteInactive(completedJob);
-                try {
-                    mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(),
-                            mRunningJob.getSourceUid());
-                } catch (RemoteException e) {
-                    // Whatever.
+                if (mCancelled) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Job cancelled while waiting for onStartJob to complete.");
+                    }
+                    // Cancelled *while* waiting for acknowledgeStartMessage from client.
+                    handleCancelLocked();
+                    return;
                 }
-                if (mWakeLock != null) {
-                    mWakeLock.release();
-                }
-                mContext.unbindService(JobServiceContext.this);
-                mWakeLock = null;
-                mRunningJob = null;
-                mParams = null;
-                mVerb = VERB_FINISHED;
-                mCancelled.set(false);
-                service = null;
-                mAvailable = true;
-                removeOpTimeOutLocked();
-                removeMessages(MSG_CALLBACK);
-                removeMessages(MSG_SERVICE_BOUND);
-                removeMessages(MSG_CANCEL);
-                removeMessages(MSG_SHUTDOWN_EXECUTION);
-                mCompletedListener.onJobCompletedLocked(completedJob, reschedule);
-            }
+                scheduleOpTimeOutLocked();
+                break;
+            default:
+                Slog.e(TAG, "Handling started job but job wasn't starting! Was "
+                        + VERB_STRINGS[mVerb] + ".");
+                return;
         }
     }
 
     /**
+     * VERB_EXECUTING  -> Client called jobFinished(), clean up and notify done.
+     *     _STOPPING   -> Successful finish, clean up and notify done.
+     *     _STARTING   -> Error
+     *     _PENDING    -> Error
+     */
+    private void handleFinishedLocked(boolean reschedule) {
+        switch (mVerb) {
+            case VERB_EXECUTING:
+            case VERB_STOPPING:
+                closeAndCleanupJobLocked(reschedule);
+                break;
+            default:
+                Slog.e(TAG, "Got an execution complete message for a job that wasn't being" +
+                        "executed. Was " + VERB_STRINGS[mVerb] + ".");
+        }
+    }
+
+    /**
+     * A job can be in various states when a cancel request comes in:
+     * VERB_BINDING    -> Cancelled before bind completed. Mark as cancelled and wait for
+     *                    {@link #onServiceConnected(android.content.ComponentName, android.os.IBinder)}
+     *     _STARTING   -> Mark as cancelled and wait for
+     *                    {@link JobServiceContext#acknowledgeStartMessage(int, boolean)}
+     *     _EXECUTING  -> call {@link #sendStopMessageLocked}}, but only if there are no callbacks
+     *                      in the message queue.
+     *     _ENDING     -> No point in doing anything here, so we ignore.
+     */
+    private void handleCancelLocked() {
+        if (JobSchedulerService.DEBUG) {
+            Slog.d(TAG, "Handling cancel for: " + mRunningJob.getJobId() + " "
+                    + VERB_STRINGS[mVerb]);
+        }
+        switch (mVerb) {
+            case VERB_BINDING:
+            case VERB_STARTING:
+                mCancelled = true;
+                break;
+            case VERB_EXECUTING:
+                sendStopMessageLocked();
+                break;
+            case VERB_STOPPING:
+                // Nada.
+                break;
+            default:
+                Slog.e(TAG, "Cancelling a job without a valid verb: " + mVerb);
+                break;
+        }
+    }
+
+    /** Process MSG_TIMEOUT here. */
+    private void handleOpTimeoutLocked() {
+        switch (mVerb) {
+            case VERB_BINDING:
+                Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
+                        ", dropping.");
+                closeAndCleanupJobLocked(false /* needsReschedule */);
+                break;
+            case VERB_STARTING:
+                // Client unresponsive - wedged or failed to respond in time. We don't really
+                // know what happened so let's log it and notify the JobScheduler
+                // FINISHED/NO-RETRY.
+                Slog.e(TAG, "No response from client for onStartJob '" +
+                        mRunningJob.toShortString());
+                closeAndCleanupJobLocked(false /* needsReschedule */);
+                break;
+            case VERB_STOPPING:
+                // At least we got somewhere, so fail but ask the JobScheduler to reschedule.
+                Slog.e(TAG, "No response from client for onStopJob, '" +
+                        mRunningJob.toShortString());
+                closeAndCleanupJobLocked(true /* needsReschedule */);
+                break;
+            case VERB_EXECUTING:
+                // Not an error - client ran out of time.
+                Slog.i(TAG, "Client timed out while executing (no jobFinished received)." +
+                        " sending onStop. "  + mRunningJob.toShortString());
+                mParams.setStopReason(JobParameters.REASON_TIMEOUT);
+                sendStopMessageLocked();
+                break;
+            default:
+                Slog.e(TAG, "Handling timeout for an invalid job state: " +
+                        mRunningJob.toShortString() + ", dropping.");
+                closeAndCleanupJobLocked(false /* needsReschedule */);
+        }
+    }
+
+    /**
+     * Already running, need to stop. Will switch {@link #mVerb} from VERB_EXECUTING ->
+     * VERB_STOPPING.
+     */
+    private void sendStopMessageLocked() {
+        removeOpTimeOutLocked();
+        if (mVerb != VERB_EXECUTING) {
+            Slog.e(TAG, "Sending onStopJob for a job that isn't started. " + mRunningJob);
+            closeAndCleanupJobLocked(false /* reschedule */);
+            return;
+        }
+        try {
+            mVerb = VERB_STOPPING;
+            scheduleOpTimeOutLocked();
+            service.stopJob(mParams);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Error sending onStopJob to client.", e);
+            // The job's host app apparently crashed during the job, so we should reschedule.
+            closeAndCleanupJobLocked(true /* reschedule */);
+        }
+    }
+
+    /**
+     * The provided job has finished, either by calling
+     * {@link android.app.job.JobService#jobFinished(android.app.job.JobParameters, boolean)}
+     * or from acknowledging the stop message we sent. Either way, we're done tracking it and
+     * we want to clean up internally.
+     */
+    private void closeAndCleanupJobLocked(boolean reschedule) {
+        final JobStatus completedJob;
+        if (mVerb == VERB_FINISHED) {
+            return;
+        }
+        completedJob = mRunningJob;
+        mJobPackageTracker.noteInactive(completedJob);
+        try {
+            mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(),
+                    mRunningJob.getSourceUid());
+        } catch (RemoteException e) {
+            // Whatever.
+        }
+        if (mWakeLock != null) {
+            mWakeLock.release();
+        }
+        mContext.unbindService(JobServiceContext.this);
+        mWakeLock = null;
+        mRunningJob = null;
+        mParams = null;
+        mVerb = VERB_FINISHED;
+        mCancelled = false;
+        service = null;
+        mAvailable = true;
+        removeOpTimeOutLocked();
+        mCompletedListener.onJobCompletedLocked(completedJob, reschedule);
+    }
+
+    /**
      * Called when sending a message to the client, over whose execution we have no control. If
      * we haven't received a response in a certain amount of time, we want to give up and carry
      * on with life.
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index fcc0827..2e6cd3f 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -368,13 +368,16 @@
          */
         private void writeConstraintsToXml(XmlSerializer out, JobStatus jobStatus) throws IOException {
             out.startTag(null, XML_TAG_PARAMS_CONSTRAINTS);
-            if (jobStatus.hasConnectivityConstraint()) {
+            if (jobStatus.needsAnyConnectivity()) {
                 out.attribute(null, "connectivity", Boolean.toString(true));
             }
-            if (jobStatus.hasUnmeteredConstraint()) {
+            if (jobStatus.needsMeteredConnectivity()) {
+                out.attribute(null, "metered", Boolean.toString(true));
+            }
+            if (jobStatus.needsUnmeteredConnectivity()) {
                 out.attribute(null, "unmetered", Boolean.toString(true));
             }
-            if (jobStatus.hasNotRoamingConstraint()) {
+            if (jobStatus.needsNonRoamingConnectivity()) {
                 out.attribute(null, "not-roaming", Boolean.toString(true));
             }
             if (jobStatus.hasIdleConstraint()) {
@@ -713,6 +716,10 @@
             if (val != null) {
                 jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
             }
+            val = parser.getAttributeValue(null, "metered");
+            if (val != null) {
+                jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_METERED);
+            }
             val = parser.getAttributeValue(null, "unmetered");
             if (val != null) {
                 jobBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index b458d8b..5ebcc93c 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -84,8 +84,7 @@
 
     @Override
     public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
-        if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()
-                || jobStatus.hasNotRoamingConstraint()) {
+        if (jobStatus.hasConnectivityConstraint()) {
             updateConstraintsSatisfied(jobStatus, null);
             mTrackedJobs.add(jobStatus);
         }
@@ -94,8 +93,7 @@
     @Override
     public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
             boolean forUpdate) {
-        if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()
-                || jobStatus.hasNotRoamingConstraint()) {
+        if (jobStatus.hasConnectivityConstraint()) {
             mTrackedJobs.remove(jobStatus);
         }
     }
@@ -114,11 +112,13 @@
                 && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
         final boolean connected = info != null && info.isConnected();
         final boolean connectionUsable = connected && validated;
+        final boolean metered = connected && info.isMetered();
         final boolean unmetered = connected && !info.isMetered();
         final boolean notRoaming = connected && !info.isRoaming();
 
         boolean changed = false;
         changed |= jobStatus.setConnectivityConstraintSatisfied(connectionUsable);
+        changed |= jobStatus.setMeteredConstraintSatisfied(metered);
         changed |= jobStatus.setUnmeteredConstraintSatisfied(unmetered);
         changed |= jobStatus.setNotRoamingConstraintSatisfied(notRoaming);
 
@@ -134,6 +134,7 @@
                     + " for " + jobStatus + ": usable=" + connectionUsable
                     + " connected=" + connected
                     + " validated=" + validated
+                    + " metered=" + metered
                     + " unmetered=" + unmetered
                     + " notRoaming=" + notRoaming);
         }
@@ -244,9 +245,10 @@
                 js.printUniqueId(pw);
                 pw.print(" from ");
                 UserHandle.formatUid(pw, js.getSourceUid());
-                pw.print(": C="); pw.print(js.hasConnectivityConstraint());
-                pw.print(": UM="); pw.print(js.hasUnmeteredConstraint());
-                pw.print(": NR="); pw.println(js.hasNotRoamingConstraint());
+                pw.print(": C="); pw.print(js.needsAnyConnectivity());
+                pw.print(": M="); pw.print(js.needsMeteredConnectivity());
+                pw.print(": UM="); pw.print(js.needsUnmeteredConnectivity());
+                pw.print(": NR="); pw.println(js.needsNonRoamingConnectivity());
             }
         }
     }
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 4cdce5f..1ab66b9 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -26,7 +26,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -35,6 +34,8 @@
 import android.util.Slog;
 import android.util.TimeUtils;
 
+import com.android.server.job.GrantedUriPermissions;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -68,6 +69,11 @@
     static final int CONSTRAINT_CONTENT_TRIGGER = 1<<26;
     static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<25;
     static final int CONSTRAINT_NOT_ROAMING = 1<<24;
+    static final int CONSTRAINT_METERED = 1<<23;
+
+    static final int CONNECTIVITY_MASK =
+            CONSTRAINT_UNMETERED | CONSTRAINT_CONNECTIVITY |
+            CONSTRAINT_NOT_ROAMING | CONSTRAINT_METERED;
 
     // Soft override: ignore constraints like time that don't affect API availability
     public static final int OVERRIDE_SOFT = 1;
@@ -98,7 +104,7 @@
 
     final String tag;
 
-    private IBinder permissionOwner;
+    private GrantedUriPermissions uriPerms;
     private boolean prepared;
 
     /**
@@ -191,15 +197,28 @@
         this.numFailures = numFailures;
 
         int requiredConstraints = job.getConstraintFlags();
-        if (job.getNetworkType() == JobInfo.NETWORK_TYPE_ANY) {
-            requiredConstraints |= CONSTRAINT_CONNECTIVITY;
+
+        switch (job.getNetworkType()) {
+            case JobInfo.NETWORK_TYPE_NONE:
+                // No constraint.
+                break;
+            case JobInfo.NETWORK_TYPE_ANY:
+                requiredConstraints |= CONSTRAINT_CONNECTIVITY;
+                break;
+            case JobInfo.NETWORK_TYPE_UNMETERED:
+                requiredConstraints |= CONSTRAINT_UNMETERED;
+                break;
+            case JobInfo.NETWORK_TYPE_NOT_ROAMING:
+                requiredConstraints |= CONSTRAINT_NOT_ROAMING;
+                break;
+            case JobInfo.NETWORK_TYPE_METERED:
+                requiredConstraints |= CONSTRAINT_METERED;
+                break;
+            default:
+                Slog.w(TAG, "Unrecognized networking constraint " + job.getNetworkType());
+                break;
         }
-        if (job.getNetworkType() == JobInfo.NETWORK_TYPE_UNMETERED) {
-            requiredConstraints |= CONSTRAINT_UNMETERED;
-        }
-        if (job.getNetworkType() == JobInfo.NETWORK_TYPE_NOT_ROAMING) {
-            requiredConstraints |= CONSTRAINT_NOT_ROAMING;
-        }
+
         if (earliestRunTimeElapsedMillis != NO_EARLIEST_RUNTIME) {
             requiredConstraints |= CONSTRAINT_TIMING_DELAY;
         }
@@ -266,12 +285,17 @@
                 earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
     }
 
-    public void enqueueWorkLocked(JobWorkItem work) {
+    public void enqueueWorkLocked(IActivityManager am, JobWorkItem work) {
         if (pendingWork == null) {
             pendingWork = new ArrayList<>();
         }
         work.setWorkId(nextPendingWorkId);
         nextPendingWorkId++;
+        if (work.getIntent() != null
+                && GrantedUriPermissions.checkGrantFlags(work.getIntent().getFlags())) {
+            work.setGrants(GrantedUriPermissions.createFromIntent(am, work.getIntent(), sourceUid,
+                    sourcePackageName, sourceUserId, toShortString()));
+        }
         pendingWork.add(work);
     }
 
@@ -293,12 +317,20 @@
         return executingWork != null && executingWork.size() > 0;
     }
 
-    public boolean completeWorkLocked(int workId) {
+    private static void ungrantWorkItem(IActivityManager am, JobWorkItem work) {
+        if (work.getGrants() != null) {
+            ((GrantedUriPermissions)work.getGrants()).revoke(am);
+        }
+    }
+
+    public boolean completeWorkLocked(IActivityManager am, int workId) {
         if (executingWork != null) {
             final int N = executingWork.size();
             for (int i = 0; i < N; i++) {
-                if (executingWork.get(i).getWorkId() == workId) {
+                JobWorkItem work = executingWork.get(i);
+                if (work.getWorkId() == workId) {
                     executingWork.remove(i);
+                    ungrantWorkItem(am, work);
                     return true;
                 }
             }
@@ -306,15 +338,36 @@
         return false;
     }
 
-    public void stopTrackingJobLocked(JobStatus incomingJob) {
+    private static void ungrantWorkList(IActivityManager am, ArrayList<JobWorkItem> list) {
+        if (list != null) {
+            final int N = list.size();
+            for (int i = 0; i < N; i++) {
+                ungrantWorkItem(am, list.get(i));
+            }
+        }
+    }
+
+    public void stopTrackingJobLocked(IActivityManager am, JobStatus incomingJob) {
         if (incomingJob != null) {
-            // We are replacing with a new job -- transfer the work!
-            incomingJob.pendingWork = pendingWork;
+            // We are replacing with a new job -- transfer the work!  We do any executing
+            // work first, since that was originally at the front of the pending work.
+            if (executingWork != null && executingWork.size() > 0) {
+                incomingJob.pendingWork = executingWork;
+            }
+            if (incomingJob.pendingWork == null) {
+                incomingJob.pendingWork = pendingWork;
+            } else if (pendingWork != null && pendingWork.size() > 0) {
+                incomingJob.pendingWork.addAll(pendingWork);
+            }
             pendingWork = null;
+            executingWork = null;
             incomingJob.nextPendingWorkId = nextPendingWorkId;
         } else {
             // We are completely stopping the job...  need to clean up work.
-            // XXX remove perms when that is impl.
+            ungrantWorkList(am, pendingWork);
+            pendingWork = null;
+            ungrantWorkList(am, executingWork);
+            executingWork = null;
         }
     }
 
@@ -326,10 +379,8 @@
         prepared = true;
         final ClipData clip = job.getClipData();
         if (clip != null) {
-            final int N = clip.getItemCount();
-            for (int i = 0; i < N; i++) {
-                grantItemLocked(am, clip.getItemAt(i), sourceUid, sourcePackageName, sourceUserId);
-            }
+            uriPerms = GrantedUriPermissions.createFromClip(am, clip, sourceUid, sourcePackageName,
+                    sourceUserId, job.getClipGrantFlags(), toShortString());
         }
     }
 
@@ -339,14 +390,9 @@
             return;
         }
         prepared = false;
-        if (permissionOwner != null) {
-            final ClipData clip = job.getClipData();
-            if (clip != null) {
-                final int N = clip.getItemCount();
-                for (int i = 0; i < N; i++) {
-                    revokeItemLocked(am, clip.getItemAt(i));
-                }
-            }
+        if (uriPerms != null) {
+            uriPerms.revoke(am);
+            uriPerms = null;
         }
     }
 
@@ -354,57 +400,6 @@
         return prepared;
     }
 
-    private final void grantUriLocked(IActivityManager am, Uri uri, int sourceUid,
-            String targetPackage, int targetUserId) {
-        try {
-            int sourceUserId = ContentProvider.getUserIdFromUri(uri,
-                    UserHandle.getUserId(sourceUid));
-            uri = ContentProvider.getUriWithoutUserId(uri);
-            if (permissionOwner == null) {
-                permissionOwner = am.newUriPermissionOwner("job: " + toShortString());
-            }
-            am.grantUriPermissionFromOwner(permissionOwner, sourceUid, targetPackage,
-                    uri, job.getClipGrantFlags(), sourceUserId, targetUserId);
-        } catch (RemoteException e) {
-            Slog.e("JobScheduler", "AM dead");
-        }
-    }
-
-    private final void grantItemLocked(IActivityManager am, ClipData.Item item, int sourceUid,
-            String targetPackage, int targetUserId) {
-        if (item.getUri() != null) {
-            grantUriLocked(am, item.getUri(), sourceUid, targetPackage, targetUserId);
-        }
-        Intent intent = item.getIntent();
-        if (intent != null && intent.getData() != null) {
-            grantUriLocked(am, intent.getData(), sourceUid, targetPackage, targetUserId);
-        }
-    }
-
-    private final void revokeUriLocked(IActivityManager am, Uri uri) {
-        int userId = ContentProvider.getUserIdFromUri(uri,
-                UserHandle.getUserId(Binder.getCallingUid()));
-        long ident = Binder.clearCallingIdentity();
-        try {
-            uri = ContentProvider.getUriWithoutUserId(uri);
-            am.revokeUriPermissionFromOwner(permissionOwner, uri,
-                    job.getClipGrantFlags(), userId);
-        } catch (RemoteException e) {
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    private final void revokeItemLocked(IActivityManager am, ClipData.Item item) {
-        if (item.getUri() != null) {
-            revokeUriLocked(am, item.getUri());
-        }
-        Intent intent = item.getIntent();
-        if (intent != null && intent.getData() != null) {
-            revokeUriLocked(am, intent.getData());
-        }
-    }
-
     public JobInfo getJob() {
         return job;
     }
@@ -467,15 +462,24 @@
         return job.getFlags();
     }
 
+    /** Does this job have any sort of networking constraint? */
     public boolean hasConnectivityConstraint() {
+        return (requiredConstraints&CONNECTIVITY_MASK) != 0;
+    }
+
+    public boolean needsAnyConnectivity() {
         return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0;
     }
 
-    public boolean hasUnmeteredConstraint() {
+    public boolean needsUnmeteredConnectivity() {
         return (requiredConstraints&CONSTRAINT_UNMETERED) != 0;
     }
 
-    public boolean hasNotRoamingConstraint() {
+    public boolean needsMeteredConnectivity() {
+        return (requiredConstraints&CONSTRAINT_METERED) != 0;
+    }
+
+    public boolean needsNonRoamingConnectivity() {
         return (requiredConstraints&CONSTRAINT_NOT_ROAMING) != 0;
     }
 
@@ -571,6 +575,10 @@
         return setConstraintSatisfied(CONSTRAINT_UNMETERED, state);
     }
 
+    boolean setMeteredConstraintSatisfied(boolean state) {
+        return setConstraintSatisfied(CONSTRAINT_METERED, state);
+    }
+
     boolean setNotRoamingConstraintSatisfied(boolean state) {
         return setConstraintSatisfied(CONSTRAINT_NOT_ROAMING, state);
     }
@@ -802,6 +810,15 @@
         }
     }
 
+    private void dumpJobWorkItem(PrintWriter pw, String prefix, JobWorkItem work, int index) {
+        pw.print(prefix); pw.print("  #"); pw.print(index); pw.print(": #");
+        pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent());
+        if (work.getGrants() != null) {
+            pw.print(prefix); pw.println("  URI grants:");
+            ((GrantedUriPermissions)work.getGrants()).dump(pw, prefix + "    ");
+        }
+    }
+
     // Dumpsys infrastructure
     public void dump(PrintWriter pw, String prefix, boolean full) {
         pw.print(prefix); UserHandle.formatUid(pw, callingUid);
@@ -867,6 +884,10 @@
                 job.getClipData().toShortString(b);
                 pw.println(b);
             }
+            if (uriPerms != null) {
+                pw.print(prefix); pw.println("  Granted URI permissions:");
+                uriPerms.dump(pw, prefix + "  ");
+            }
             if (job.getNetworkType() != JobInfo.NETWORK_TYPE_NONE) {
                 pw.print(prefix); pw.print("  Network type: "); pw.println(job.getNetworkType());
             }
@@ -919,17 +940,13 @@
         if (pendingWork != null && pendingWork.size() > 0) {
             pw.print(prefix); pw.println("Pending work:");
             for (int i = 0; i < pendingWork.size(); i++) {
-                JobWorkItem work = pendingWork.get(i);
-                pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": #");
-                pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent());
+                dumpJobWorkItem(pw, prefix, pendingWork.get(i), i);
             }
         }
         if (executingWork != null && executingWork.size() > 0) {
             pw.print(prefix); pw.println("Executing work:");
             for (int i = 0; i < executingWork.size(); i++) {
-                JobWorkItem work = executingWork.get(i);
-                pw.print(prefix); pw.print("  #"); pw.print(i); pw.print(": #");
-                pw.print(work.getWorkId()); pw.print(" "); pw.println(work.getIntent());
+                dumpJobWorkItem(pw, prefix, executingWork.get(i), i);
             }
         }
         pw.print(prefix); pw.print("Earliest run time: ");
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 8fe021c..2704c44 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -290,6 +290,9 @@
     // current setting - 4 hours
     private static final long MAX_RETRY_INTERVAL = 4*60*60*1000;
 
+    // Timeout when holding wakelocks for downloading XTRA data.
+    private static final long DOWNLOAD_XTRA_DATA_TIMEOUT_MS = 60 * 1000;
+
     private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
     private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
 
@@ -992,7 +995,7 @@
         mDownloadXtraDataPending = STATE_DOWNLOADING;
 
         // hold wake lock while task runs
-        mWakeLock.acquire();
+        mWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
         Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
         AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
             @Override
@@ -1015,7 +1018,11 @@
                 }
 
                 // release wake lock held by task
-                mWakeLock.release();
+                if (mWakeLock.isHeld()) {
+                    mWakeLock.release();
+                } else {
+                    Log.e(TAG, "WakeLock expired before release in handleDownloadXtraData()");
+                }
                 Log.i(TAG, "WakeLock released by handleDownloadXtraData()");
             }
         });
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 53a8092..ee348cf 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -101,8 +101,6 @@
     private ParceledListSlice mQueue;
     private CharSequence mQueueTitle;
     private int mRatingType;
-    private int mRepeatMode;
-    private boolean mShuffleModeEnabled;
     // End TransportPerformer fields
 
     // Volume handling fields
@@ -622,47 +620,6 @@
         }
     }
 
-    private void pushRepeatModeUpdate() {
-        synchronized (mLock) {
-            if (mDestroyed) {
-                return;
-            }
-            for (int i = mControllerCallbackHolders.size() - 1; i >= 0; i--) {
-                ISessionControllerCallbackHolder holder = mControllerCallbackHolders.get(i);
-                try {
-                    holder.mCallback.onRepeatModeChanged(mRepeatMode);
-                } catch (DeadObjectException e) {
-                    mControllerCallbackHolders.remove(i);
-                    logCallbackException("Removed dead callback in pushRepeatModeUpdate",
-                            holder, e);
-                } catch (RemoteException e) {
-                    logCallbackException("unexpected exception in pushRepeatModeUpdate", holder, e);
-                }
-            }
-        }
-    }
-
-    private void pushShuffleModeUpdate() {
-        synchronized (mLock) {
-            if (mDestroyed) {
-                return;
-            }
-            for (int i = mControllerCallbackHolders.size() - 1; i >= 0; i--) {
-                ISessionControllerCallbackHolder holder = mControllerCallbackHolders.get(i);
-                try {
-                    holder.mCallback.onShuffleModeChanged(mShuffleModeEnabled);
-                } catch (DeadObjectException e) {
-                    mControllerCallbackHolders.remove(i);
-                    logCallbackException("Removed dead callback in pushShuffleModeUpdate",
-                            holder, e);
-                } catch (RemoteException e) {
-                    logCallbackException("unexpected exception in pushShuffleModeUpdate",
-                            holder, e);
-                }
-            }
-        }
-    }
-
     private void pushSessionDestroyed() {
         synchronized (mLock) {
             // This is the only method that may be (and can only be) called
@@ -887,30 +844,6 @@
         }
 
         @Override
-        public void setRepeatMode(int repeatMode) {
-            boolean changed;
-            synchronized (mLock) {
-                changed = mRepeatMode != repeatMode;
-                mRepeatMode = repeatMode;
-            }
-            if (changed) {
-                mHandler.post(MessageHandler.MSG_UPDATE_REPEAT_MODE);
-            }
-        }
-
-        @Override
-        public void setShuffleModeEnabled(boolean enabled) {
-            boolean changed;
-            synchronized (mLock) {
-                changed = mShuffleModeEnabled != enabled;
-                mShuffleModeEnabled = enabled;
-            }
-            if (changed) {
-                mHandler.post(MessageHandler.MSG_UPDATE_SHUFFLE_MODE);
-            }
-        }
-
-        @Override
         public void setCurrentVolume(int volume) {
             mCurrentVolume = volume;
             mHandler.post(MessageHandler.MSG_UPDATE_VOLUME);
@@ -1126,54 +1059,6 @@
             }
         }
 
-        public void repeatMode(int repeatMode) {
-            try {
-                mCb.onRepeatMode(repeatMode);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote failure in repeatMode.", e);
-            }
-        }
-
-        public void shuffleMode(boolean enabled) {
-            try {
-                mCb.onShuffleMode(enabled);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote failure in shuffleMode.", e);
-            }
-        }
-
-        public void addQueueItem(MediaDescription description) {
-            try {
-                mCb.onAddQueueItem(description);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote failure in addQueueItem.", e);
-            }
-        }
-
-        public void addQueueItemAt(MediaDescription description, int index) {
-            try {
-                mCb.onAddQueueItemAt(description, index);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote failure in addQueueItemAt.", e);
-            }
-        }
-
-        public void removeQueueItem(MediaDescription description) {
-            try {
-                mCb.onRemoveQueueItem(description);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote failure in removeQueueItem.", e);
-            }
-        }
-
-        public void removeQueueItemAt(int index) {
-            try {
-                mCb.onRemoveQueueItemAt(index);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Remote failure in removeQueueItem.", e);
-            }
-        }
-
         public void adjustVolume(int direction) {
             try {
                 mCb.onAdjustVolume(direction);
@@ -1410,25 +1295,13 @@
         }
 
         @Override
-        public void repeatMode(int repeatMode) {
-            updateCallingPackage();
-            mSessionCb.repeatMode(repeatMode);
-        }
-
-        @Override
-        public void shuffleMode(boolean enabled) throws RemoteException {
-            updateCallingPackage();
-            mSessionCb.shuffleMode(enabled);
-        }
-
-
-        @Override
         public void sendCustomAction(String action, Bundle args)
                 throws RemoteException {
             updateCallingPackage();
             mSessionCb.sendCustomAction(action, args);
         }
 
+
         @Override
         public MediaMetadata getMetadata() {
             synchronized (mLock) {
@@ -1449,30 +1322,6 @@
         }
 
         @Override
-        public void addQueueItem(MediaDescription description) {
-            updateCallingPackage();
-            mSessionCb.addQueueItem(description);
-        }
-
-        @Override
-        public void addQueueItemAt(MediaDescription description, int index) {
-            updateCallingPackage();
-            mSessionCb.addQueueItemAt(description, index);
-        }
-
-        @Override
-        public void removeQueueItem(MediaDescription description) {
-            updateCallingPackage();
-            mSessionCb.removeQueueItem(description);
-        }
-
-        @Override
-        public void removeQueueItemAt(int index) {
-            updateCallingPackage();
-            mSessionCb.removeQueueItemAt(index);
-        }
-
-        @Override
         public CharSequence getQueueTitle() {
             return mQueueTitle;
         }
@@ -1490,16 +1339,6 @@
         }
 
         @Override
-        public int getRepeatMode() {
-            return mRepeatMode;
-        }
-
-        @Override
-        public boolean isShuffleModeEnabled() {
-            return mShuffleModeEnabled;
-        }
-
-        @Override
         public boolean isTransportControlEnabled() {
             return MediaSessionRecord.this.isTransportControlEnabled();
         }
@@ -1524,9 +1363,7 @@
         private static final int MSG_SEND_EVENT = 6;
         private static final int MSG_UPDATE_SESSION_STATE = 7;
         private static final int MSG_UPDATE_VOLUME = 8;
-        private static final int MSG_UPDATE_REPEAT_MODE = 9;
-        private static final int MSG_UPDATE_SHUFFLE_MODE = 10;
-        private static final int MSG_DESTROYED = 11;
+        private static final int MSG_DESTROYED = 9;
 
         public MessageHandler(Looper looper) {
             super(looper);
@@ -1558,12 +1395,6 @@
                 case MSG_UPDATE_VOLUME:
                     pushVolumeUpdate();
                     break;
-                case MSG_UPDATE_REPEAT_MODE:
-                    pushRepeatModeUpdate();
-                    break;
-                case MSG_UPDATE_SHUFFLE_MODE:
-                    pushShuffleModeUpdate();
-                    break;
                 case MSG_DESTROYED:
                     pushSessionDestroyed();
             }
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index b0d8adc..0e69bca 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -23,6 +23,7 @@
 import android.os.UserHandle;
 import android.util.IntArray;
 import android.util.Log;
+import android.util.SparseArray;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -38,7 +39,7 @@
     private static final String TAG = "MediaSessionStack";
 
     /**
-     * Listens the change in the media button session.
+     * Listen the change in the media button session.
      */
     interface OnMediaButtonSessionChangedListener {
         /**
@@ -85,7 +86,12 @@
 
     private MediaSessionRecord mCachedDefault;
     private MediaSessionRecord mCachedVolumeDefault;
-    private ArrayList<MediaSessionRecord> mCachedActiveList;
+
+    /**
+     * Cache the result of the {@link #getActiveSessions} per user.
+     */
+    private final SparseArray<ArrayList<MediaSessionRecord>> mCachedActiveLists =
+            new SparseArray<>();
 
     MediaSessionStack(AudioPlaybackMonitor monitor, OnMediaButtonSessionChangedListener listener) {
         mAudioPlaybackMonitor = monitor;
@@ -99,7 +105,7 @@
      */
     public void addSession(MediaSessionRecord record) {
         mSessions.add(record);
-        clearCache();
+        clearCache(record.getUserId());
 
         // Update the media button session.
         // The added session could be the session from the package with the audio playback.
@@ -115,11 +121,14 @@
     public void removeSession(MediaSessionRecord record) {
         mSessions.remove(record);
         if (mMediaButtonSession == record) {
-            // When the media button session is gone, try to find the alternative media session
-            // in the media button session app.
-            onMediaSessionChangeInMediaButtonSessionApp();
+            // When the media button session is removed, nullify the media button session and do not
+            // search for the alternative media session within the app. It's because the alternative
+            // media session might be a dummy which isn't able to handle the media key events.
+            mOnMediaButtonSessionChangedListener.onMediaButtonSessionChanged(
+                    mMediaButtonSession, null);
+            mMediaButtonSession = null;
         }
-        clearCache();
+        clearCache(record.getUserId());
     }
 
     /**
@@ -140,7 +149,7 @@
         if (shouldUpdatePriority(oldState, newState)) {
             mSessions.remove(record);
             mSessions.add(0, record);
-            clearCache();
+            clearCache(record.getUserId());
         } else if (!MediaSession.isActiveState(newState)) {
             // Just clear the volume cache when a state goes inactive
             mCachedVolumeDefault = null;
@@ -151,7 +160,13 @@
         // In that case, we pick the media session whose PlaybackState matches
         // the audio playback configuration.
         if (mMediaButtonSession != null && mMediaButtonSession.getUid() == record.getUid()) {
-            onMediaSessionChangeInMediaButtonSessionApp();
+            MediaSessionRecord newMediaButtonSession =
+                    findMediaButtonSession(mMediaButtonSession.getUid());
+            if (newMediaButtonSession != mMediaButtonSession) {
+                mOnMediaButtonSessionChangedListener.onMediaButtonSessionChanged(
+                        mMediaButtonSession, newMediaButtonSession);
+                mMediaButtonSession = newMediaButtonSession;
+            }
         }
     }
 
@@ -163,7 +178,7 @@
     public void onSessionStateChange(MediaSessionRecord record) {
         // For now just clear the cache. Eventually we'll selectively clear
         // depending on what changed.
-        clearCache();
+        clearCache(record.getUserId());
     }
 
     /**
@@ -194,22 +209,6 @@
     }
 
     /**
-     * Handle the change in a media session in the media button session app.
-     * <p>If the app has multiple media sessions, change in a media sesion in the app may change
-     * the media button session.
-     * @see #findMediaButtonSession
-     */
-    private void onMediaSessionChangeInMediaButtonSessionApp() {
-        MediaSessionRecord newMediaButtonSession =
-                findMediaButtonSession(mMediaButtonSession.getUid());
-        if (newMediaButtonSession != mMediaButtonSession) {
-            mOnMediaButtonSessionChangedListener.onMediaButtonSessionChanged(mMediaButtonSession,
-                    newMediaButtonSession);
-            mMediaButtonSession = newMediaButtonSession;
-        }
-    }
-
-    /**
      * Find the media button session with the given {@param uid}.
      * If the app has multiple media sessions, the media session matches the audio playback state
      * becomes the media button session.
@@ -245,14 +244,17 @@
      * Get the current priority sorted list of active sessions. The most
      * important session is at index 0 and the least important at size - 1.
      *
-     * @param userId The user to check.
+     * @param userId The user to check. It can be {@link UserHandle#USER_ALL} to get all sessions
+     *    for all users in this {@link MediaSessionStack}.
      * @return All the active sessions in priority order.
      */
     public ArrayList<MediaSessionRecord> getActiveSessions(int userId) {
-        if (mCachedActiveList == null) {
-            mCachedActiveList = getPriorityList(true, userId);
+        ArrayList<MediaSessionRecord> cachedActiveList = mCachedActiveLists.get(userId);
+        if (cachedActiveList == null) {
+            cachedActiveList = getPriorityList(true, userId);
+            mCachedActiveLists.put(userId, cachedActiveList);
         }
-        return mCachedActiveList;
+        return cachedActiveList;
     }
 
     /**
@@ -382,9 +384,12 @@
         return false;
     }
 
-    private void clearCache() {
+    private void clearCache(int userId) {
         mCachedDefault = null;
         mCachedVolumeDefault = null;
-        mCachedActiveList = null;
+        mCachedActiveLists.remove(userId);
+        // mCachedActiveLists may also include the list of sessions for UserHandle.USER_ALL,
+        // so they also need to be cleared.
+        mCachedActiveLists.remove(UserHandle.USER_ALL);
     }
 }
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 2fab288..c28fb67 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -251,7 +251,7 @@
 
     public IConditionProvider findConditionProvider(ComponentName component) {
         if (component == null) return null;
-        for (ManagedServiceInfo service : mServices) {
+        for (ManagedServiceInfo service : getServices()) {
             if (component.equals(service.component)) {
                 return provider(service);
             }
diff --git a/services/core/java/com/android/server/notification/GlobalSortKeyComparator.java b/services/core/java/com/android/server/notification/GlobalSortKeyComparator.java
index ce976d2..acedafc 100644
--- a/services/core/java/com/android/server/notification/GlobalSortKeyComparator.java
+++ b/services/core/java/com/android/server/notification/GlobalSortKeyComparator.java
@@ -15,19 +15,25 @@
  */
 package com.android.server.notification;
 
+import android.util.Slog;
+
 import java.util.Comparator;
 
 /**
  * Sorts notifications by their global sort key.
  */
 public class GlobalSortKeyComparator implements Comparator<NotificationRecord> {
+    private final static String TAG = "GlobalSortComp";
+
     @Override
     public int compare(NotificationRecord left, NotificationRecord right) {
         if (left.getGlobalSortKey() == null) {
-            throw new IllegalStateException("Missing left global sort key: " + left);
+            Slog.wtf(TAG, "Missing left global sort key: " + left);
+            return 1;
         }
         if (right.getGlobalSortKey() == null) {
-            throw new IllegalStateException("Missing right global sort key: " + right);
+            Slog.wtf(TAG, "Missing right global sort key: " + right);
+            return  -1;
         }
         return left.getGlobalSortKey().compareTo(right.getGlobalSortKey());
     }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 182a710..b8d633f 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -93,7 +93,7 @@
 
     // contains connections to all connected services, including app services
     // and system services
-    protected final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
+    private final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
     // things that will be put into mServices as soon as they're ready
     private final ArrayList<String> mServicesBinding = new ArrayList<String>();
     // lists the component names of all enabled (and therefore potentially connected)
@@ -359,7 +359,6 @@
 
     private void rebuildRestoredPackages() {
         mRestoredPackages.clear();
-        mSnoozingForCurrentProfiles.clear();
         String secureSettingName = restoredSettingName(mConfig.secureSettingName);
         String secondarySettingName = mConfig.secondarySettingName == null
                 ? null : restoredSettingName(mConfig.secondarySettingName);
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index d6c89a4..63647ff 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -21,15 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
 import android.telecom.TelecomManager;
-import android.text.TextUtils;
-import android.util.ArrayMap;
 
 import com.android.internal.util.NotificationMessagingUtil;
 
@@ -56,8 +48,8 @@
     @Override
     public int compare(NotificationRecord left, NotificationRecord right) {
         // first all colorized notifications
-        boolean leftImportantColorized = isImportantColorized(left);
-        boolean rightImportantColorized = isImportantColorized(right);
+        boolean leftImportantColorized = isImportantOngoingColorized(left);
+        boolean rightImportantColorized = isImportantOngoingColorized(right);
 
         if (leftImportantColorized != rightImportantColorized) {
             return -1 * Boolean.compare(leftImportantColorized, rightImportantColorized);
@@ -118,7 +110,10 @@
         return -1 * Long.compare(left.getRankingTimeMs(), right.getRankingTimeMs());
     }
 
-    private boolean isImportantColorized(NotificationRecord record) {
+    private boolean isImportantOngoingColorized(NotificationRecord record) {
+        if (!isOngoing(record)) {
+            return false;
+        }
         if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
             return false;
         }
@@ -133,7 +128,6 @@
         if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
             return false;
         }
-        // TODO: add whitelist
 
         return isCall(record) || isMediaNotification(record);
     }
@@ -153,8 +147,7 @@
     }
 
     private boolean isOngoing(NotificationRecord record) {
-        final int ongoingFlags =
-                Notification.FLAG_FOREGROUND_SERVICE | Notification.FLAG_ONGOING_EVENT;
+        final int ongoingFlags = Notification.FLAG_FOREGROUND_SERVICE;
         return (record.getNotification().flags & ongoingFlags) != 0;
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d8e7e7d..e13aeaf 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -97,6 +97,7 @@
 import android.media.IRingtonePlayer;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
@@ -1322,7 +1323,8 @@
 
         if (!fromListener) {
             mListeners.notifyNotificationChannelChanged(
-                    pkg, modifiedChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+                    pkg, UserHandle.getUserHandleForUid(uid),
+                    modifiedChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
         }
 
         synchronized (mNotificationLock) {
@@ -1647,7 +1649,8 @@
                 Preconditions.checkNotNull(group, "group in list is null");
                 mRankingHelper.createNotificationChannelGroup(pkg, Binder.getCallingUid(), group,
                         true /* fromTargetApp */);
-                mListeners.notifyNotificationChannelGroupChanged(pkg, group,
+                mListeners.notifyNotificationChannelGroupChanged(pkg,
+                        UserHandle.of(UserHandle.getCallingUserId()), group,
                         NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
             }
             savePolicyFile();
@@ -1663,6 +1666,7 @@
                 mRankingHelper.createNotificationChannel(pkg, uid, channel,
                         true /* fromTargetApp */);
                 mListeners.notifyNotificationChannelChanged(pkg,
+                        UserHandle.getUserHandleForUid(uid),
                         mRankingHelper.getNotificationChannel(pkg, uid, channel.getId(), false),
                         NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
             }
@@ -1708,6 +1712,7 @@
                     UserHandle.getUserId(callingUid), REASON_CHANNEL_BANNED, null);
             mRankingHelper.deleteNotificationChannel(pkg, callingUid, channelId);
             mListeners.notifyNotificationChannelChanged(pkg,
+                    UserHandle.getUserHandleForUid(callingUid),
                     mRankingHelper.getNotificationChannel(pkg, callingUid, channelId, true),
                     NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
             savePolicyFile();
@@ -1737,11 +1742,14 @@
                             true,
                             UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
                             null);
-                    mListeners.notifyNotificationChannelChanged(pkg, deletedChannel,
+                    mListeners.notifyNotificationChannelChanged(pkg,
+                            UserHandle.getUserHandleForUid(callingUid),
+                            deletedChannel,
                             NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
                 }
                 mListeners.notifyNotificationChannelGroupChanged(
-                        pkg, groupToDelete, NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
+                        pkg, UserHandle.getUserHandleForUid(callingUid), groupToDelete,
+                        NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
                 savePolicyFile();
             }
         }
@@ -1866,10 +1874,9 @@
             int userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                     Binder.getCallingUid(), incomingUserId, true, false,
                     "getAppActiveNotifications", pkg);
-            final ArrayMap<String, StatusBarNotification> map
-                    = new ArrayMap<>(mNotificationList.size() + mEnqueuedNotifications.size());
-
             synchronized (mNotificationLock) {
+                final ArrayMap<String, StatusBarNotification> map
+                        = new ArrayMap<>(mNotificationList.size() + mEnqueuedNotifications.size());
                 final int N = mNotificationList.size();
                 for (int i = 0; i < N; i++) {
                     StatusBarNotification sbn = sanitizeSbn(pkg, userId,
@@ -1892,11 +1899,10 @@
                         map.put(sbn.getKey(), sbn); // pending update overwrites existing post here
                     }
                 }
+                final ArrayList<StatusBarNotification> list = new ArrayList<>(map.size());
+                list.addAll(map.values());
+                return new ParceledListSlice<StatusBarNotification>(list);
             }
-
-            final ArrayList<StatusBarNotification> list = new ArrayList<>(map.size());
-            list.addAll(map.values());
-            return new ParceledListSlice<StatusBarNotification>(list);
         }
 
         private StatusBarNotification sanitizeSbn(String pkg, int userId,
@@ -2028,8 +2034,10 @@
             long identity = Binder.clearCallingIdentity();
             try {
                 // allow bound services to disable themselves
-                final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
-                info.getOwner().setComponentState(info.component, false);
+                synchronized (mNotificationLock) {
+                    final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+                    info.getOwner().setComponentState(info.component, false);
+                }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -2093,8 +2101,10 @@
                 String key, String snoozeCriterionId) {
             long identity = Binder.clearCallingIdentity();
             try {
-                final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
-                snoozeNotificationInt(key, SNOOZE_UNTIL_UNSPECIFIED, snoozeCriterionId, info);
+                synchronized (mNotificationLock) {
+                    final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+                    snoozeNotificationInt(key, SNOOZE_UNTIL_UNSPECIFIED, snoozeCriterionId, info);
+                }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -2110,8 +2120,10 @@
                 long duration) {
             long identity = Binder.clearCallingIdentity();
             try {
-                final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
-                snoozeNotificationInt(key, duration, null, info);
+                synchronized (mNotificationLock) {
+                    final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+                    snoozeNotificationInt(key, duration, null, info);
+                }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -2126,9 +2138,11 @@
         public void unsnoozeNotificationFromAssistant(INotificationListener token, String key) {
             long identity = Binder.clearCallingIdentity();
             try {
-                final ManagedServiceInfo info =
-                        mNotificationAssistants.checkServiceTokenLocked(token);
-                unsnoozeNotificationInt(key, info);
+                synchronized (mNotificationLock) {
+                    final ManagedServiceInfo info =
+                            mNotificationAssistants.checkServiceTokenLocked(token);
+                    unsnoozeNotificationInt(key, info);
+                }
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -2691,43 +2705,62 @@
 
         @Override
         public void updateNotificationChannelFromPrivilegedListener(INotificationListener token,
-                String pkg, NotificationChannel channel) throws RemoteException {
+                String pkg, UserHandle user, NotificationChannel channel) throws RemoteException {
             Preconditions.checkNotNull(channel);
+            Preconditions.checkNotNull(pkg);
+            Preconditions.checkNotNull(user);
 
-            ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
-            if (!hasCompanionDevice(info)) {
-                throw new SecurityException(info + " does not have access");
-            }
-
-            int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
-            updateNotificationChannelInt(pkg, uid, channel, true);
+            verifyPrivilegedListener(token, user);
+            updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true);
         }
 
         @Override
         public ParceledListSlice<NotificationChannel> getNotificationChannelsFromPrivilegedListener(
-                INotificationListener token, String pkg) throws RemoteException {
-            ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
-            if (!hasCompanionDevice(info)) {
-                throw new SecurityException(info + " does not have access");
-            }
+                INotificationListener token, String pkg, UserHandle user) throws RemoteException {
+            Preconditions.checkNotNull(pkg);
+            Preconditions.checkNotNull(user);
+            verifyPrivilegedListener(token, user);
 
-            int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
-            return mRankingHelper.getNotificationChannels(pkg, uid, false /* includeDeleted */);
+            return mRankingHelper.getNotificationChannels(pkg, getUidForPackageAndUser(pkg, user),
+                    false /* includeDeleted */);
         }
 
         @Override
         public ParceledListSlice<NotificationChannelGroup>
                 getNotificationChannelGroupsFromPrivilegedListener(
-                INotificationListener token, String pkg) throws RemoteException {
-            ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
+                INotificationListener token, String pkg, UserHandle user) throws RemoteException {
+            Preconditions.checkNotNull(pkg);
+            Preconditions.checkNotNull(user);
+            verifyPrivilegedListener(token, user);
+
+            List<NotificationChannelGroup> groups = new ArrayList<>();
+            groups.addAll(mRankingHelper.getNotificationChannelGroups(
+                    pkg, getUidForPackageAndUser(pkg, user)));
+            return new ParceledListSlice<>(groups);
+        }
+
+        private void verifyPrivilegedListener(INotificationListener token, UserHandle user) {
+            ManagedServiceInfo info;
+            synchronized (mNotificationLock) {
+                info = mListeners.checkServiceTokenLocked(token);
+            }
             if (!hasCompanionDevice(info)) {
                 throw new SecurityException(info + " does not have access");
             }
+            if (!info.enabledAndUserMatches(user.getIdentifier())) {
+                throw new SecurityException(info + " does not have access");
+            }
+        }
 
-            List<NotificationChannelGroup> groups = new ArrayList<>();
-            int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
-            groups.addAll(mRankingHelper.getNotificationChannelGroups(pkg, uid));
-            return new ParceledListSlice<>(groups);
+        private int getUidForPackageAndUser(String pkg, UserHandle user) throws RemoteException {
+            int uid = 0;
+            long identity = Binder.clearCallingIdentity();
+            try {
+                uid = mPackageManager.getPackageUid(pkg, 0, user.getIdentifier());
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            return uid;
         }
     };
 
@@ -3071,32 +3104,36 @@
         public void removeForegroundServiceFlagFromNotification(String pkg, int notificationId,
                 int userId) {
             checkCallerIsSystem();
-            synchronized (mNotificationLock) {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        NotificationRecord r =
-                                findNotificationLocked(pkg, null, notificationId, userId);
-                        if (r == null) {
-                            Log.d(TAG,
-                                    "stripForegroundServiceFlag: Could not find notification with "
-                                    + "pkg=" + pkg + " / id=" + notificationId
-                                    + " / userId=" + userId);
-                            return;
-                        }
-                        StatusBarNotification sbn = r.sbn;
-                        // NoMan adds flags FLAG_NO_CLEAR and FLAG_ONGOING_EVENT when it sees
-                        // FLAG_FOREGROUND_SERVICE. Hence it's not enough to remove
-                        // FLAG_FOREGROUND_SERVICE, we have to revert to the flags we received
-                        // initially *and* force remove FLAG_FOREGROUND_SERVICE.
-                        sbn.getNotification().flags =
-                                (r.mOriginalFlags & ~Notification.FLAG_FOREGROUND_SERVICE);
-                        mRankingHelper.sort(mNotificationList);
-                        mListeners.notifyPostedLocked(sbn, sbn /* oldSbn */);
-                        mGroupHelper.onNotificationPosted(sbn);
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    synchronized (mNotificationLock) {
+                        removeForegroundServiceFlagByListLocked(
+                                mEnqueuedNotifications, pkg, notificationId, userId);
+                        removeForegroundServiceFlagByListLocked(
+                                mNotificationList, pkg, notificationId, userId);
                     }
-                });
+                }
+            });
+        }
+
+        private void removeForegroundServiceFlagByListLocked(
+                ArrayList<NotificationRecord> notificationList, String pkg, int notificationId, int userId) {
+            NotificationRecord r =
+                    findNotificationByListLocked(notificationList, pkg, null, notificationId, userId);
+            if (r == null) {
+                return;
             }
+            StatusBarNotification sbn = r.sbn;
+            // NoMan adds flags FLAG_NO_CLEAR and FLAG_ONGOING_EVENT when it sees
+            // FLAG_FOREGROUND_SERVICE. Hence it's not enough to remove
+            // FLAG_FOREGROUND_SERVICE, we have to revert to the flags we received
+            // initially *and* force remove FLAG_FOREGROUND_SERVICE.
+            sbn.getNotification().flags =
+                    (r.mOriginalFlags & ~Notification.FLAG_FOREGROUND_SERVICE);
+            mRankingHelper.sort(mNotificationList);
+            mListeners.notifyPostedLocked(sbn, sbn /* oldSbn */);
+            mGroupHelper.onNotificationPosted(sbn);
         }
     };
 
@@ -3160,16 +3197,16 @@
             // STOPSHIP TODO: should throw instead of logging or toasting.
             // throw new IllegalArgumentException(noChannelStr);
             Log.e(TAG, noChannelStr);
-
-            final String noChannelToastStr =
-                    "Developer warning for package \"" + pkg + "\"\n" +
+            doDebugOnlyToast("Developer warning for package \"" + pkg + "\"\n" +
                     "Failed to post notification on channel \"" + channelId + "\"\n" +
-                    "See log for more details";
-            Toast noChannelToast =
-                    Toast.makeText(getContext(), noChannelToastStr, Toast.LENGTH_LONG);
-            noChannelToast.show();
+                    "See log for more details");
             return;
+        } else if (channelId == null && shouldWarnUseChannels(pkg, notificationUid)) {
+            // STOPSHIP TODO: remove once default channel is removed for all apps that target O.
+            doDebugOnlyToast("Developer warning for package \"" + pkg + "\"\n" +
+                    "Posted notification should specify a channel");
         }
+
         final StatusBarNotification n = new StatusBarNotification(
                 pkg, opPkg, id, tag, notificationUid, callingPid, notification,
                 user, null, System.currentTimeMillis());
@@ -3201,6 +3238,30 @@
         idOut[0] = id;
     }
 
+    private void doDebugOnlyToast(CharSequence toastText) {
+        if (Build.IS_DEBUGGABLE) {
+            try {
+                Toast toast = Toast.makeText(getContext(), toastText, Toast.LENGTH_LONG);
+                toast.show();
+            } catch (RuntimeException e) {
+                Slog.w(TAG, "Unable to toast with text: " + toastText, e);
+            }
+        }
+    }
+
+    // STOPSHIP - Remove once RankingHelper deletes default channel for all apps targeting O.
+    private boolean shouldWarnUseChannels(String pkg, int uid) {
+        try {
+            final int userId = UserHandle.getUserId(uid);
+            final ApplicationInfo applicationInfo =
+                    mPackageManagerClient.getApplicationInfoAsUser(pkg, 0, userId);
+            return applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1;
+        } catch (NameNotFoundException e) {
+            Slog.e(TAG, e.toString());
+            return false;
+        }
+    }
+
     private int resolveNotificationUid(String opPackageName, int callingUid, int userId) {
         // The system can post notifications on behalf of any package it wants
         if (isCallerSystem() && opPackageName != null && !"android".equals(opPackageName)) {
@@ -3550,7 +3611,7 @@
         final boolean aboveThreshold =
                 record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT;
         final boolean canInterrupt = aboveThreshold && !record.isIntercepted();
-        if (DBG || record.isIntercepted())
+        if (DBG)
             Slog.v(TAG,
                     "pkg=" + record.sbn.getPackageName() + " canInterrupt=" + canInterrupt +
                             " intercept=" + record.isIntercepted()
@@ -4781,7 +4842,7 @@
 
             // There should be only one, but it's a list, so while we enforce
             // singularity elsewhere, we keep it general here, to avoid surprises.
-            for (final ManagedServiceInfo info : NotificationAssistants.this.mServices) {
+            for (final ManagedServiceInfo info : NotificationAssistants.this.getServices()) {
                 boolean sbnVisible = isVisibleToListener(sbn, info);
                 if (!sbnVisible) {
                     continue;
@@ -4817,7 +4878,7 @@
         public void notifyAssistantSnoozedLocked(final StatusBarNotification sbn,
                 final String snoozeCriterionId) {
             TrimCache trimCache = new TrimCache(sbn);
-            for (final ManagedServiceInfo info : mServices) {
+            for (final ManagedServiceInfo info : getServices()) {
                 final StatusBarNotification sbnToPost =  trimCache.ForListener(info);
                 mHandler.post(new Runnable() {
                     @Override
@@ -4838,7 +4899,7 @@
         }
 
         public boolean isEnabled() {
-            return !mServices.isEmpty();
+            return !getServices().isEmpty();
         }
     }
 
@@ -4918,7 +4979,7 @@
             // Lazily initialized snapshots of the notification.
             TrimCache trimCache = new TrimCache(sbn);
 
-            for (final ManagedServiceInfo info : mServices) {
+            for (final ManagedServiceInfo info : getServices()) {
                 boolean sbnVisible = isVisibleToListener(sbn, info);
                 boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info) : false;
                 // This notification hasn't been and still isn't visible -> ignore.
@@ -4957,7 +5018,7 @@
             // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
             // notification
             final StatusBarNotification sbnLight = sbn.cloneLight();
-            for (final ManagedServiceInfo info : mServices) {
+            for (final ManagedServiceInfo info : getServices()) {
                 if (!isVisibleToListener(sbn, info)) {
                     continue;
                 }
@@ -4975,7 +5036,7 @@
          * asynchronously notify all listeners about a reordering of notifications
          */
         public void notifyRankingUpdateLocked() {
-            for (final ManagedServiceInfo serviceInfo : mServices) {
+            for (final ManagedServiceInfo serviceInfo : getServices()) {
                 if (!serviceInfo.isEnabledForCurrentProfiles()) {
                     continue;
                 }
@@ -4990,7 +5051,7 @@
         }
 
         public void notifyListenerHintsChangedLocked(final int hints) {
-            for (final ManagedServiceInfo serviceInfo : mServices) {
+            for (final ManagedServiceInfo serviceInfo : getServices()) {
                 if (!serviceInfo.isEnabledForCurrentProfiles()) {
                     continue;
                 }
@@ -5004,7 +5065,7 @@
         }
 
         public void notifyInterruptionFilterChanged(final int interruptionFilter) {
-            for (final ManagedServiceInfo serviceInfo : mServices) {
+            for (final ManagedServiceInfo serviceInfo : getServices()) {
                 if (!serviceInfo.isEnabledForCurrentProfiles()) {
                     continue;
                 }
@@ -5017,7 +5078,7 @@
             }
         }
 
-        protected void notifyNotificationChannelChanged(final String pkg,
+        protected void notifyNotificationChannelChanged(final String pkg, final UserHandle user,
                 final NotificationChannel channel, final int modificationType) {
             if (channel == null) {
                 return;
@@ -5032,15 +5093,16 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        notifyNotificationChannelChanged(serviceInfo, pkg, channel,
-                                modificationType);
+                        notifyNotificationChannelChanged(
+                                serviceInfo, pkg, user, channel, modificationType);
                     }
                 });
             }
         }
 
-        protected void notifyNotificationChannelGroupChanged(final String pkg,
-                final NotificationChannelGroup group, final int modificationType) {
+        protected void notifyNotificationChannelGroupChanged(
+                final String pkg, final UserHandle user, final NotificationChannelGroup group,
+                final int modificationType) {
             if (group == null) {
                 return;
             }
@@ -5054,8 +5116,8 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        notifyNotificationChannelGroupChanged(serviceInfo, pkg, group,
-                                modificationType);
+                        notifyNotificationChannelGroupChanged(
+                                serviceInfo, pkg, user, group, modificationType);
                     }
                 });
             }
@@ -5116,22 +5178,22 @@
         }
 
         void notifyNotificationChannelChanged(ManagedServiceInfo info,
-                final String pkg, final NotificationChannel channel,
+                final String pkg, final UserHandle user, final NotificationChannel channel,
                 final int modificationType) {
             final INotificationListener listener = (INotificationListener) info.service;
             try {
-                listener.onNotificationChannelModification(pkg, channel, modificationType);
+                listener.onNotificationChannelModification(pkg, user, channel, modificationType);
             } catch (RemoteException ex) {
                 Log.e(TAG, "unable to notify listener (channel changed): " + listener, ex);
             }
         }
 
         private void notifyNotificationChannelGroupChanged(ManagedServiceInfo info,
-                final String pkg, final NotificationChannelGroup group,
+                final String pkg, final UserHandle user, final NotificationChannelGroup group,
                 final int modificationType) {
             final INotificationListener listener = (INotificationListener) info.service;
             try {
-                listener.onNotificationChannelGroupModification(pkg, group, modificationType);
+                listener.onNotificationChannelGroupModification(pkg, user, group, modificationType);
             } catch (RemoteException ex) {
                 Log.e(TAG, "unable to notify listener (channel group changed): " + listener, ex);
             }
@@ -5143,7 +5205,7 @@
             }
             // TODO: clean up locking object later
             synchronized (mNotificationLock) {
-                for (final ManagedServiceInfo serviceInfo : mServices) {
+                for (final ManagedServiceInfo serviceInfo : getServices()) {
                     if (packageName.equals(serviceInfo.component.getPackageName())) {
                         return true;
                     }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index b043230..b48fd5c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -172,7 +172,7 @@
             final boolean useDefaultSound = (n.defaults & Notification.DEFAULT_SOUND) != 0;
             if (useDefaultSound) {
                 sound = Settings.System.DEFAULT_NOTIFICATION_URI;
-            } else if (n.sound != null) {
+            } else {
                 sound = n.sound;
             }
         }
@@ -376,7 +376,20 @@
         pw.println(prefix + "fullscreenIntent=" + notification.fullScreenIntent);
         pw.println(prefix + "contentIntent=" + notification.contentIntent);
         pw.println(prefix + "deleteIntent=" + notification.deleteIntent);
-        pw.println(prefix + "tickerText=" + notification.tickerText);
+
+        pw.print(prefix + "tickerText=");
+        if (!TextUtils.isEmpty(notification.tickerText)) {
+            final String ticker = notification.tickerText.toString();
+            if (redact) {
+                // if the string is long enough, we allow ourselves a few bytes for debugging
+                pw.print(ticker.length() > 16 ? ticker.substring(0,8) : "");
+                pw.println("...");
+            } else {
+                pw.println(ticker);
+            }
+        } else {
+            pw.println("null");
+        }
         pw.println(prefix + "contentView=" + notification.contentView);
         pw.println(prefix + String.format("color=0x%08x", notification.color));
         pw.println(prefix + "timeout=" + TimeUtils.formatForLogging(notification.getTimeout()));
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 9e12f91..221b2bb 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -232,7 +232,9 @@
 
     private Record getRecord(String pkg, int uid) {
         final String key = recordKey(pkg, uid);
-        return mRecords.get(key);
+        synchronized (mRecords) {
+            return mRecords.get(key);
+        }
     }
 
     private Record getOrCreateRecord(String pkg, int uid) {
@@ -243,29 +245,32 @@
     private Record getOrCreateRecord(String pkg, int uid, int importance, int priority,
             int visibility, boolean showBadge) {
         final String key = recordKey(pkg, uid);
-        Record r = (uid == Record.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg) : mRecords.get(key);
-        if (r == null) {
-            r = new Record();
-            r.pkg = pkg;
-            r.uid = uid;
-            r.importance = importance;
-            r.priority = priority;
-            r.visibility = visibility;
-            r.showBadge = showBadge;
+        synchronized (mRecords) {
+            Record r = (uid == Record.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg) : mRecords.get(
+                    key);
+            if (r == null) {
+                r = new Record();
+                r.pkg = pkg;
+                r.uid = uid;
+                r.importance = importance;
+                r.priority = priority;
+                r.visibility = visibility;
+                r.showBadge = showBadge;
 
-            try {
-                createDefaultChannelIfNeeded(r);
-            } catch (NameNotFoundException e) {
-                Slog.e(TAG, "createDefaultChannelIfNeeded - Exception: " + e);
-            }
+                try {
+                    createDefaultChannelIfNeeded(r);
+                } catch (NameNotFoundException e) {
+                    Slog.e(TAG, "createDefaultChannelIfNeeded - Exception: " + e);
+                }
 
-            if (r.uid == Record.UNKNOWN_UID) {
-                mRestoredWithoutUids.put(pkg, r);
-            } else {
-                mRecords.put(key, r);
+                if (r.uid == Record.UNKNOWN_UID) {
+                    mRestoredWithoutUids.put(pkg, r);
+                } else {
+                    mRecords.put(key, r);
+                }
             }
+            return r;
         }
-        return r;
     }
 
     private boolean shouldHaveDefaultChannel(Record r) throws NameNotFoundException {
@@ -346,46 +351,48 @@
         out.startTag(null, TAG_RANKING);
         out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
 
-        final int N = mRecords.size();
-        for (int i = 0; i < N; i++) {
-            final Record r = mRecords.valueAt(i);
-            //TODO: http://b/22388012
-            if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
-                continue;
-            }
-            final boolean hasNonDefaultSettings = r.importance != DEFAULT_IMPORTANCE
-                    || r.priority != DEFAULT_PRIORITY || r.visibility != DEFAULT_VISIBILITY
-                    || r.showBadge != DEFAULT_SHOW_BADGE || r.channels.size() > 0
-                    || r.groups.size() > 0;
-            if (hasNonDefaultSettings) {
-                out.startTag(null, TAG_PACKAGE);
-                out.attribute(null, ATT_NAME, r.pkg);
-                if (r.importance != DEFAULT_IMPORTANCE) {
-                    out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
+        synchronized (mRecords) {
+            final int N = mRecords.size();
+            for (int i = 0; i < N; i++) {
+                final Record r = mRecords.valueAt(i);
+                //TODO: http://b/22388012
+                if (forBackup && UserHandle.getUserId(r.uid) != UserHandle.USER_SYSTEM) {
+                    continue;
                 }
-                if (r.priority != DEFAULT_PRIORITY) {
-                    out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority));
-                }
-                if (r.visibility != DEFAULT_VISIBILITY) {
-                    out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility));
-                }
-                out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge));
-
-                if (!forBackup) {
-                    out.attribute(null, ATT_UID, Integer.toString(r.uid));
-                }
-
-                for (NotificationChannelGroup group : r.groups.values()) {
-                    group.writeXml(out);
-                }
-
-                for (NotificationChannel channel : r.channels.values()) {
-                    if (!forBackup || (forBackup && !channel.isDeleted())) {
-                        channel.writeXml(out);
+                final boolean hasNonDefaultSettings = r.importance != DEFAULT_IMPORTANCE
+                        || r.priority != DEFAULT_PRIORITY || r.visibility != DEFAULT_VISIBILITY
+                        || r.showBadge != DEFAULT_SHOW_BADGE || r.channels.size() > 0
+                        || r.groups.size() > 0;
+                if (hasNonDefaultSettings) {
+                    out.startTag(null, TAG_PACKAGE);
+                    out.attribute(null, ATT_NAME, r.pkg);
+                    if (r.importance != DEFAULT_IMPORTANCE) {
+                        out.attribute(null, ATT_IMPORTANCE, Integer.toString(r.importance));
                     }
-                }
+                    if (r.priority != DEFAULT_PRIORITY) {
+                        out.attribute(null, ATT_PRIORITY, Integer.toString(r.priority));
+                    }
+                    if (r.visibility != DEFAULT_VISIBILITY) {
+                        out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility));
+                    }
+                    out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge));
 
-                out.endTag(null, TAG_PACKAGE);
+                    if (!forBackup) {
+                        out.attribute(null, ATT_UID, Integer.toString(r.uid));
+                    }
+
+                    for (NotificationChannelGroup group : r.groups.values()) {
+                        group.writeXml(out);
+                    }
+
+                    for (NotificationChannel channel : r.channels.values()) {
+                        if (!forBackup || (forBackup && !channel.isDeleted())) {
+                            channel.writeXml(out);
+                        }
+                    }
+
+                    out.endTag(null, TAG_PACKAGE);
+                }
             }
         }
         out.endTag(null, TAG_RANKING);
@@ -570,10 +577,6 @@
         if (!r.showBadge) {
             channel.setShowBadge(false);
         }
-        if (channel.getSound() == null) {
-            channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
-                    Notification.AUDIO_ATTRIBUTES_DEFAULT);
-        }
         r.channels.put(channel.getId(), channel);
         MetricsLogger.action(getChannelLog(channel, pkg).setType(
                 MetricsProto.MetricsEvent.TYPE_OPEN));
@@ -818,7 +821,9 @@
             pw.println("per-package config:");
         }
         pw.println("Records:");
-        dumpRecords(pw, prefix, filter, mRecords);
+        synchronized (mRecords) {
+            dumpRecords(pw, prefix, filter, mRecords);
+        }
         pw.println("Restored without uid:");
         dumpRecords(pw, prefix, filter, mRestoredWithoutUids);
     }
@@ -874,36 +879,38 @@
         } catch (JSONException e) {
            // pass
         }
-        final int N = mRecords.size();
-        for (int i = 0; i < N; i++) {
-            final Record r = mRecords.valueAt(i);
-            if (filter == null || filter.matches(r.pkg)) {
-                JSONObject record = new JSONObject();
-                try {
-                    record.put("userId", UserHandle.getUserId(r.uid));
-                    record.put("packageName", r.pkg);
-                    if (r.importance != DEFAULT_IMPORTANCE) {
-                        record.put("importance", Ranking.importanceToString(r.importance));
+        synchronized (mRecords) {
+            final int N = mRecords.size();
+            for (int i = 0; i < N; i++) {
+                final Record r = mRecords.valueAt(i);
+                if (filter == null || filter.matches(r.pkg)) {
+                    JSONObject record = new JSONObject();
+                    try {
+                        record.put("userId", UserHandle.getUserId(r.uid));
+                        record.put("packageName", r.pkg);
+                        if (r.importance != DEFAULT_IMPORTANCE) {
+                            record.put("importance", Ranking.importanceToString(r.importance));
+                        }
+                        if (r.priority != DEFAULT_PRIORITY) {
+                            record.put("priority", Notification.priorityToString(r.priority));
+                        }
+                        if (r.visibility != DEFAULT_VISIBILITY) {
+                            record.put("visibility", Notification.visibilityToString(r.visibility));
+                        }
+                        if (r.showBadge != DEFAULT_SHOW_BADGE) {
+                            record.put("showBadge", Boolean.valueOf(r.showBadge));
+                        }
+                        for (NotificationChannel channel : r.channels.values()) {
+                            record.put("channel", channel.toJson());
+                        }
+                        for (NotificationChannelGroup group : r.groups.values()) {
+                            record.put("group", group.toJson());
+                        }
+                    } catch (JSONException e) {
+                        // pass
                     }
-                    if (r.priority != DEFAULT_PRIORITY) {
-                        record.put("priority", Notification.priorityToString(r.priority));
-                    }
-                    if (r.visibility != DEFAULT_VISIBILITY) {
-                        record.put("visibility", Notification.visibilityToString(r.visibility));
-                    }
-                    if (r.showBadge != DEFAULT_SHOW_BADGE) {
-                        record.put("showBadge", Boolean.valueOf(r.showBadge));
-                    }
-                    for (NotificationChannel channel : r.channels.values()) {
-                        record.put("channel", channel.toJson());
-                    }
-                    for (NotificationChannelGroup group : r.groups.values()) {
-                        record.put("group", group.toJson());
-                    }
-                } catch (JSONException e) {
-                   // pass
+                    records.put(record);
                 }
-                records.put(record);
             }
         }
         try {
@@ -944,15 +951,18 @@
     }
 
     public Map<Integer, String> getPackageBans() {
-        final int N = mRecords.size();
-        ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
-        for (int i = 0; i < N; i++) {
-            final Record r = mRecords.valueAt(i);
-            if (r.importance == NotificationManager.IMPORTANCE_NONE) {
-                packageBans.put(r.uid, r.pkg);
+        synchronized (mRecords) {
+            final int N = mRecords.size();
+            ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
+            for (int i = 0; i < N; i++) {
+                final Record r = mRecords.valueAt(i);
+                if (r.importance == NotificationManager.IMPORTANCE_NONE) {
+                    packageBans.put(r.uid, r.pkg);
+                }
             }
+
+            return packageBans;
         }
-        return packageBans;
     }
 
     /**
@@ -985,15 +995,17 @@
 
     private Map<String, Integer> getPackageChannels() {
         ArrayMap<String, Integer> packageChannels = new ArrayMap<>();
-        for (int i = 0; i < mRecords.size(); i++) {
-            final Record r = mRecords.valueAt(i);
-            int channelCount = 0;
-            for (int j = 0; j < r.channels.size();j++) {
-                if (!r.channels.valueAt(j).isDeleted()) {
-                    channelCount++;
+        synchronized (mRecords) {
+            for (int i = 0; i < mRecords.size(); i++) {
+                final Record r = mRecords.valueAt(i);
+                int channelCount = 0;
+                for (int j = 0; j < r.channels.size(); j++) {
+                    if (!r.channels.valueAt(j).isDeleted()) {
+                        channelCount++;
+                    }
                 }
+                packageChannels.put(r.pkg, channelCount);
             }
-            packageChannels.put(r.pkg, channelCount);
         }
         return packageChannels;
     }
@@ -1010,7 +1022,9 @@
             for (int i = 0; i < size; i++) {
                 final String pkg = pkgList[i];
                 final int uid = uidList[i];
-                mRecords.remove(recordKey(pkg, uid));
+                synchronized (mRecords) {
+                    mRecords.remove(recordKey(pkg, uid));
+                }
                 mRestoredWithoutUids.remove(pkg);
                 updated = true;
             }
@@ -1022,7 +1036,9 @@
                     try {
                         r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
                         mRestoredWithoutUids.remove(pkg);
-                        mRecords.put(recordKey(r.pkg, r.uid), r);
+                        synchronized (mRecords) {
+                            mRecords.put(recordKey(r.pkg, r.uid), r);
+                        }
                         updated = true;
                     } catch (NameNotFoundException e) {
                         // noop
diff --git a/services/core/java/com/android/server/oemlock/OemLock.java b/services/core/java/com/android/server/oemlock/OemLock.java
new file mode 100644
index 0000000..ee70c29
--- /dev/null
+++ b/services/core/java/com/android/server/oemlock/OemLock.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.oemlock;
+
+import android.annotation.Nullable;
+
+abstract class OemLock {
+    abstract void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature);
+    abstract boolean isOemUnlockAllowedByCarrier();
+
+    abstract void setOemUnlockAllowedByDevice(boolean allowedByDevice);
+    abstract boolean isOemUnlockAllowedByDevice();
+}
diff --git a/services/core/java/com/android/server/oemlock/OemLockService.java b/services/core/java/com/android/server/oemlock/OemLockService.java
new file mode 100644
index 0000000..5e19b13
--- /dev/null
+++ b/services/core/java/com/android/server/oemlock/OemLockService.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.oemlock;
+
+import android.Manifest;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.oemlock.V1_0.IOemLock;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.UserManagerInternal;
+import android.os.UserManagerInternal.UserRestrictionsListener;
+import android.service.oemlock.IOemLockService;
+import android.util.Slog;
+
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.pm.UserRestrictionsUtils;
+
+/**
+ * Service for managing the OEM lock state of the device.
+ *
+ * The OemLock HAL will be used if it is available, otherwise the persistent data block will be
+ * used.
+ */
+public class OemLockService extends SystemService {
+    private static final String TAG = "OemLock";
+
+    private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
+    private static final String FLASH_LOCK_UNLOCKED = "0";
+
+    private Context mContext;
+    private OemLock mOemLock;
+
+    public static boolean isHalPresent() {
+        return VendorLock.getOemLockHalService() != null;
+    }
+
+    /** Select the OEM lock implementation */
+    private static OemLock getOemLock(Context context) {
+        final IOemLock oemLockHal = VendorLock.getOemLockHalService();
+        if (oemLockHal != null) {
+            Slog.i(TAG, "Using vendor lock via the HAL");
+            return new VendorLock(context, oemLockHal);
+        } else {
+            Slog.i(TAG, "Using persistent data block based lock");
+            return new PersistentDataBlockLock(context);
+        }
+    }
+
+    public OemLockService(Context context) {
+        this(context, getOemLock(context));
+    }
+
+    OemLockService(Context context, OemLock oemLock) {
+        super(context);
+        mContext = context;
+        mOemLock = oemLock;
+
+        LocalServices.getService(UserManagerInternal.class)
+                .addUserRestrictionsListener(mUserRestrictionsListener);
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.OEM_LOCK_SERVICE, mService);
+    }
+
+    private final UserRestrictionsListener mUserRestrictionsListener =
+            new UserRestrictionsListener() {
+        @Override
+        public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
+                Bundle prevRestrictions) {
+            // The admin can prevent OEM unlock with the DISALLOW_FACTORY_RESET user restriction
+            if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
+                     UserManager.DISALLOW_FACTORY_RESET)) {
+                final boolean unlockAllowedByAdmin =
+                        !newRestrictions.getBoolean(UserManager.DISALLOW_FACTORY_RESET);
+                if (!unlockAllowedByAdmin) {
+                    mOemLock.setOemUnlockAllowedByDevice(false);
+                }
+            }
+        }
+    };
+
+    /**
+     * Implements the binder interface for the service.
+     *
+     * This checks for the relevant permissions before forwarding the call to the OEM lock
+     * implementation being used on this device.
+     */
+    private final IBinder mService = new IOemLockService.Stub() {
+        @Override
+        public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+            enforceManageCarrierOemUnlockPermission();
+            enforceUserIsAdmin();
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mOemLock.setOemUnlockAllowedByCarrier(allowed, signature);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public boolean isOemUnlockAllowedByCarrier() {
+            enforceManageCarrierOemUnlockPermission();
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+              return mOemLock.isOemUnlockAllowedByCarrier();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        // The user has the final say so if they allow unlock, then the device allows the bootloader
+        // to OEM unlock it.
+        @Override
+        public void setOemUnlockAllowedByUser(boolean allowedByUser) {
+            if (ActivityManager.isUserAMonkey()) {
+                // Prevent a monkey from changing this
+                return;
+            }
+
+            enforceManageUserOemUnlockPermission();
+            enforceUserIsAdmin();
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (!canUserAllowOemUnlock()) {
+                    throw new SecurityException("User cannot allow OEM unlock");
+                }
+
+                mOemLock.setOemUnlockAllowedByDevice(allowedByUser);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public boolean isOemUnlockAllowedByUser() {
+            enforceManageUserOemUnlockPermission();
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return mOemLock.isOemUnlockAllowedByDevice();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public boolean canUserAllowOemUnlock() {
+            enforceOemUnlockReadPermission();
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return isOemUnlockAllowedByAdmin() && mOemLock.isOemUnlockAllowedByCarrier();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public boolean isOemUnlockAllowed() {
+            enforceOemUnlockReadPermission();
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return mOemLock.isOemUnlockAllowedByCarrier() &&
+                        mOemLock.isOemUnlockAllowedByDevice();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public boolean isDeviceOemUnlocked() {
+            enforceOemUnlockReadPermission();
+
+            String locked = SystemProperties.get(FLASH_LOCK_PROP);
+            switch (locked) {
+                case FLASH_LOCK_UNLOCKED:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+    };
+
+    private boolean isOemUnlockAllowedByAdmin() {
+        return !UserManager.get(mContext)
+                .hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET, UserHandle.SYSTEM);
+    }
+
+    private void enforceManageCarrierOemUnlockPermission() {
+        mContext.enforceCallingOrSelfPermission(
+                Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE,
+                "Can't manage OEM unlock allowed by carrier");
+    }
+
+    private void enforceManageUserOemUnlockPermission() {
+        mContext.enforceCallingOrSelfPermission(
+                Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE,
+                "Can't manage OEM unlock allowed by user");
+    }
+
+    private void enforceOemUnlockReadPermission() {
+        if (mContext.checkCallingOrSelfPermission(Manifest.permission.READ_OEM_UNLOCK_STATE)
+                == PackageManager.PERMISSION_DENIED
+                && mContext.checkCallingOrSelfPermission(Manifest.permission.OEM_UNLOCK_STATE)
+                == PackageManager.PERMISSION_DENIED) {
+            throw new SecurityException("Can't access OEM unlock state. Requires "
+                    + "READ_OEM_UNLOCK_STATE or OEM_UNLOCK_STATE permission.");
+        }
+    }
+
+    private void enforceUserIsAdmin() {
+        final int userId = UserHandle.getCallingUserId();
+        final long token = Binder.clearCallingIdentity();
+        try {
+            if (!UserManager.get(mContext).isUserAdmin(userId)) {
+                throw new SecurityException("Must be an admin user");
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java b/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java
new file mode 100644
index 0000000..d9362d4
--- /dev/null
+++ b/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.oemlock;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.service.persistentdata.PersistentDataBlockManager;
+import android.util.Slog;
+
+/**
+ * Implementation of the OEM lock using the persistent data block to communicate with the
+ * bootloader.
+ *
+ * The carrier flag is stored as a user restriction on the system user. The user flag is set in the
+ * presistent data block but depends on the carrier flag.
+ */
+class PersistentDataBlockLock extends OemLock {
+    private static final String TAG = "OemLock";
+
+    private Context mContext;
+
+    PersistentDataBlockLock(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+        // Note: this implementation does not require a signature
+        if (signature != null) {
+            Slog.w(TAG, "Signature provided but is not being used");
+        }
+
+        // Continue using user restriction for backwards compatibility
+        UserManager.get(mContext).setUserRestriction(
+                UserManager.DISALLOW_OEM_UNLOCK, !allowed, UserHandle.SYSTEM);
+
+        if (!allowed) {
+            disallowUnlockIfNotUnlocked();
+        }
+    }
+
+    @Override
+    boolean isOemUnlockAllowedByCarrier() {
+        return !UserManager.get(mContext)
+                .hasUserRestriction(UserManager.DISALLOW_OEM_UNLOCK, UserHandle.SYSTEM);
+    }
+
+    @Override
+    void setOemUnlockAllowedByDevice(boolean allowedByDevice) {
+        // The method name is misleading as it really just means whether or not the device can be
+        // unlocked but doesn't actually do any unlocking.
+        final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+                mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+        pdbm.setOemUnlockEnabled(allowedByDevice);
+    }
+
+    @Override
+    boolean isOemUnlockAllowedByDevice() {
+        final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+            mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+        return pdbm.getOemUnlockEnabled();
+    }
+
+    /**
+     * Update state to prevent the bootloader from being able to unlock the device unless the device
+     * has already been unlocked by the bootloader in which case it is too late as it would remain
+     * unlocked.
+     */
+    private void disallowUnlockIfNotUnlocked() {
+        final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+            mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+        if (pdbm.getFlashLockState() != PersistentDataBlockManager.FLASH_LOCK_UNLOCKED) {
+            pdbm.setOemUnlockEnabled(false);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/oemlock/VendorLock.java b/services/core/java/com/android/server/oemlock/VendorLock.java
new file mode 100644
index 0000000..1b9de36
--- /dev/null
+++ b/services/core/java/com/android/server/oemlock/VendorLock.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.oemlock;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.oemlock.V1_0.IOemLock;
+import android.hardware.oemlock.V1_0.OemLockSecureStatus;
+import android.hardware.oemlock.V1_0.OemLockStatus;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+
+/**
+ * Uses the OEM lock HAL.
+ */
+class VendorLock extends OemLock {
+    private static final String TAG = "OemLock";
+
+    private Context mContext;
+    private IOemLock mOemLock;
+
+    static IOemLock getOemLockHalService() {
+        try {
+            return IOemLock.getService();
+        } catch (NoSuchElementException e) {
+            Slog.i(TAG, "OemLock HAL not present on device");
+            return null;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    VendorLock(Context context, IOemLock oemLock) {
+        mContext = context;
+        mOemLock = oemLock;
+    }
+
+    @Override
+    void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+        try {
+            switch (mOemLock.setOemUnlockAllowedByCarrier(allowed, toByteArrayList(signature))) {
+                case OemLockSecureStatus.OK:
+                    Slog.i(TAG, "Updated carrier allows OEM lock state to: " + allowed);
+                    return;
+
+                case OemLockSecureStatus.INVALID_SIGNATURE:
+                    throw new SecurityException(
+                            "Invalid signature used in attempt to carrier unlock");
+
+                default:
+                    Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+                    // Fallthrough
+                case OemLockSecureStatus.FAILED:
+                    throw new RuntimeException("Failed to set carrier OEM unlock state");
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to set carrier state with HAL", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
+    boolean isOemUnlockAllowedByCarrier() {
+        final Integer[] requestStatus = new Integer[1];
+        final Boolean[] allowedByCarrier = new Boolean[1];
+
+        try {
+            mOemLock.isOemUnlockAllowedByCarrier((status, allowed) -> {
+                requestStatus[0] = status;
+                allowedByCarrier[0] = allowed;
+            });
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to get carrier state from HAL");
+            throw e.rethrowFromSystemServer();
+        }
+
+        switch (requestStatus[0]) {
+            case OemLockStatus.OK:
+                // Success
+                return allowedByCarrier[0];
+
+            default:
+                Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+                // Fallthrough
+            case OemLockStatus.FAILED:
+                throw new RuntimeException("Failed to get carrier OEM unlock state");
+        }
+    }
+
+    @Override
+    void setOemUnlockAllowedByDevice(boolean allowedByDevice) {
+        try {
+            switch (mOemLock.setOemUnlockAllowedByDevice(allowedByDevice)) {
+                case OemLockSecureStatus.OK:
+                    Slog.i(TAG, "Updated device allows OEM lock state to: " + allowedByDevice);
+                    return;
+
+                default:
+                    Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+                    // Fallthrough
+                case OemLockSecureStatus.FAILED:
+                    throw new RuntimeException("Failed to set device OEM unlock state");
+            }
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to set device state with HAL", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
+    boolean isOemUnlockAllowedByDevice() {
+        final Integer[] requestStatus = new Integer[1];
+        final Boolean[] allowedByDevice = new Boolean[1];
+
+        try {
+            mOemLock.isOemUnlockAllowedByDevice((status, allowed) -> {
+                requestStatus[0] = status;
+                allowedByDevice[0] = allowed;
+            });
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to get devie state from HAL");
+            throw e.rethrowFromSystemServer();
+        }
+
+        switch (requestStatus[0]) {
+            case OemLockStatus.OK:
+                // Success
+                return allowedByDevice[0];
+
+            default:
+                Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+                // Fallthrough
+            case OemLockStatus.FAILED:
+                throw new RuntimeException("Failed to get device OEM unlock state");
+        }
+    }
+
+    private ArrayList toByteArrayList(byte[] data) {
+        if (data == null) {
+            return null;
+        }
+        ArrayList<Byte> result = new ArrayList<Byte>(data.length);
+        for (final byte b : data) {
+            result.add(b);
+        }
+        return result;
+    }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 818c3ad..0e1f485 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -71,6 +71,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -754,12 +755,17 @@
                 // restarted before we received USER_REMOVED. Remove data for
                 // users that will not exist after the system is ready.
 
-                final List<UserInfo> deadUsers = getDeadUsers();
-                final int N = deadUsers.size();
-                for (int i = 0; i < N; i++) {
-                    final UserInfo deadUser = deadUsers.get(i);
-                    final int userId = deadUser.getUserHandle().getIdentifier();
-                    mSettings.removeUser(userId);
+                final List<UserInfo> liveUsers = mUserManager.getUsers(true /*excludeDying*/);
+                final int[] liveUserIds = new int[liveUsers.size()];
+                for (int i = 0; i < liveUsers.size(); i++) {
+                    liveUserIds[i] = liveUsers.get(i).getUserHandle().getIdentifier();
+                }
+                Arrays.sort(liveUserIds);
+
+                for (int userId : mSettings.getUsers()) {
+                    if (Arrays.binarySearch(liveUserIds, userId) < 0) {
+                        mSettings.removeUser(userId);
+                    }
                 }
             } catch (IOException | XmlPullParserException e) {
                 Slog.e(TAG, "failed to restore overlay state", e);
@@ -767,13 +773,6 @@
         }
     }
 
-    private List<UserInfo> getDeadUsers() {
-        final List<UserInfo> users = mUserManager.getUsers(false);
-        final List<UserInfo> onlyLiveUsers = mUserManager.getUsers(true);
-        users.removeAll(onlyLiveUsers);
-        return users;
-    }
-
     private static final class PackageManagerHelper implements
             OverlayManagerServiceImpl.PackageManagerHelper {
 
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index b203674..5196c66 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -109,6 +109,10 @@
                     if (overlayPackage.isStaticOverlay ||
                             mDefaultOverlays.contains(overlayPackage.packageName)) {
                         // Enable this overlay by default.
+                        if (DEBUG) {
+                            Slog.d(TAG, "Enabling overlay " + overlayPackage.packageName
+                                    + " for user " + newUserId + " by default");
+                        }
                         mSettings.setEnabled(overlayPackage.packageName, newUserId, true);
                     }
                 } else {
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 72979f6..2f83793 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -16,11 +16,15 @@
 
 package com.android.server.om;
 
+import static com.android.server.om.OverlayManagerService.DEBUG;
+import static com.android.server.om.OverlayManagerService.TAG;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.om.OverlayInfo;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
+import android.util.Slog;
 import android.util.Xml;
 
 import com.android.internal.util.FastXmlSerializer;
@@ -185,6 +189,10 @@
         for (int i = 0; i < mItems.size(); i++) {
             final SettingsItem item = mItems.get(i);
             if (item.getUserId() == userId) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Removing overlay " + item.mPackageName + " for user " + userId
+                            + " from settings because user was removed");
+                }
                 mItems.remove(i);
                 removed = true;
                 i--;
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 7b86542..2e4b49a 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -274,23 +274,56 @@
         // Intercept and collect dexopt requests
         final List<String> commands = new ArrayList<String>();
         final Installer collectingInstaller = new Installer(mContext, true) {
+            /**
+             * Encode the dexopt command into a string.
+             *
+             * Note: If you have to change the signature of this function, increase the version
+             *       number, and update the counterpart in
+             *       frameworks/native/cmds/installd/otapreopt.cpp.
+             */
             @Override
             public void dexopt(String apkPath, int uid, @Nullable String pkgName,
                     String instructionSet, int dexoptNeeded, @Nullable String outputPath,
                     int dexFlags, String compilerFilter, @Nullable String volumeUuid,
                     @Nullable String sharedLibraries, @Nullable String seInfo) throws InstallerException {
-                commands.add(buildCommand("dexopt",
-                        apkPath,
-                        uid,
-                        pkgName,
-                        instructionSet,
-                        dexoptNeeded,
-                        outputPath,
-                        dexFlags,
-                        compilerFilter,
-                        volumeUuid,
-                        sharedLibraries,
-                        seInfo));
+                final StringBuilder builder = new StringBuilder();
+
+                // The version. Right now it's 2.
+                builder.append("2 ");
+
+                builder.append("dexopt");
+
+                encodeParameter(builder, apkPath);
+                encodeParameter(builder, uid);
+                encodeParameter(builder, pkgName);
+                encodeParameter(builder, instructionSet);
+                encodeParameter(builder, dexoptNeeded);
+                encodeParameter(builder, outputPath);
+                encodeParameter(builder, dexFlags);
+                encodeParameter(builder, compilerFilter);
+                encodeParameter(builder, volumeUuid);
+                encodeParameter(builder, sharedLibraries);
+                encodeParameter(builder, seInfo);
+
+                commands.add(builder.toString());
+            }
+
+            /**
+             * Encode a parameter as necessary for the commands string.
+             */
+            private void encodeParameter(StringBuilder builder, Object arg) {
+                builder.append(' ');
+
+                if (arg == null) {
+                    builder.append('!');
+                }
+
+                String txt = String.valueOf(arg);
+                if (txt.indexOf('\0') != -1 || txt.indexOf(' ') != -1 || "!".equals(txt)) {
+                    throw new IllegalArgumentException(
+                            "Invalid argument while executing " + arg);
+                }
+                builder.append(txt);
             }
         };
 
@@ -430,28 +463,4 @@
             super(installer, installLock, context, "*otadexopt*");
         }
     }
-
-    /**
-     * Cook up argument list in the format that {@code installd} expects.
-     */
-    private static String buildCommand(Object... args) {
-        final StringBuilder builder = new StringBuilder();
-        for (Object arg : args) {
-            String escaped;
-            if (arg == null) {
-                escaped = "";
-            } else {
-                escaped = String.valueOf(arg);
-            }
-            if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
-                throw new IllegalArgumentException(
-                        "Invalid argument while executing " + Arrays.toString(args));
-            }
-            if (TextUtils.isEmpty(escaped)) {
-                escaped = "!";
-            }
-            builder.append(' ').append(escaped);
-        }
-        return builder.toString();
-    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 9039647..8413491 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -149,13 +149,14 @@
         final boolean profileUpdated = checkForProfileUpdates &&
                 isProfileUpdated(pkg, sharedGid, compilerFilter);
 
-        // TODO(calin,jeffhao): shared library paths should be adjusted to include previous code
-        // paths (b/34169257).
-        final String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries);
+        String sharedLibrariesPath = getSharedLibrariesPath(sharedLibraries);
         // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags.
         final int dexoptFlags = getDexFlags(pkg, compilerFilter);
 
         int result = DEX_OPT_SKIPPED;
+        // TODO: Iterate based on dependency hierarchy (currently alphabetically by name)
+        // (b/37480811).
+        String basePathCheck = null;
         for (String path : paths) {
             for (String dexCodeIsa : dexCodeInstructionSets) {
                 int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter, profileUpdated,
@@ -167,6 +168,22 @@
                 if ((result != DEX_OPT_FAILED) && (newResult != DEX_OPT_SKIPPED)) {
                     result = newResult;
                 }
+                // Add the relative path of code we just compiled to the shared libraries.
+                int slashIndex = path.lastIndexOf('/') + 1;
+                String relativePath = path.substring(slashIndex);
+                if (sharedLibrariesPath == null) {
+                    sharedLibrariesPath = relativePath;
+                } else {
+                    sharedLibrariesPath += ":" + relativePath;
+                }
+                // Sanity check that the base paths are all the same.
+                String basePath = path.substring(0, slashIndex);
+                if (basePathCheck == null) {
+                    basePathCheck = basePath;
+                } else if (!basePath.equals(basePathCheck)) {
+                    Slog.wtf(TAG, "Split paths have different base paths: " + basePath + " and " +
+                        basePathCheck);
+                }
             }
         }
         return result;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3a2b4be..8daf28b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -364,7 +364,8 @@
  * $ cts-tradefed run commandAndExit cts -m CtsAppSecurityHostTestCases
  * </pre>
  */
-public class PackageManagerService extends IPackageManager.Stub {
+public class PackageManagerService extends IPackageManager.Stub
+        implements PackageSender {
     static final String TAG = "PackageManager";
     static final boolean DEBUG_SETTINGS = false;
     static final boolean DEBUG_PREFERRED = false;
@@ -1833,6 +1834,10 @@
                 extras.putInt(Intent.EXTRA_UID, res.uid);
                 if (update) {
                     extras.putBoolean(Intent.EXTRA_REPLACING, true);
+                } else {
+                    sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_ADDED, packageName,
+                            extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
+                            null /*targetPackage*/, null /*finishedReceiver*/, updateUsers);
                 }
                 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
                         extras, 0 /*flags*/, null /*targetPackage*/,
@@ -4213,8 +4218,10 @@
                     }
 
                     SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getName(),
-                            libInfo.getVersion(), libInfo.getType(), libInfo.getDeclaringPackage(),
-                            getPackagesUsingSharedLibraryLPr(libInfo, flags, userId));
+                            // TODO: Remove cast for lib version once internally we support longs.
+                            (int) libInfo.getVersion(), libInfo.getType(),
+                            libInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr(libInfo,
+                            flags, userId));
 
                     if (result == null) {
                         result = new ArrayList<>();
@@ -7095,17 +7102,23 @@
                 // used when either 1) the service is in an instant application and the
                 // caller is not the same instant application or 2) the calling package is
                 // ephemeral and the activity is not visible to ephemeral applications.
+                final boolean matchInstantApp =
+                        (flags & PackageManager.MATCH_INSTANT) != 0;
                 final boolean matchVisibleToInstantAppOnly =
                         (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
                 final boolean isCallerInstantApp =
                         instantAppPkgName != null;
                 final boolean isTargetSameInstantApp =
                         comp.getPackageName().equals(instantAppPkgName);
+                final boolean isTargetInstantApp =
+                        (si.applicationInfo.privateFlags
+                                & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
                 final boolean isTargetHiddenFromInstantApp =
                         (si.flags & ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
                 final boolean blockResolution =
                         !isTargetSameInstantApp
-                        && ((matchVisibleToInstantAppOnly && isCallerInstantApp
+                        && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
+                                || (matchVisibleToInstantAppOnly && isCallerInstantApp
                                         && isTargetHiddenFromInstantApp));
                 if (!blockResolution) {
                     final ResolveInfo ri = new ResolveInfo();
@@ -7192,6 +7205,7 @@
             Intent intent, String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
+        final String instantAppPkgName = getInstantAppPackageName(callingUid);
         flags = updateFlagsForResolve(flags, userId, intent, callingUid,
                 false /*includeInstantApps*/);
         ComponentName comp = intent.getComponent();
@@ -7205,9 +7219,33 @@
             final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
             final ProviderInfo pi = getProviderInfo(comp, flags, userId);
             if (pi != null) {
-                final ResolveInfo ri = new ResolveInfo();
-                ri.providerInfo = pi;
-                list.add(ri);
+                // When specifying an explicit component, we prevent the provider from being
+                // used when either 1) the provider is in an instant application and the
+                // caller is not the same instant application or 2) the calling package is an
+                // instant application and the provider is not visible to instant applications.
+                final boolean matchInstantApp =
+                        (flags & PackageManager.MATCH_INSTANT) != 0;
+                final boolean matchVisibleToInstantAppOnly =
+                        (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+                final boolean isCallerInstantApp =
+                        instantAppPkgName != null;
+                final boolean isTargetSameInstantApp =
+                        comp.getPackageName().equals(instantAppPkgName);
+                final boolean isTargetInstantApp =
+                        (pi.applicationInfo.privateFlags
+                                & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
+                final boolean isTargetHiddenFromInstantApp =
+                        (pi.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0;
+                final boolean blockResolution =
+                        !isTargetSameInstantApp
+                        && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
+                                || (matchVisibleToInstantAppOnly && isCallerInstantApp
+                                        && isTargetHiddenFromInstantApp));
+                if (!blockResolution) {
+                    final ResolveInfo ri = new ResolveInfo();
+                    ri.providerInfo = pi;
+                    list.add(ri);
+                }
             }
             return list;
         }
@@ -7216,17 +7254,67 @@
         synchronized (mPackages) {
             String pkgName = intent.getPackage();
             if (pkgName == null) {
-                return mProviders.queryIntent(intent, resolvedType, flags, userId);
+                return applyPostContentProviderResolutionFilter(
+                        mProviders.queryIntent(intent, resolvedType, flags, userId),
+                        instantAppPkgName);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                return mProviders.queryIntentForPackage(
-                        intent, resolvedType, flags, pkg.providers, userId);
+                return applyPostContentProviderResolutionFilter(
+                        mProviders.queryIntentForPackage(
+                        intent, resolvedType, flags, pkg.providers, userId),
+                        instantAppPkgName);
             }
             return Collections.emptyList();
         }
     }
 
+    private List<ResolveInfo> applyPostContentProviderResolutionFilter(
+            List<ResolveInfo> resolveInfos, String instantAppPkgName) {
+        // TODO: When adding on-demand split support for non-instant applications, remove
+        // this check and always apply post filtering
+        if (instantAppPkgName == null) {
+            return resolveInfos;
+        }
+        for (int i = resolveInfos.size() - 1; i >= 0; i--) {
+            final ResolveInfo info = resolveInfos.get(i);
+            final boolean isEphemeralApp = info.providerInfo.applicationInfo.isInstantApp();
+            // allow providers that are defined in the provided package
+            if (isEphemeralApp && instantAppPkgName.equals(info.providerInfo.packageName)) {
+                if (info.providerInfo.splitName != null
+                        && !ArrayUtils.contains(info.providerInfo.applicationInfo.splitNames,
+                                info.providerInfo.splitName)) {
+                    // requested provider is defined in a split that hasn't been installed yet.
+                    // add the installer to the resolve list
+                    if (DEBUG_EPHEMERAL) {
+                        Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list");
+                    }
+                    final ResolveInfo installerInfo = new ResolveInfo(mInstantAppInstallerInfo);
+                    installerInfo.auxiliaryInfo = new AuxiliaryResolveInfo(
+                            info.providerInfo.packageName, info.providerInfo.splitName,
+                            info.providerInfo.applicationInfo.versionCode);
+                    // make sure this resolver is the default
+                    installerInfo.isDefault = true;
+                    installerInfo.match = IntentFilter.MATCH_CATEGORY_SCHEME_SPECIFIC_PART
+                            | IntentFilter.MATCH_ADJUSTMENT_NORMAL;
+                    // add a non-generic filter
+                    installerInfo.filter = new IntentFilter();
+                    // load resources from the correct package
+                    installerInfo.resolvePackageName = info.getComponentInfo().packageName;
+                    resolveInfos.set(i, installerInfo);
+                }
+                continue;
+            }
+            // allow providers that have been explicitly exposed to instant applications
+            if (!isEphemeralApp
+                    && ((info.providerInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
+                continue;
+            }
+            resolveInfos.remove(i);
+        }
+        return resolveInfos;
+    }
+
     @Override
     public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -7558,17 +7646,38 @@
     public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId, name);
+        final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
         // reader
         synchronized (mPackages) {
             final PackageParser.Provider provider = mProvidersByAuthority.get(name);
             PackageSetting ps = provider != null
                     ? mSettings.mPackages.get(provider.owner.packageName)
                     : null;
-            return ps != null
-                    && mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)
-                    ? PackageParser.generateProviderInfo(provider, flags,
-                            ps.readUserState(userId), userId)
-                    : null;
+            if (ps != null) {
+                final boolean isInstantApp = ps.getInstantApp(userId);
+                // normal application; filter out instant application provider
+                if (instantAppPkgName == null && isInstantApp) {
+                    return null;
+                }
+                // instant application; filter out other instant applications
+                if (instantAppPkgName != null
+                        && isInstantApp
+                        && !provider.owner.packageName.equals(instantAppPkgName)) {
+                    return null;
+                }
+                // instant application; filter out non-exposed provider
+                if (instantAppPkgName != null
+                        && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL) == 0) {
+                    return null;
+                }
+                // provider not enabled
+                if (!mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)) {
+                    return null;
+                }
+                return PackageParser.generateProviderInfo(
+                        provider, flags, ps.readUserState(userId), userId);
+            }
+            return null;
         }
     }
 
@@ -12772,8 +12881,26 @@
             if (ps == null) {
                 return null;
             }
+            final PackageUserState userState = ps.readUserState(userId);
+            final boolean matchVisibleToInstantApp =
+                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            // throw out filters that aren't visible to instant applications
+            if (matchVisibleToInstantApp
+                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+                return null;
+            }
+            // throw out instant application filters if we're not explicitly requesting them
+            if (!isInstantApp && userState.instantApp) {
+                return null;
+            }
+            // throw out instant application filters if updates are available; will trigger
+            // instant application resolution
+            if (userState.instantApp && ps.isUpdateAvailable()) {
+                return null;
+            }
             ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
-                    ps.readUserState(userId), userId);
+                    userState, userId);
             if (pi == null) {
                 return null;
             }
@@ -12959,7 +13086,7 @@
         }
     };
 
-    final void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
+    public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
             final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,
             final int[] userIds) {
         mHandler.post(new Runnable() {
@@ -13077,7 +13204,7 @@
                 if (dcsUid > 0) {
                     am.backgroundWhitelistUid(dcsUid);
                 }
-                am.startService(null, intent, null, -1, null, false, mContext.getOpPackageName(),
+                am.startService(null, intent, null, false, mContext.getOpPackageName(),
                         UserHandle.USER_SYSTEM);
             } catch (RemoteException e) {
             }
@@ -13262,8 +13389,7 @@
         sendPackageAddedForNewUsers(packageName, isSystem, pkgSetting.appId, userId);
     }
 
-    private void sendPackageAddedForNewUsers(String packageName, boolean isSystem,
-            int appId, int... userIds) {
+    public void sendPackageAddedForNewUsers(String packageName, boolean isSystem, int appId, int... userIds) {
         if (ArrayUtils.isEmpty(userIds)) {
             return;
         }
@@ -13271,8 +13397,10 @@
         // Set to UID of the first user, EXTRA_UID is automatically updated in sendPackageBroadcast
         extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userIds[0], appId));
 
-        sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
-                packageName, extras, 0, null, null, userIds);
+        sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_ADDED, packageName,
+                extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null, null, userIds);
+        sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+                extras, 0, null, null, userIds);
         if (isSystem) {
             mHandler.post(() -> {
                         for (int userId : userIds) {
@@ -13388,7 +13516,7 @@
 
     private void sendApplicationHiddenForUser(String packageName, PackageSetting pkgSetting,
             int userId) {
-        final PackageRemovedInfo info = new PackageRemovedInfo();
+        final PackageRemovedInfo info = new PackageRemovedInfo(this);
         info.removedPackage = packageName;
         info.removedUsers = new int[] {userId};
         info.broadcastUsers = new int[] {userId};
@@ -16024,7 +16152,7 @@
         }
 
         // Update what is removed
-        res.removedInfo = new PackageRemovedInfo();
+        res.removedInfo = new PackageRemovedInfo(this);
         res.removedInfo.uid = oldPackage.applicationInfo.uid;
         res.removedInfo.removedPackage = oldPackage.packageName;
         res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null;
@@ -16054,7 +16182,7 @@
                 }
             }
             if (!childPackageUpdated) {
-                PackageRemovedInfo childRemovedRes = new PackageRemovedInfo();
+                PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);
                 childRemovedRes.removedPackage = childPkg.packageName;
                 childRemovedRes.isUpdate = false;
                 childRemovedRes.dataRemoved = true;
@@ -16744,7 +16872,7 @@
                                 sUserManager.getUserIds(), true);
                     }
                     if ((mPackages.containsKey(childPkg.packageName))) {
-                        childRes.removedInfo = new PackageRemovedInfo();
+                        childRes.removedInfo = new PackageRemovedInfo(this);
                         childRes.removedInfo.removedPackage = childPkg.packageName;
                     }
                     if (res.addedChildPackages == null) {
@@ -17467,7 +17595,8 @@
         for (int i = 0; i < versionCount; i++) {
             SharedLibraryEntry libEntry = versionedLib.valueAt(i);
             if (versionsCallerCanSee != null && versionsCallerCanSee.indexOfKey(
-                    libEntry.info.getVersion()) < 0) {
+                    // TODO: Remove cast for lib version once internally we support longs.
+                    (int) libEntry.info.getVersion()) < 0) {
                 continue;
             }
             // TODO: We will change version code to long, so in the new API it is long
@@ -17590,7 +17719,7 @@
      *  sending a broadcast if necessary
      */
     private int deletePackageX(String packageName, int versionCode, int userId, int deleteFlags) {
-        final PackageRemovedInfo info = new PackageRemovedInfo();
+        final PackageRemovedInfo info = new PackageRemovedInfo(this);
         final boolean res;
 
         final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
@@ -17690,7 +17819,8 @@
         return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
     }
 
-    class PackageRemovedInfo {
+    static class PackageRemovedInfo {
+        final PackageSender packageSender;
         String removedPackage;
         int uid = -1;
         int removedAppId = -1;
@@ -17708,6 +17838,10 @@
         ArrayMap<String, PackageRemovedInfo> removedChildPackages;
         ArrayMap<String, PackageInstalledInfo> appearedChildPackages;
 
+        PackageRemovedInfo(PackageSender packageSender) {
+            this.packageSender = packageSender;
+        }
+
         void sendPackageRemovedBroadcasts(boolean killApp) {
             sendPackageRemovedBroadcastInternal(killApp);
             final int childCount = removedChildPackages != null ? removedChildPackages.size() : 0;
@@ -17736,8 +17870,9 @@
                     ? appearedChildPackages.size() : 0;
             for (int i = 0; i < packageCount; i++) {
                 PackageInstalledInfo installedInfo = appearedChildPackages.valueAt(i);
-                sendPackageAddedForNewUsers(installedInfo.name, true,
-                        UserHandle.getAppId(installedInfo.uid), installedInfo.newUsers);
+                packageSender.sendPackageAddedForNewUsers(installedInfo.name,
+                    true, UserHandle.getAppId(installedInfo.uid),
+                    installedInfo.newUsers);
             }
         }
 
@@ -17745,12 +17880,12 @@
             Bundle extras = new Bundle(2);
             extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
             extras.putBoolean(Intent.EXTRA_REPLACING, true);
-            sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage,
-                    extras, 0, null, null, null);
-            sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage,
-                    extras, 0, null, null, null);
-            sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
-                    null, 0, removedPackage, null, null);
+            packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+                removedPackage, extras, 0, null, null, null);
+            packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
+                removedPackage, extras, 0, null, null, null);
+            packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
+                null, null, 0, removedPackage, null, null);
         }
 
         private void sendPackageRemovedBroadcastInternal(boolean killApp) {
@@ -17769,17 +17904,36 @@
             }
             extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, removedForAllUsers);
             if (removedPackage != null) {
-                sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
-                        extras, 0, null, null, broadcastUsers);
+                packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
+                    removedPackage, extras, 0, null, null, broadcastUsers);
                 if (dataRemoved && !isRemovedPackageSystemUpdate) {
-                    sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
-                            removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
-                            null, null, broadcastUsers);
+                    packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
+                        removedPackage, extras,
+                        Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
+                        null, null, broadcastUsers);
                 }
             }
             if (removedAppId >= 0) {
-                sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, 0, null, null,
-                        broadcastUsers);
+                packageSender.sendPackageBroadcast(Intent.ACTION_UID_REMOVED,
+                    null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
+                    null, null, broadcastUsers);
+            }
+        }
+
+        void populateUsers(int[] userIds, PackageSetting deletedPackageSetting) {
+            removedUsers = userIds;
+            if (removedUsers == null) {
+                broadcastUsers = null;
+                return;
+            }
+
+            broadcastUsers = EMPTY_INT_ARRAY;
+            for (int i = userIds.length - 1; i >= 0; --i) {
+                final int userId = userIds[i];
+                if (deletedPackageSetting.getInstantApp(userId)) {
+                    continue;
+                }
+                broadcastUsers = ArrayUtils.appendInt(broadcastUsers, userId);
             }
         }
     }
@@ -17805,23 +17959,8 @@
                 outInfo.removedPackage = packageName;
                 outInfo.isStaticSharedLib = deletedPkg != null
                         && deletedPkg.staticSharedLibName != null;
-                outInfo.removedUsers = deletedPs != null
-                        ? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
-                        : null;
-                if (outInfo.removedUsers == null) {
-                    outInfo.broadcastUsers = null;
-                } else {
-                    outInfo.broadcastUsers = EMPTY_INT_ARRAY;
-                    int[] allUsers = outInfo.removedUsers;
-                    for (int i = allUsers.length - 1; i >= 0; --i) {
-                        final int userId = allUsers[i];
-                        if (deletedPs.getInstantApp(userId)) {
-                            continue;
-                        }
-                        outInfo.broadcastUsers =
-                                ArrayUtils.appendInt(outInfo.broadcastUsers, userId);
-                    }
-                }
+                outInfo.populateUsers(deletedPs == null ? null
+                        : deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true), deletedPs);
             }
         }
 
@@ -18304,7 +18443,7 @@
                 outInfo.removedChildPackages = new ArrayMap<>(childCount);
                 for (int i = 0; i < childCount; i++) {
                     String childPackageName = ps.childPackageNames.get(i);
-                    PackageRemovedInfo childInfo = new PackageRemovedInfo();
+                    PackageRemovedInfo childInfo = new PackageRemovedInfo(this);
                     childInfo.removedPackage = childPackageName;
                     outInfo.removedChildPackages.put(childPackageName, childInfo);
                     PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
@@ -21566,7 +21705,7 @@
             if (DEBUG_SD_INSTALL)
                 Log.i(TAG, "Trying to unload pkg : " + pkgName);
             // Delete package internally
-            PackageRemovedInfo outInfo = new PackageRemovedInfo();
+            PackageRemovedInfo outInfo = new PackageRemovedInfo(this);
             synchronized (mInstallLock) {
                 final int deleteFlags = PackageManager.DELETE_KEEP_DATA;
                 final boolean res;
@@ -21733,7 +21872,7 @@
 
                 final ApplicationInfo info = ps.pkg.applicationInfo;
                 final int deleteFlags = PackageManager.DELETE_KEEP_DATA;
-                final PackageRemovedInfo outInfo = new PackageRemovedInfo();
+                final PackageRemovedInfo outInfo = new PackageRemovedInfo(this);
 
                 try (PackageFreezer freezer = freezePackageForDelete(ps.name, deleteFlags,
                         "unloadPrivatePackagesInner")) {
@@ -23358,7 +23497,6 @@
                     intent, resolvedType, flags, userId, callingUid, true /*includeInstantApps*/);
         }
 
-
         @Override
         public void addIsolatedUid(int isolatedUid, int ownerUid) {
             synchronized (mPackages) {
@@ -23514,4 +23652,18 @@
     public ComponentName getInstantAppResolverSettingsComponent() {
         return mInstantAppResolverSettingsComponent;
     }
+
+    @Override
+    public ComponentName getInstantAppInstallerComponent() {
+        return mInstantAppInstallerActivity == null
+                ? null : mInstantAppInstallerActivity.getComponentName();
+    }
+}
+
+interface PackageSender {
+    void sendPackageBroadcast(final String action, final String pkg,
+        final Bundle extras, final int flags, final String targetPkg,
+        final IIntentReceiver finishedReceiver, final int[] userIds);
+    void sendPackageAddedForNewUsers(String packageName, boolean isSystem,
+        int appId, int... userIds);
 }
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index c6667a7..a6b05d7 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -31,7 +31,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
-import android.service.persistentdata.PersistentDataBlockManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.util.Log;
@@ -519,22 +518,6 @@
                             android.provider.Settings.Global.SAFE_BOOT_DISALLOWED,
                             newValue ? 1 : 0);
                     break;
-                case UserManager.DISALLOW_FACTORY_RESET:
-                case UserManager.DISALLOW_OEM_UNLOCK:
-                    if (newValue) {
-                        PersistentDataBlockManager manager = (PersistentDataBlockManager) context
-                                .getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
-                        if (manager != null
-                                && manager.getOemUnlockEnabled()
-                                && manager.getFlashLockState()
-                                        != PersistentDataBlockManager.FLASH_LOCK_UNLOCKED) {
-                            // Only disable OEM unlock if the bootloader is locked. If it's already
-                            // unlocked, setting the OEM unlock enabled flag to false has no effect
-                            // (the bootloader would remain unlocked).
-                            manager.setOemUnlockEnabled(false);
-                        }
-                    }
-                    break;
             }
         } finally {
             Binder.restoreCallingIdentity(id);
diff --git a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
index 7d53310..d8e9e16 100644
--- a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
+++ b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
@@ -78,6 +78,7 @@
 
     public AccessibilityShortcutController(Context context, Handler handler, int initialUserId) {
         mContext = context;
+        mUserId = initialUserId;
 
         // Keep track of state of shortcut settings
         final ContentObserver co = new ContentObserver(handler) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 95fb5af..c70344c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -145,6 +145,7 @@
 import android.database.ContentObserver;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.hardware.display.DisplayManager;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiPlaybackClient;
@@ -221,6 +222,7 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationSet;
 import android.view.animation.AnimationUtils;
+import android.view.inputmethod.InputMethodManagerInternal;
 
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
@@ -277,6 +279,7 @@
     static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2;
     static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3;
     static final int SHORT_PRESS_POWER_GO_HOME = 4;
+    static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5;
 
     static final int LONG_PRESS_POWER_NOTHING = 0;
     static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
@@ -405,6 +408,7 @@
     PowerManager mPowerManager;
     ActivityManagerInternal mActivityManagerInternal;
     InputManagerInternal mInputManagerInternal;
+    InputMethodManagerInternal mInputMethodManagerInternal;
     DreamManagerInternal mDreamManagerInternal;
     PowerManagerInternal mPowerManagerInternal;
     IStatusBarService mStatusBarService;
@@ -511,6 +515,7 @@
     volatile boolean mPictureInPictureVisible;
     // Written by vr manager thread, only read in this class
     volatile boolean mPersistentVrModeEnabled;
+    volatile private boolean mDismissImeOnBackKeyPressed;
 
     // Used to hold the last user key used to wake the device.  This helps us prevent up events
     // from being passed to the foregrounded app without a corresponding down event
@@ -1394,6 +1399,21 @@
                 case SHORT_PRESS_POWER_GO_HOME:
                     launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
                     break;
+                case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
+                    if (mDismissImeOnBackKeyPressed) {
+                        if (mInputMethodManagerInternal == null) {
+                            mInputMethodManagerInternal =
+                                    LocalServices.getService(InputMethodManagerInternal.class);
+                        }
+                        if (mInputMethodManagerInternal != null) {
+                            mInputMethodManagerInternal.hideCurrentInputMethod();
+                        }
+                    } else {
+                        launchHomeFromHotKey(true /* awakenFromDreams */,
+                                false /*respectKeyguard*/);
+                    }
+                    break;
+                }
             }
         }
     }
@@ -2809,6 +2829,7 @@
                             + overrideConfig + " to starting window resId=" + resId);
                     context = overrideContext;
                 }
+                typedArray.recycle();
             }
 
             final PhoneWindow win = new PhoneWindow(context);
@@ -2868,6 +2889,8 @@
             }
 
             params.setTitle("Splash Screen " + packageName);
+            addSplashscreenContent(win, context);
+
             wm = (WindowManager) context.getSystemService(WINDOW_SERVICE);
             view = win.getDecorView();
 
@@ -2898,6 +2921,24 @@
         return null;
     }
 
+    private void addSplashscreenContent(PhoneWindow win, Context ctx) {
+        final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window);
+        final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0);
+        a.recycle();
+        if (resId == 0) {
+            return;
+        }
+        final Drawable drawable = ctx.getDrawable(resId);
+        if (drawable == null) {
+            return;
+        }
+
+        // We wrap this into a view so the system insets get applied to the drawable.
+        final View v = new View(ctx);
+        v.setBackground(drawable);
+        win.setContentView(v);
+    }
+
     /** Obtain proper context for showing splash screen on the provided display. */
     private Context getDisplayContext(Context context, int displayId) {
         if (displayId == Display.DEFAULT_DISPLAY) {
@@ -5238,7 +5279,7 @@
     @Override
     public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
             WindowState attached, WindowState imeTarget) {
-        final boolean visible = !win.isGoneForLayoutLw();
+        final boolean visible = !win.isGoneForLayoutLw() && win.getAttrs().alpha > 0f;
         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
         applyKeyguardPolicyLw(win, imeTarget);
         final int fl = PolicyControl.getWindowFlags(win, attrs);
@@ -7514,7 +7555,7 @@
 
     private boolean areSystemNavigationKeysEnabled() {
         return Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
+                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 1, UserHandle.USER_CURRENT) == 1;
     }
 
     @Override
@@ -7932,6 +7973,11 @@
     }
 
     @Override
+    public void setDismissImeOnBackKeyPressed(boolean newValue) {
+        mDismissImeOnBackKeyPressed = newValue;
+    }
+
+    @Override
     public int getInputMethodWindowVisibleHeightLw() {
         return mDockBottom - mCurBottom;
     }
@@ -8147,6 +8193,8 @@
             pw.print(prefix); pw.print("mLastInputMethodTargetWindow=");
                     pw.println(mLastInputMethodTargetWindow);
         }
+        pw.print(prefix); pw.print("mDismissImeOnBackKeyPressed=");
+                pw.println(mDismissImeOnBackKeyPressed);
         if (mStatusBar != null) {
             pw.print(prefix); pw.print("mStatusBar=");
                     pw.print(mStatusBar); pw.print(" isStatusBarKeyguard=");
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 8f11436..f5bb082 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -406,11 +406,7 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        LogMaker log = new LogMaker(MetricsEvent.SCREEN);
-                        log.setType(MetricsEvent.TYPE_OPEN);
-                        log.setSubtype(0); // not user initiated
-                        MetricsLogger.action(log);
-                        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
+                        // Note a SCREEN tron event is logged in PowerManagerService.
                         mPolicy.startedWakingUp();
                     }
                 });
@@ -470,7 +466,7 @@
                         log.setType(MetricsEvent.TYPE_CLOSE);
                         log.setSubtype(why);
                         MetricsLogger.action(log);
-                        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
+                        EventLogTags.writePowerScreenState(0, why, 0, 0, 0);
                         mPolicy.finishedGoingToSleep(why);
                     }
                 });
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index cf597b05..4f239a5 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -32,6 +32,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
 import android.hardware.power.V1_0.PowerHint;
+import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.BatteryManagerInternal;
@@ -75,6 +76,8 @@
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
@@ -188,6 +191,11 @@
     // System property indicating that the screen should remain off until an explicit user action
     private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
 
+    private static final String TRACE_SCREEN_ON = "Screen turning on";
+
+    /** If turning screen on takes more than this long, we show a warning on logcat. */
+    private static final int SCREEN_ON_LATENCY_WARNING_MS = 200;
+
     /** Constants for {@link #shutdownOrRebootInternal} */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({HALT_MODE_SHUTDOWN, HALT_MODE_REBOOT, HALT_MODE_REBOOT_SAFE_MODE})
@@ -1369,6 +1377,8 @@
             return false;
         }
 
+        Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);
+
         Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");
         try {
             switch (mWakefulness) {
@@ -1551,6 +1561,23 @@
         }
     }
 
+    private void logScreenOn() {
+        Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);
+
+        final int latencyMs = (int) (SystemClock.uptimeMillis() - mLastWakeTime);
+
+        LogMaker log = new LogMaker(MetricsEvent.SCREEN);
+        log.setType(MetricsEvent.TYPE_OPEN);
+        log.setSubtype(0); // not user initiated
+        log.setLatency(latencyMs); // How long it took.
+        MetricsLogger.action(log);
+        EventLogTags.writePowerScreenState(1, 0, 0, 0, latencyMs);
+
+        if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {
+            Slog.w(TAG, "Screen on took " + latencyMs+ " ms");
+        }
+    }
+
     private void finishWakefulnessChangeIfNeededLocked() {
         if (mWakefulnessChanging && mDisplayReady) {
             if (mWakefulness == WAKEFULNESS_DOZING
@@ -1560,6 +1587,9 @@
             if (mWakefulness == WAKEFULNESS_DOZING || mWakefulness == WAKEFULNESS_ASLEEP) {
                 logSleepTimeoutRecapturedLocked();
             }
+            if (mWakefulness == WAKEFULNESS_AWAKE) {
+                logScreenOn();
+            }
             mWakefulnessChanging = false;
             mNotifier.onWakefulnessChangeFinished();
         }
diff --git a/services/core/java/com/android/server/radio/RadioService.java b/services/core/java/com/android/server/radio/RadioService.java
index 327e98f..fb93384 100644
--- a/services/core/java/com/android/server/radio/RadioService.java
+++ b/services/core/java/com/android/server/radio/RadioService.java
@@ -28,29 +28,37 @@
     // TODO(b/36863239): rename to RadioService when native service goes away
     private static final String TAG = "RadioServiceJava";
 
+    private final RadioServiceImpl mServiceImpl = new RadioServiceImpl();
+
+    /**
+     * This field is used by native code, do not access or modify.
+     */
+    private final long mNativeContext = nativeInit();
+
     public RadioService(Context context) {
         super(context);
     }
 
     @Override
+    protected void finalize() throws Throwable {
+        nativeFinalize(mNativeContext);
+        super.finalize();
+    }
+
+    private native long nativeInit();
+    private native void nativeFinalize(long nativeContext);
+    private native Tuner openTunerNative(long nativeContext, boolean withAudio);
+
+    @Override
     public void onStart() {
-        publishBinderService(Context.RADIO_SERVICE, new RadioServiceImpl());
+        publishBinderService(Context.RADIO_SERVICE, mServiceImpl);
         Slog.v(TAG, "RadioService started");
     }
 
-    private static class RadioServiceImpl extends IRadioService.Stub {
+    private class RadioServiceImpl extends IRadioService.Stub {
         @Override
-        public ITuner openTuner() {
-            Slog.d(TAG, "openTuner()");
-            return new TunerImpl();
-        }
-    }
-
-    private static class TunerImpl extends ITuner.Stub {
-        @Override
-        public int getProgramInformation(RadioManager.ProgramInfo[] infoOut) {
-            Slog.d(TAG, "getProgramInformation()");
-            return RadioManager.STATUS_INVALID_OPERATION;
+        public ITuner openTuner(boolean withAudio) {
+            return openTunerNative(mNativeContext, withAudio);
         }
     }
 }
diff --git a/services/core/java/com/android/server/radio/Tuner.java b/services/core/java/com/android/server/radio/Tuner.java
new file mode 100644
index 0000000..6de9c99
--- /dev/null
+++ b/services/core/java/com/android/server/radio/Tuner.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.radio;
+
+import android.hardware.radio.ITuner;
+import android.hardware.radio.RadioManager;
+import android.util.Slog;
+
+class Tuner extends ITuner.Stub {
+    // TODO(b/36863239): rename to RadioService.Tuner when native service goes away
+    private static final String TAG = "RadioServiceJava.Tuner";
+
+    /**
+     * This field is used by native code, do not access or modify.
+     */
+    private final long mNativeContext = nativeInit();
+
+    @Override
+    protected void finalize() throws Throwable {
+        nativeFinalize(mNativeContext);
+        super.finalize();
+    }
+
+    private native long nativeInit();
+    private native void nativeFinalize(long nativeContext);
+
+    @Override
+    public native void close();
+
+    @Override
+    public int getProgramInformation(RadioManager.ProgramInfo[] infoOut) {
+        Slog.d(TAG, "getProgramInformation()");
+        return RadioManager.STATUS_INVALID_OPERATION;
+    }
+}
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index a77d33f..03b754f 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -21,22 +21,21 @@
 import android.app.usage.StorageStatsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageStatsObserver;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageStats;
 import android.content.pm.UserInfo;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
 import android.os.UserManager;
 import android.os.storage.VolumeInfo;
 import android.util.Log;
+
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.Preconditions;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -44,7 +43,6 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * AppCollector asynchronously collects package sizes.
@@ -132,7 +130,7 @@
 
                             try {
                                 StorageStats storageStats =
-                                        mStorageStatsManager.queryStatsForPackage(app.volumeUuid,
+                                        mStorageStatsManager.queryStatsForPackage(app.storageUuid,
                                                 app.packageName, user.getUserHandle());
                                 PackageStats packageStats = new PackageStats(app.packageName,
                                         user.id);
@@ -140,7 +138,7 @@
                                 packageStats.codeSize = storageStats.getCodeBytes();
                                 packageStats.dataSize = storageStats.getDataBytes();
                                 stats.add(packageStats);
-                            } catch (IllegalStateException e) {
+                            } catch (NameNotFoundException | IOException e) {
                                 Log.e(TAG, "An exception occurred while fetching app size", e);
                             }
                         }
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index a519acc..25a0772 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1954,6 +1954,33 @@
         }
 
         @Override
+        public void requestChannelBrowsable(Uri channelUri, int userId)
+                throws RemoteException {
+            final String callingPackageName = getCallingPackageName();
+            final long identity = Binder.clearCallingIdentity();
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                userId, "requestChannelBrowsable");
+            try {
+                Intent intent = new Intent(TvContract.ACTION_CHANNEL_BROWSABLE_REQUESTED);
+                List<ResolveInfo> list = getContext().getPackageManager()
+                    .queryBroadcastReceivers(intent, 0);
+                if (list != null) {
+                    for (ResolveInfo info : list) {
+                        String receiverPackageName = info.activityInfo.packageName;
+                        intent.putExtra(TvContract.EXTRA_CHANNEL_ID, ContentUris.parseId(
+                                channelUri));
+                        intent.putExtra(TvContract.EXTRA_PACKAGE_NAME, callingPackageName);
+                        intent.setPackage(receiverPackageName);
+                        getContext().sendBroadcastAsUser(intent, new UserHandle(resolvedUserId));
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         @SuppressWarnings("resource")
         protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 2811145..e634552 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 android.animation.Animator;
 import android.animation.ValueAnimator;
+import android.annotation.IntDef;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Handler;
@@ -33,6 +34,11 @@
 import android.view.animation.Interpolator;
 import android.view.WindowManagerInternal;
 
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Enables animating bounds of objects.
  *
@@ -41,7 +47,7 @@
  * relaunching it would cause poorer experience), these class provides a way to directly animate
  * the bounds of the resized object.
  *
- * The object that is resized needs to implement {@link AnimateBoundsUser} interface.
+ * The object that is resized needs to implement {@link BoundsAnimationTarget} interface.
  *
  * NOTE: All calls to methods in this class should be done on the UI thread
  */
@@ -54,8 +60,19 @@
 
     private static final int DEFAULT_TRANSITION_DURATION = 425;
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({NO_PIP_MODE_CHANGED_CALLBACKS, SCHEDULE_PIP_MODE_CHANGED_ON_START,
+        SCHEDULE_PIP_MODE_CHANGED_ON_END})
+    public @interface SchedulePipModeChangedState {}
+    /** Do not schedule any PiP mode changed callbacks as a part of this animation. */
+    public static final int NO_PIP_MODE_CHANGED_CALLBACKS = 0;
+    /** Schedule a PiP mode changed callback when this animation starts. */
+    public static final int SCHEDULE_PIP_MODE_CHANGED_ON_START = 1;
+    /** Schedule a PiP mode changed callback when this animation ends. */
+    public static final int SCHEDULE_PIP_MODE_CHANGED_ON_END = 2;
+
     // Only accessed on UI thread.
-    private ArrayMap<AnimateBoundsUser, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
+    private ArrayMap<BoundsAnimationTarget, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
 
     private final class AppTransitionNotifier
             extends WindowManagerInternal.AppTransitionListener implements Runnable {
@@ -103,40 +120,45 @@
                 com.android.internal.R.interpolator.fast_out_slow_in);
     }
 
-    private final class BoundsAnimator extends ValueAnimator
+    @VisibleForTesting
+    final class BoundsAnimator extends ValueAnimator
             implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
-        private final AnimateBoundsUser mTarget;
+        private final BoundsAnimationTarget mTarget;
         private final Rect mFrom = new Rect();
         private final Rect mTo = new Rect();
         private final Rect mTmpRect = new Rect();
         private final Rect mTmpTaskBounds = new Rect();
-        private final boolean mMoveToFullScreen;
-        // True if this this animation was cancelled and will be replaced the another animation from
-        // the same {@link #AnimateBoundsUser} target.
-        private boolean mSkipAnimationEnd;
+
+        // True if this this animation was canceled and will be replaced the another animation from
+        // the same {@link #BoundsAnimationTarget} target.
+        private boolean mSkipFinalResize;
         // True if this animation replaced a previous animation of the same
-        // {@link #AnimateBoundsUser} target.
+        // {@link #BoundsAnimationTarget} target.
         private final boolean mSkipAnimationStart;
-        // True if this animation is not replacing a previous animation, or if the previous
-        // animation is animating to a different fullscreen state than the current animation.
-        // We use this to ensure that we always provide a consistent set/order of callbacks when we
-        // transition to/from PiP.
-        private final boolean mAnimatingToNewFullscreenState;
+        // True if this animation was canceled by the user, not as a part of a replacing animation
+        private boolean mSkipAnimationEnd;
+        // True if the animation target should be moved to the fullscreen stack at the end of this
+        // animation
+        private boolean mMoveToFullscreen;
+
+        // Whether to schedule PiP mode changes on animation start/end
+        private @SchedulePipModeChangedState int mSchedulePipModeChangedState;
 
         // Depending on whether we are animating from
         // a smaller to a larger size
         private final int mFrozenTaskWidth;
         private final int mFrozenTaskHeight;
 
-        BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to, boolean moveToFullScreen,
-                boolean replacingExistingAnimation, boolean animatingToNewFullscreenState) {
+        BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to,
+                @SchedulePipModeChangedState int schedulePipModeChangedState,
+                boolean moveToFullscreen, boolean replacingExistingAnimation) {
             super();
             mTarget = target;
             mFrom.set(from);
             mTo.set(to);
-            mMoveToFullScreen = moveToFullScreen;
             mSkipAnimationStart = replacingExistingAnimation;
-            mAnimatingToNewFullscreenState = animatingToNewFullscreenState;
+            mSchedulePipModeChangedState = schedulePipModeChangedState;
+            mMoveToFullscreen = moveToFullscreen;
             addUpdateListener(this);
             addListener(this);
 
@@ -156,7 +178,8 @@
         @Override
         public void onAnimationStart(Animator animation) {
             if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
-                    + " mSkipAnimationStart=" + mSkipAnimationStart);
+                    + " mSkipAnimationStart=" + mSkipAnimationStart
+                    + " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState);
             mFinishAnimationAfterTransition = false;
             mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth,
                     mFrom.top + mFrozenTaskHeight);
@@ -165,13 +188,8 @@
             // we trigger any size changes, so it can swap surfaces
             // in to appropriate modes, or do as it wishes otherwise.
             if (!mSkipAnimationStart) {
-                mTarget.onAnimationStart(mMoveToFullScreen);
-            }
-
-            // If we are animating to a new fullscreen state (either to/from fullscreen), then
-            // notify the target of the change with the new frozen task bounds
-            if (mAnimatingToNewFullscreenState && mMoveToFullScreen) {
-                mTarget.updatePictureInPictureMode(null);
+                mTarget.onAnimationStart(mSchedulePipModeChangedState ==
+                        SCHEDULE_PIP_MODE_CHANGED_ON_START);
             }
 
             // Immediately update the task bounds if they have to become larger, but preserve
@@ -200,17 +218,27 @@
                 // Whoops, the target doesn't feel like animating anymore. Let's immediately finish
                 // any further animation.
                 if (DEBUG) Slog.d(TAG, "animateUpdate: cancelled");
-                animation.cancel();
+
+                // If we have already scheduled a PiP mode changed at the start of the animation,
+                // then we need to clean up and schedule one at the end, since we have canceled the
+                // animation to the final state.
+                if (mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
+                    mSchedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
+                }
+
+                // Since we are cancelling immediately without a replacement animation, send the
+                // animation end to maintain callback parity, but also skip any further resizes
+                cancelAndCallAnimationEnd();
             }
         }
 
         @Override
         public void onAnimationEnd(Animator animation) {
             if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
-                    + " mMoveToFullScreen=" + mMoveToFullScreen
-                    + " mSkipAnimationEnd=" + mSkipAnimationEnd
+                    + " mSkipFinalResize=" + mSkipFinalResize
                     + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition
-                    + " mAppTransitionIsRunning=" + mAppTransition.isRunning());
+                    + " mAppTransitionIsRunning=" + mAppTransition.isRunning()
+                    + " callers=" + Debug.getCallers(2));
 
             // There could be another animation running. For example in the
             // move to fullscreen case, recents will also be closing while the
@@ -222,47 +250,57 @@
                 return;
             }
 
-            finishAnimation();
-
-            mTarget.setPinnedStackSize(mTo, null);
-            if (mMoveToFullScreen && !mSkipAnimationEnd) {
-                mTarget.moveToFullscreen();
+            if (!mSkipAnimationEnd) {
+                // If this animation has already scheduled the picture-in-picture mode on start, and
+                // we are not skipping the final resize due to being canceled, then move the PiP to
+                // fullscreen once the animation ends
+                if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
+                        + " moveToFullscreen=" + mMoveToFullscreen);
+                mTarget.onAnimationEnd(mSchedulePipModeChangedState ==
+                        SCHEDULE_PIP_MODE_CHANGED_ON_END, !mSkipFinalResize ? mTo : null,
+                                mMoveToFullscreen);
             }
+
+            // Clean up this animation
+            removeListener(this);
+            removeUpdateListener(this);
+            mRunningAnimations.remove(mTarget);
         }
 
         @Override
         public void onAnimationCancel(Animator animation) {
-            finishAnimation();
+            // Always skip the final resize when the animation is canceled
+            mSkipFinalResize = true;
+            mMoveToFullscreen = false;
+        }
+
+        private void cancelAndCallAnimationEnd() {
+            if (DEBUG) Slog.d(TAG, "cancelAndCallAnimationEnd: mTarget=" + mTarget);
+            mSkipAnimationEnd = false;
+            super.cancel();
         }
 
         @Override
         public void cancel() {
+            if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget);
             mSkipAnimationEnd = true;
-            if (DEBUG) Slog.d(TAG, "cancel: willReplace mTarget=" + mTarget);
             super.cancel();
         }
 
-        /** Returns true if the animation target is the same as the input bounds. */
+        /**
+         * @return true if the animation target is the same as the input bounds.
+         */
         boolean isAnimatingTo(Rect bounds) {
             return mTo.equals(bounds);
         }
 
-        private boolean animatingToLargerSize() {
-            if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
-                return false;
-            }
-            return true;
-        }
-
-        private void finishAnimation() {
-            if (DEBUG) Slog.d(TAG, "finishAnimation: mTarget=" + mTarget
-                    + " callers" + Debug.getCallers(2));
-            if (!mSkipAnimationEnd) {
-                mTarget.onAnimationEnd();
-            }
-            removeListener(this);
-            removeUpdateListener(this);
-            mRunningAnimations.remove(mTarget);
+        /**
+         * @return true if we are animating to a larger surface size
+         */
+        @VisibleForTesting
+        boolean animatingToLargerSize() {
+            // TODO: Fix this check for aspect ratio changes
+            return (mFrom.width() * mFrom.height() <= mTo.width() * mTo.height());
         }
 
         @Override
@@ -271,76 +309,66 @@
         }
     }
 
-    public interface AnimateBoundsUser {
-        /**
-         * Asks the target to directly (without any intermediate steps, like scheduling animation)
-         * resize its bounds.
-         *
-         * @return Whether the target still wants to be animated and successfully finished the
-         * operation. If it returns false, the animation will immediately be cancelled. The target
-         * should return false when something abnormal happened, e.g. it was completely removed
-         * from the hierarchy and is not valid anymore.
-         */
-        boolean setSize(Rect bounds);
-        /**
-         * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
-         * to allow for more flexibility during resizing. Only works for the pinned stack at the
-         * moment.
-         */
-        boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
-
-        /**
-         * Callback for the target to inform it that the animation has started, so it can do some
-         * necessary preparation.
-         */
-        void onAnimationStart(boolean toFullscreen);
-
-        /**
-         * Callback for the target to inform it that the animation is going to a new fullscreen
-         * state and should update the picture-in-picture mode accordingly.
-         *
-         * @param targetStackBounds the target stack bounds we are animating to, can be null if
-         *                          we are animating to fullscreen
-         */
-        void updatePictureInPictureMode(Rect targetStackBounds);
-
-        /**
-         * Callback for the target to inform it that the animation has ended, so it can do some
-         * necessary cleanup.
-         */
-        void onAnimationEnd();
-
-        void moveToFullscreen();
+    public void animateBounds(final BoundsAnimationTarget target, Rect from, Rect to,
+            int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
+            boolean moveToFullscreen) {
+        animateBoundsImpl(target, from, to, animationDuration, schedulePipModeChangedState,
+                moveToFullscreen);
     }
 
-    void animateBounds(final AnimateBoundsUser target, Rect from, Rect to, int animationDuration,
+    @VisibleForTesting
+    BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to,
+            int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
             boolean moveToFullscreen) {
         final BoundsAnimator existing = mRunningAnimations.get(target);
         final boolean replacing = existing != null;
-        final boolean animatingToNewFullscreenState = (existing == null) ||
-                (existing.mMoveToFullScreen != moveToFullscreen);
 
         if (DEBUG) Slog.d(TAG, "animateBounds: target=" + target + " from=" + from + " to=" + to
-                + " moveToFullscreen=" + moveToFullscreen + " replacing=" + replacing
-                + " animatingToNewFullscreenState=" + animatingToNewFullscreenState);
+                + " schedulePipModeChangedState=" + schedulePipModeChangedState
+                + " replacing=" + replacing);
 
         if (replacing) {
             if (existing.isAnimatingTo(to)) {
-                // Just les the current animation complete if it has the same destination as the
+                // Just let the current animation complete if it has the same destination as the
                 // one we are trying to start.
                 if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing
                         + " ignoring...");
-                return;
+
+                return existing;
             }
+
+            // Update the PiP callback states if we are replacing the animation
+            if (existing.mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
+                if (schedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
+                    if (DEBUG) Slog.d(TAG, "animateBounds: still animating to fullscreen, keep"
+                            + " existing deferred state");
+                } else {
+                    if (DEBUG) Slog.d(TAG, "animateBounds: fullscreen animation canceled, callback"
+                            + " on start already processed, schedule deferred update on end");
+                    schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
+                }
+            } else if (existing.mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END) {
+                if (schedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
+                    if (DEBUG) Slog.d(TAG, "animateBounds: non-fullscreen animation canceled,"
+                            + " callback on start will be processed");
+                } else {
+                    if (DEBUG) Slog.d(TAG, "animateBounds: still animating from fullscreen, keep"
+                            + " existing deferred state");
+                    schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
+                }
+            }
+
+            // Since we are replacing, we skip both animation start and end callbacks
             existing.cancel();
         }
-        final BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen,
-                replacing, animatingToNewFullscreenState);
+        final BoundsAnimator animator = new BoundsAnimator(target, from, to,
+                schedulePipModeChangedState, moveToFullscreen, replacing);
         mRunningAnimations.put(target, animator);
         animator.setFloatValues(0f, 1f);
         animator.setDuration((animationDuration != -1 ? animationDuration
                 : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
         animator.setInterpolator(mFastOutSlowInInterpolator);
         animator.start();
+        return animator;
     }
 }
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
new file mode 100644
index 0000000..8b1bf7b
--- /dev/null
+++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Rect;
+
+/**
+ * The target for a BoundsAnimation.
+ * @see BoundsAnimationController
+ */
+interface BoundsAnimationTarget {
+
+    /**
+     * Callback for the target to inform it that the animation has started, so it can do some
+     * necessary preparation.
+     *
+     * @param schedulePipModeChangedCallback whether or not to schedule the PiP mode changed
+     * callbacks
+     */
+    void onAnimationStart(boolean schedulePipModeChangedCallback);
+
+    /**
+     * Sets the size of the target (without any intermediate steps, like scheduling animation)
+     * but freezes the bounds of any tasks in the target at taskBounds, to allow for more
+     * flexibility during resizing. Only works for the pinned stack at the moment.  This will
+     * only be called between onAnimationStart() and onAnimationEnd().
+     *
+     * @return Whether the target should continue to be animated and this call was successful.
+     * If false, the animation will be cancelled because the user has determined that the
+     * animation is now invalid and not required. In such a case, the cancel will trigger the
+     * animation end callback as well, but will not send any further size changes.
+     */
+    boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds);
+
+    /**
+     * Callback for the target to inform it that the animation has ended, so it can do some
+     * necessary cleanup.
+     *
+     * @param schedulePipModeChangedCallback whether or not to schedule the PiP mode changed
+     * callbacks
+     * @param finalStackSize the final stack bounds to set on the target (can be to indicate that
+     * the animation was cancelled and the target does not need to update to the final stack bounds)
+     * @param moveToFullscreen whether or the target should reparent itself to the fullscreen stack
+     * when the animation completes
+     */
+    void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
+            boolean moveToFullscreen);
+}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2f64cd4..1823610 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -125,6 +125,7 @@
 import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
 import com.android.internal.view.IInputMethodClient;
 
@@ -1396,6 +1397,22 @@
         return null;
     }
 
+    @VisibleForTesting
+    int getStackCount() {
+        return mTaskStackContainers.size();
+    }
+
+    @VisibleForTesting
+    int getStaskPosById(int stackId) {
+        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
+            final TaskStack stack = mTaskStackContainers.get(i);
+            if (stack.mStackId == stackId) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     @Override
     void onConfigurationChanged(Configuration newParentConfig) {
         super.onConfigurationChanged(newParentConfig);
@@ -1420,6 +1437,13 @@
                 changedStackList.add(stack.mStackId);
             }
         }
+
+        // If there was no pinned stack, we still need to notify the controller of the display info
+        // update as a result of the config change.  We do this here to consolidate the flow between
+        // changes when there is and is not a stack.
+        if (getStackById(PINNED_STACK_ID) == null) {
+            mPinnedStackControllerLocked.onDisplayInfoChanged();
+        }
     }
 
     @Override
@@ -3267,8 +3291,9 @@
                     : requestedPosition >= topChildPosition;
             int targetPosition = requestedPosition;
 
-            if (toTop && isStackVisible(PINNED_STACK_ID) && stack.mStackId != PINNED_STACK_ID) {
-                // The pinned stack is always the top most stack (always-on-top) when it is visible.
+            if (toTop && stack.mStackId != PINNED_STACK_ID
+                    && getStackById(PINNED_STACK_ID) != null) {
+                // The pinned stack is always the top most stack (always-on-top) when it is present.
                 TaskStack topStack = mChildren.get(topChildPosition);
                 if (topStack.mStackId != PINNED_STACK_ID) {
                     throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 3ce61f0..82416ec 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -26,7 +26,6 @@
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
 import android.graphics.Point;
-import android.graphics.PointF;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.IBinder;
@@ -123,6 +122,13 @@
                 mSnapAlgorithm.setMinimized(isMinimized);
             });
         }
+
+        @Override
+        public int getDisplayRotation() {
+            synchronized (mService.mWindowMap) {
+                return mDisplayInfo.rotation;
+            }
+        }
     }
 
     /**
@@ -147,7 +153,6 @@
 
     void onConfigurationChanged() {
         reloadResources();
-        notifyMovementBoundsChanged(false /* fromImeAdjustment */);
     }
 
     /**
@@ -222,56 +227,81 @@
      * @return the size of the PIP based on the given {@param aspectRatio}.
      */
     Size getSize(float aspectRatio) {
-        return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize,
-                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+        synchronized (mService.mWindowMap) {
+            return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize,
+                    mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+        }
     }
 
     /**
      * @return the default bounds to show the PIP when there is no active PIP.
      */
     Rect getDefaultBounds() {
-        final Rect insetBounds = new Rect();
-        getInsetBounds(insetBounds);
+        synchronized (mService.mWindowMap) {
+            final Rect insetBounds = new Rect();
+            getInsetBounds(insetBounds);
 
-        final Rect defaultBounds = new Rect();
-        final Size size = getSize(mDefaultAspectRatio);
-        Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
-                0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
-        return defaultBounds;
+            final Rect defaultBounds = new Rect();
+            final Size size = getSize(mDefaultAspectRatio);
+            Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
+                    0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
+            return defaultBounds;
+        }
+    }
+
+    /**
+     * In the case where the display rotation is changed but there is no stack, we can't depend on
+     * onTaskStackBoundsChanged() to be called.  But we still should update our known display info
+     * with the new state so that we can update SystemUI.
+     */
+    synchronized void onDisplayInfoChanged() {
+        mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
+        notifyMovementBoundsChanged(false /* fromImeAdjustment */);
     }
 
     /**
      * Updates the display info, calculating and returning the new stack and movement bounds in the
      * new orientation of the device if necessary.
      */
-    void onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
-        if (mDisplayInfo.equals(displayInfo)) {
-            return;
+    boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
+        synchronized (mService.mWindowMap) {
+            final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+            if (mDisplayInfo.equals(displayInfo)) {
+                // We are already in the right orientation, ignore
+                outBounds.setEmpty();
+                return false;
+            } else if (targetBounds.isEmpty()) {
+                // The stack is null, we are just initializing the stack, so just store the display
+                // info and ignore
+                mDisplayInfo.copyFrom(displayInfo);
+                outBounds.setEmpty();
+                return false;
+            }
+
+            mTmpRect.set(targetBounds);
+            final Rect postChangeStackBounds = mTmpRect;
+
+            // Calculate the snap fraction of the current stack along the old movement bounds
+            final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds);
+            final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds,
+                    preChangeMovementBounds);
+            mDisplayInfo.copyFrom(displayInfo);
+
+            // Calculate the stack bounds in the new orientation to the same same fraction along the
+            // rotated movement bounds.
+            final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
+                    false /* adjustForIme */);
+            mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
+                    snapFraction);
+            if (mIsMinimized) {
+                applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
+            }
+
+            notifyMovementBoundsChanged(false /* fromImeAdjustment */);
+
+            outBounds.set(postChangeStackBounds);
+            return true;
         }
-
-        mTmpRect.set(targetBounds);
-        final Rect postChangeStackBounds = mTmpRect;
-
-        // Calculate the snap fraction of the current stack along the old movement bounds
-        final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds);
-        final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds,
-                preChangeMovementBounds);
-        mDisplayInfo.copyFrom(displayInfo);
-
-        // Calculate the stack bounds in the new orientation to the same same fraction along the
-        // rotated movement bounds.
-        final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
-                false /* adjustForIme */);
-        mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
-                snapFraction);
-        if (mIsMinimized) {
-            applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
-        }
-
-        notifyMovementBoundsChanged(false /* fromImeAdjustment */);
-
-        outBounds.set(postChangeStackBounds);
     }
 
     /**
@@ -360,25 +390,27 @@
      * Notifies listeners that the PIP movement bounds have changed.
      */
     private void notifyMovementBoundsChanged(boolean fromImeAdjustement) {
-        if (mPinnedStackListener != null) {
-            try {
-                final Rect insetBounds = new Rect();
-                getInsetBounds(insetBounds);
-                final Rect normalBounds = getDefaultBounds();
-                if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
-                    transformBoundsToAspectRatio(normalBounds, mAspectRatio);
+        synchronized (mService.mWindowMap) {
+            if (mPinnedStackListener != null) {
+                try {
+                    final Rect insetBounds = new Rect();
+                    getInsetBounds(insetBounds);
+                    final Rect normalBounds = getDefaultBounds();
+                    if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
+                        transformBoundsToAspectRatio(normalBounds, mAspectRatio);
+                    }
+                    final Rect animatingBounds = mTmpAnimatingBoundsRect;
+                    final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
+                    if (pinnedStack != null) {
+                        pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
+                    } else {
+                        animatingBounds.set(normalBounds);
+                    }
+                    mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
+                            animatingBounds, fromImeAdjustement, mDisplayInfo.rotation);
+                } catch (RemoteException e) {
+                    Slog.e(TAG_WM, "Error delivering actions changed event.", e);
                 }
-                final Rect animatingBounds = mTmpAnimatingBoundsRect;
-                final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
-                if (pinnedStack != null) {
-                    pinnedStack.getAnimatingBounds(animatingBounds);
-                } else {
-                    animatingBounds.set(normalBounds);
-                }
-                mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
-                        animatingBounds, fromImeAdjustement);
-            } catch (RemoteException e) {
-                Slog.e(TAG_WM, "Error delivering actions changed event.", e);
             }
         }
     }
@@ -387,11 +419,13 @@
      * @return the bounds on the screen that the PIP can be visible in.
      */
     private void getInsetBounds(Rect outRect) {
-        mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth,
-                mDisplayInfo.logicalHeight, mTmpInsets);
-        outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
-                mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
-                mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
+        synchronized (mService.mWindowMap) {
+            mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth,
+                    mDisplayInfo.logicalHeight, mTmpInsets);
+            outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
+                    mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
+                    mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
+        }
     }
 
     /**
@@ -399,7 +433,9 @@
      *         controller.
      */
     private Rect getMovementBounds(Rect stackBounds) {
-        return getMovementBounds(stackBounds, true /* adjustForIme */);
+        synchronized (mService.mWindowMap) {
+            return getMovementBounds(stackBounds, true /* adjustForIme */);
+        }
     }
 
     /**
@@ -407,23 +443,27 @@
      *         controller.
      */
     private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
-        final Rect movementBounds = new Rect();
-        getInsetBounds(movementBounds);
+        synchronized (mService.mWindowMap) {
+            final Rect movementBounds = new Rect();
+            getInsetBounds(movementBounds);
 
-        // Apply the movement bounds adjustments based on the current state
-        mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
-                (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
-        return movementBounds;
+            // Apply the movement bounds adjustments based on the current state
+            mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
+                    (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
+            return movementBounds;
+        }
     }
 
     /**
      * Applies the minimized offsets to the given stack bounds.
      */
     private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
-        mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
-        mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets);
-        mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
-                mStableInsets);
+        synchronized (mService.mWindowMap) {
+            mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+            mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets);
+            mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
+                    mStableInsets);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
index 0145454..5b9c16c 100644
--- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
@@ -17,6 +17,10 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
+import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
+import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
+import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
 
 import android.app.RemoteAction;
 import android.graphics.Rect;
@@ -32,44 +36,61 @@
 
     private Rect mTmpBoundsRect = new Rect();
 
-    public PinnedStackWindowController(int stackId, StackWindowListener listener, int displayId,
-            boolean onTop, Rect outBounds) {
+    public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener,
+            int displayId, boolean onTop, Rect outBounds) {
         super(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
     }
 
     /**
      * Animates the pinned stack.
      */
-    public void animateResizePinnedStack(Rect sourceBounds, Rect destBounds,
-            int animationDuration) {
+    public void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds,
+            int animationDuration, boolean schedulePipModeChangedOnAnimationEnd) {
         synchronized (mWindowMap) {
             if (mContainer == null) {
                 throw new IllegalArgumentException("Pinned stack container not found :(");
             }
 
-            // Get non-null fullscreen bounds if the bounds are null
-            final boolean moveToFullscreen = destBounds == null;
-            destBounds = getPinnedStackAnimationBounds(destBounds);
+            // Get the from-bounds
+            final Rect fromBounds = new Rect();
+            mContainer.getBounds(fromBounds);
 
-            // If the bounds are truly null, then there was no fullscreen stack at this time, so
-            // animate this to the full display bounds
-            final Rect toBounds;
-            if (destBounds == null) {
-                toBounds = new Rect();
-                mContainer.getDisplayContent().getLogicalDisplayRect(toBounds);
-            } else {
-                toBounds = destBounds;
+            // Get non-null fullscreen to-bounds for animating if the bounds are null
+            @SchedulePipModeChangedState int schedulePipModeChangedState =
+                NO_PIP_MODE_CHANGED_CALLBACKS;
+            final boolean toFullscreen = toBounds == null;
+            if (toFullscreen) {
+                if (schedulePipModeChangedOnAnimationEnd) {
+                    throw new IllegalArgumentException("Should not defer scheduling PiP mode"
+                            + " change on animation to fullscreen.");
+                }
+                schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
+
+                mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpBoundsRect);
+                if (!mTmpBoundsRect.isEmpty()) {
+                    // If there is a fullscreen bounds, use that
+                    toBounds = new Rect(mTmpBoundsRect);
+                } else {
+                    // Otherwise, use the display bounds
+                    toBounds = new Rect();
+                    mContainer.getDisplayContent().getLogicalDisplayRect(toBounds);
+                }
+            } else if (schedulePipModeChangedOnAnimationEnd) {
+                schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
             }
 
-            final Rect originalBounds = new Rect();
-            mContainer.getBounds(originalBounds);
-            mContainer.setAnimatingBounds(sourceBounds, toBounds);
+            mContainer.setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen);
+
+            final Rect finalToBounds = toBounds;
+            final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
+                schedulePipModeChangedState;
             UiThread.getHandler().post(() -> {
                 if (mContainer == null) {
                     return;
                 }
-                mService.mBoundsAnimationController.animateBounds(mContainer, originalBounds,
-                        toBounds, animationDuration, moveToFullscreen);
+                mService.mBoundsAnimationController.animateBounds(mContainer, fromBounds,
+                        finalToBounds, animationDuration, finalSchedulePipModeChangedState,
+                        toFullscreen);
             });
         }
     }
@@ -84,15 +105,17 @@
             }
 
             final int displayId = mContainer.getDisplayContent().getDisplayId();
-            final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
+            final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio,
+                    true /* useExistingStackBounds */);
             final Rect targetBounds = new Rect();
-            mContainer.getAnimatingBounds(targetBounds);
+            mContainer.getAnimationOrCurrentBounds(targetBounds);
             final PinnedStackController pinnedStackController =
                     mContainer.getDisplayContent().getPinnedStackController();
 
             if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) {
                 if (!toBounds.equals(targetBounds)) {
-                    animateResizePinnedStack(null /* sourceBounds */, toBounds, -1 /* duration */);
+                    animateResizePinnedStack(toBounds, null /* sourceHintBounds */,
+                            -1 /* duration */, false /* schedulePipModeChangedOnAnimationEnd */);
                 }
                 pinnedStackController.setAspectRatio(
                         pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
@@ -115,21 +138,42 @@
     }
 
     /**
-     * @return whether the bounds are currently animating to fullscreen.
+     * @return whether the multi-window mode change should be deferred as a part of a transition
+     * from fullscreen to non-fullscreen bounds.
      */
-    public boolean isBoundsAnimatingToFullscreen() {
-        return mContainer.isBoundsAnimatingToFullscreen();
+    public boolean deferScheduleMultiWindowModeChanged() {
+        synchronized(mWindowMap) {
+            return mContainer.deferScheduleMultiWindowModeChanged();
+        }
     }
 
     /**
-     * Checks the {@param bounds} and retirms non-null fullscreen bounds for the pinned stack
-     * animation if necessary.
+     * @return whether the bounds are currently animating to fullscreen.
      */
-    private Rect getPinnedStackAnimationBounds(Rect bounds) {
-        mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpBoundsRect);
-        if (bounds == null && !mTmpBoundsRect.isEmpty()) {
-            bounds = new Rect(mTmpBoundsRect);
+    public boolean isAnimatingBoundsToFullscreen() {
+        synchronized (mWindowMap) {
+            return mContainer.isAnimatingBoundsToFullscreen();
         }
-        return bounds;
+    }
+
+    /**
+     * @return whether the stack can be resized from the bounds animation.
+     */
+    public boolean pinnedStackResizeDisallowed() {
+        synchronized (mWindowMap) {
+            return mContainer.pinnedStackResizeDisallowed();
+        }
+    }
+
+    /**
+     * The following calls are made from WM to AM.
+     */
+
+    /** Calls directly into activity manager so window manager lock shouldn't held. */
+    public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
+        if (mListener != null) {
+            PinnedStackWindowListener listener = (PinnedStackWindowListener) mListener;
+            listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
new file mode 100644
index 0000000..12b9c1f
--- /dev/null
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Rect;
+
+/**
+ * Interface used by the creator of {@link PinnedStackWindowController} to listen to changes with
+ * the stack container.
+ */
+public interface PinnedStackWindowListener extends StackWindowListener {
+
+    /**
+     * Called when the stack container pinned stack animation will change the picture-in-picture
+     * mode. This is a direct call into ActivityManager.
+     */
+    default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {}
+}
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index bf024cf..b927e67 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -368,13 +368,6 @@
         }
     }
 
-    /** Calls directly into activity manager so window manager lock shouldn't held. */
-    void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {
-        if (mListener != null) {
-            mListener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
-        }
-    }
-
     void requestResize(Rect bounds) {
         mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
     }
diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/services/core/java/com/android/server/wm/StackWindowListener.java
index a55f9df..c763c17 100644
--- a/services/core/java/com/android/server/wm/StackWindowListener.java
+++ b/services/core/java/com/android/server/wm/StackWindowListener.java
@@ -26,10 +26,4 @@
 
     /** Called when the stack container would like its controller to resize. */
     void requestResize(Rect bounds);
-
-    /**
-     * Called when the stack container pinned stack animation will change the picture-in-picture
-     * mode. This is a direct call into ActivityManager.
-     */
-    default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds) {}
 }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d61bbd0..4262d12 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -595,8 +595,7 @@
      * we will have a jump at the end.
      */
     boolean isFloating() {
-        return StackId.tasksAreFloating(mStack.mStackId)
-            && !mStack.isBoundsAnimatingToFullscreen();
+        return StackId.tasksAreFloating(mStack.mStackId) && !mStack.isAnimatingBoundsToFullscreen();
     }
 
     WindowState getTopVisibleAppMainWindow() {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 1a67ac7..d141f7c 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -56,7 +56,7 @@
 import java.io.PrintWriter;
 
 public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLayerUser,
-        BoundsAnimationController.AnimateBoundsUser {
+        BoundsAnimationTarget {
     /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
      * restrict IME adjustment so that a min portion of top stack remains visible.*/
     private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
@@ -77,6 +77,7 @@
     /** For comparison with DisplayContent bounds. */
     private Rect mTmpRect = new Rect();
     private Rect mTmpRect2 = new Rect();
+    private Rect mTmpRect3 = new Rect();
 
     /** Content limits relative to the DisplayContent this sits in. */
     private Rect mBounds = new Rect();
@@ -125,9 +126,13 @@
     // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
     // would otherwise apply while resizing, while resizing in the bounds animating mode.
     private boolean mBoundsAnimating = false;
+    // Set when an animation has been requested but has not yet started from the UI thread. This is
+    // cleared when the animation actually starts.
+    private boolean mBoundsAnimatingRequested = false;
     private boolean mBoundsAnimatingToFullscreen = false;
+    private boolean mCancelCurrentBoundsAnimation = false;
     private Rect mBoundsAnimationTarget = new Rect();
-    private Rect mBoundsAnimationSourceBounds = new Rect();
+    private Rect mBoundsAnimationSourceHintBounds = new Rect();
 
     // Temporary storage for the new bounds that should be used after the configuration change.
     // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
@@ -262,12 +267,6 @@
 
         if (mDisplayContent != null) {
             mDisplayContent.mDimLayerController.updateDimLayer(this);
-            if (mStackId == PINNED_STACK_ID) {
-                // Update the bounds based on any changes to the display info
-                getAnimatingBounds(mTmpRect2);
-                mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(mTmpRect2,
-                        bounds);
-            }
             mAnimationBackgroundSurface.setBounds(bounds);
         }
 
@@ -320,40 +319,45 @@
     }
 
     /**
-     * Sets the bounds animation target bounds.  This can't currently be done in onAnimationStart()
-     * since that is started on the UiThread.
+     * Sets the bounds animation target bounds ahead of an animation.  This can't currently be done
+     * in onAnimationStart() since that is started on the UiThread.
      */
-    void setAnimatingBounds(Rect sourceBounds, Rect destBounds) {
-        if (sourceBounds != null) {
-            mBoundsAnimationSourceBounds.set(sourceBounds);
-        } else {
-            mBoundsAnimationSourceBounds.setEmpty();
-        }
+    void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds, boolean toFullscreen) {
+        mBoundsAnimatingRequested = true;
+        mBoundsAnimatingToFullscreen = toFullscreen;
         if (destBounds != null) {
             mBoundsAnimationTarget.set(destBounds);
         } else {
             mBoundsAnimationTarget.setEmpty();
         }
-    }
-
-    /**
-     * @return the source bounds for the bounds animation.
-     */
-    void getAnimatingSourceBounds(Rect outBounds) {
-        if (!mBoundsAnimationSourceBounds.isEmpty()) {
-            outBounds.set(mBoundsAnimationSourceBounds);
-            return;
+        if (sourceHintBounds != null) {
+            mBoundsAnimationSourceHintBounds.set(sourceHintBounds);
+        } else {
+            mBoundsAnimationSourceHintBounds.setEmpty();
         }
-        outBounds.setEmpty();
     }
 
     /**
-     * @return the bounds that the task stack is currently being animated towards, or the current
-     *         stack bounds if there is no animation in progress.
+     * @return the final bounds for the bounds animation.
      */
-    void getAnimatingBounds(Rect outBounds) {
-        if (!mBoundsAnimationTarget.isEmpty()) {
-            outBounds.set(mBoundsAnimationTarget);
+    void getFinalAnimationBounds(Rect outBounds) {
+        outBounds.set(mBoundsAnimationTarget);
+    }
+
+    /**
+     * @return the final source bounds for the bounds animation.
+     */
+    void getFinalAnimationSourceHintBounds(Rect outBounds) {
+        outBounds.set(mBoundsAnimationSourceHintBounds);
+    }
+
+    /**
+     * @return the final animation bounds if the task stack is currently being animated, or the
+     *         current stack bounds otherwise.
+     */
+    void getAnimationOrCurrentBounds(Rect outBounds) {
+        if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
+            getFinalAnimationBounds(outBounds);
             return;
         }
         getBounds(outBounds);
@@ -398,6 +402,24 @@
             // as it's going away soon anyway.
             return false;
         }
+
+        if (mStackId == PINNED_STACK_ID) {
+            getAnimationOrCurrentBounds(mTmpRect2);
+            boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+                    mTmpRect2, mTmpRect3);
+            if (updated) {
+                mBoundsAfterRotation.set(mTmpRect3);
+
+                // Once we've set the bounds based on the rotation of the old bounds in the new
+                // orientation, clear the animation target bounds since they are obsolete, and
+                // cancel any currently running animations
+                mBoundsAnimationTarget.setEmpty();
+                mBoundsAnimationSourceHintBounds.setEmpty();
+                mCancelCurrentBoundsAnimation = true;
+                return true;
+            }
+        }
+
         final int newRotation = getDisplayInfo().rotation;
         final int newDensity = getDisplayInfo().logicalDensityDpi;
 
@@ -413,20 +435,6 @@
             return false;
         }
 
-        if (StackId.tasksAreFloating(mStackId)) {
-            // Update stack bounds again since the display info has changed since updateDisplayInfo,
-            // however, for floating tasks, we don't need to apply the new rotation to the bounds,
-            // we can just update and return them here
-            setBounds(mBounds);
-            mBoundsAfterRotation.set(mBounds);
-
-            // Once we've set the bounds based on the rotation of the old bounds in the new
-            // orientation, clear the animation target bounds since they are obsolete
-            mBoundsAnimationTarget.setEmpty();
-            mBoundsAnimationSourceBounds.setEmpty();
-            return true;
-        }
-
         mTmpRect2.set(mBounds);
         mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
         switch (mStackId) {
@@ -692,6 +700,14 @@
             getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
                     mDisplayContent.mDividerControllerLocked.getContentWidth(),
                     dockedOnTopOrLeft);
+        } else if (mStackId == PINNED_STACK_ID) {
+            // Update the bounds based on any changes to the display info
+            getAnimationOrCurrentBounds(mTmpRect2);
+            boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
+                    mTmpRect2, mTmpRect3);
+            if (updated) {
+                bounds = new Rect(mTmpRect3);
+            }
         }
 
         updateDisplayInfo(bounds);
@@ -1443,23 +1459,16 @@
         }
     }
 
-    @Override  // AnimatesBounds
-    public boolean setSize(Rect bounds) {
+    public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
+        // Hold the lock since this is called from the BoundsAnimator running on the UiThread
         synchronized (mService.mWindowMap) {
-            if (mDisplayContent == null) {
+            if (mCancelCurrentBoundsAnimation) {
                 return false;
             }
         }
-        try {
-            mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false, -1);
-        } catch (RemoteException e) {
-        }
-        return true;
-    }
 
-    public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
         try {
-            mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
+            mService.mActivityManager.resizePinnedStack(stackBounds, tempTaskBounds);
         } catch (RemoteException e) {
             // I don't believe you.
         }
@@ -1467,10 +1476,12 @@
     }
 
     @Override  // AnimatesBounds
-    public void onAnimationStart(boolean toFullscreen) {
+    public void onAnimationStart(boolean schedulePipModeChangedCallback) {
+        // Hold the lock since this is called from the BoundsAnimator running on the UiThread
         synchronized (mService.mWindowMap) {
+            mBoundsAnimatingRequested = false;
             mBoundsAnimating = true;
-            mBoundsAnimatingToFullscreen = toFullscreen;
+            mCancelCurrentBoundsAnimation = false;
         }
 
         if (mStackId == PINNED_STACK_ID) {
@@ -1479,40 +1490,63 @@
             } catch (RemoteException e) {
                 // I don't believe you...
             }
+
+            final PinnedStackWindowController controller =
+                    (PinnedStackWindowController) getController();
+            if (schedulePipModeChangedCallback && controller != null) {
+                // We need to schedule the PiP mode change after the animation down, so use the
+                // final bounds
+                controller.updatePictureInPictureModeForPinnedStackAnimation(null);
+            }
         }
     }
 
     @Override  // AnimatesBounds
-    public void updatePictureInPictureMode(Rect targetStackBounds) {
-        final StackWindowController controller = getController();
-        if (controller != null) {
-            controller.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds);
-        }
-    }
-
-    @Override  // AnimatesBounds
-    public void onAnimationEnd() {
+    public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
+            boolean moveToFullscreen) {
+        // Hold the lock since this is called from the BoundsAnimator running on the UiThread
         synchronized (mService.mWindowMap) {
             mBoundsAnimating = false;
             mService.requestTraversal();
         }
 
         if (mStackId == PINNED_STACK_ID) {
+            final PinnedStackWindowController controller =
+                    (PinnedStackWindowController) getController();
+            if (schedulePipModeChangedCallback && controller != null) {
+                // We need to schedule the PiP mode change after the animation down, so use the
+                // final bounds
+                controller.updatePictureInPictureModeForPinnedStackAnimation(
+                        mBoundsAnimationTarget);
+            }
+
+            // Update to the final bounds if requested. This is done here instead of in the bounds
+            // animator to allow us to coordinate this after we notify the PiP mode changed
+            if (finalStackSize != null) {
+                setPinnedStackSize(finalStackSize, null);
+            }
+
             try {
                 mService.mActivityManager.notifyPinnedStackAnimationEnded();
+                if (moveToFullscreen) {
+                    mService.mActivityManager.moveTasksToFullscreenStack(mStackId,
+                            true /* onTop */);
+                }
             } catch (RemoteException e) {
                 // I don't believe you...
             }
         }
     }
 
-    @Override
-    public void moveToFullscreen() {
-        try {
-            mService.mActivityManager.moveTasksToFullscreenStack(mStackId, true);
-        } catch (RemoteException e) {
-            e.printStackTrace();
+    /**
+     * @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen
+     *         bounds and we have a deferred PiP mode changed callback set with the animation.
+     */
+    public boolean deferScheduleMultiWindowModeChanged() {
+        if (mStackId == PINNED_STACK_ID) {
+            return (mBoundsAnimatingRequested || mBoundsAnimating);
         }
+        return false;
     }
 
     public boolean hasMovementAnimations() {
@@ -1523,14 +1557,21 @@
         return mBoundsAnimating;
     }
 
-    public boolean getBoundsAnimating() {
+    public boolean isAnimatingBounds() {
         return mBoundsAnimating;
     }
 
-    public boolean isBoundsAnimatingToFullscreen() {
+    public boolean isAnimatingBoundsToFullscreen() {
         return mBoundsAnimating && mBoundsAnimatingToFullscreen;
     }
 
+    public boolean pinnedStackResizeDisallowed() {
+        if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
+            return true;
+        }
+        return false;
+    }
+
     /** Returns true if a removal action is still being deferred. */
     boolean checkCompleteDeferredRemoval() {
         if (isAnimating()) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0f4707e..252b4d4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -31,7 +31,6 @@
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.THREAD_PRIORITY_DISPLAY;
 import static android.os.Process.myPid;
-import static android.os.Process.myTid;
 import static android.os.UserHandle.USER_NULL;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.DOCKED_INVALID;
@@ -148,7 +147,6 @@
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
@@ -2758,7 +2756,12 @@
         mDockedStackCreateBounds = bounds;
     }
 
-    public Rect getPictureInPictureBounds(int displayId, float aspectRatio) {
+    /**
+     * @param useExistingStackBounds Apply {@param aspectRatio} to the existing target stack bounds
+     *                               if possible
+     */
+    public Rect getPictureInPictureBounds(int displayId, float aspectRatio,
+            boolean useExistingStackBounds) {
         synchronized (mWindowMap) {
             if (!mSupportsPictureInPicture) {
                 return null;
@@ -2773,11 +2776,11 @@
             final PinnedStackController pinnedStackController =
                     displayContent.getPinnedStackController();
             final TaskStack stack = displayContent.getStackById(PINNED_STACK_ID);
-            if (stack != null) {
+            if (stack != null && useExistingStackBounds) {
                 // If the stack exists, then use its final bounds to calculate the new aspect ratio
                 // bounds.
                 stackBounds = new Rect();
-                stack.getAnimatingBounds(stackBounds);
+                stack.getAnimationOrCurrentBounds(stackBounds);
             } else {
                 // Otherwise, just calculate the aspect ratio bounds from the default bounds
                 stackBounds = pinnedStackController.getDefaultBounds();
@@ -7264,13 +7267,16 @@
 
         @Override
         public void updateInputMethodWindowStatus(@NonNull IBinder imeToken,
-                boolean imeWindowVisible, @Nullable IBinder targetWindowToken) {
+                boolean imeWindowVisible, boolean dismissImeOnBackKeyPressed,
+                @Nullable IBinder targetWindowToken) {
             // TODO (b/34628091): Use this method to address the window animation issue.
             if (DEBUG_INPUT_METHOD) {
                 Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken
+                        + " dismissImeOnBackKeyPressed=" + dismissImeOnBackKeyPressed
                         + " imeWindowVisible=" + imeWindowVisible
                         + " targetWindowToken=" + targetWindowToken);
             }
+            mPolicy.setDismissImeOnBackKeyPressed(dismissImeOnBackKeyPressed);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8098eea..9555c8d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -50,6 +50,7 @@
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -1089,7 +1090,7 @@
         // notify the client of frame changes in this case. Not only is it a lot of churn, but
         // the frame may not correspond to the surface size or the onscreen area at various
         // phases in the animation, and the client will become sad and confused.
-        if (task != null && task.mStack.getBoundsAnimating()) {
+        if (task != null && task.mStack.isAnimatingBounds()) {
             return;
         }
 
@@ -4364,9 +4365,12 @@
         // When we change the Surface size, in scenarios which may require changing
         // the surface position in sync with the resize, we use a preserved surface
         // so we can freeze it while waiting for the client to report draw on the newly
-        // sized surface.
+        // sized surface.  Don't preserve surfaces if the insets change while animating the pinned
+        // stack since it can lead to issues if a new surface is created while calculating the
+        // scale for the animation using the source hint rect
+        // (see WindowStateAnimator#setSurfaceBoundariesLocked()).
         if (isDragResizeChanged() || isResizedWhileNotDragResizing()
-                || surfaceInsetsChanging()) {
+                || (surfaceInsetsChanging() && !inPinnedWorkspace())) {
             mLastSurfaceInsets.set(mAttrs.surfaceInsets);
 
             setDragResizing();
@@ -4411,4 +4415,14 @@
             nowGone = true;
         }
     }
+
+    boolean usesRelativeZOrdering() {
+        if (!isChildWindow()) {
+            return false;
+        } else if (mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) {
+            return true;
+        } else {
+            return false;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a7f6db1..a2889b1 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -714,7 +714,16 @@
         }
 
         // Start a new transaction and apply position & offset.
-        mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, getLayerStack(), mAnimLayer);
+
+        mService.openSurfaceTransaction();
+        try {
+            mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, false);
+            mSurfaceController.setLayerStackInTransaction(getLayerStack());
+            mSurfaceController.setLayer(mAnimLayer);
+        } finally {
+            mService.closeSurfaceTransaction();
+        }
+
         mLastHidden = true;
 
         if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
@@ -1351,11 +1360,11 @@
             int posX = mTmpSize.left;
             int posY = mTmpSize.top;
             task.mStack.getDimBounds(mTmpStackBounds);
-            task.mStack.getAnimatingSourceBounds(mTmpSourceBounds);
+            task.mStack.getFinalAnimationSourceHintBounds(mTmpSourceBounds);
             if (!mTmpSourceBounds.isEmpty()) {
                 // Get the final target stack bounds, if we are not animating, this is just the
                 // current stack bounds
-                task.mStack.getAnimatingBounds(mTmpAnimatingBounds);
+                task.mStack.getFinalAnimationBounds(mTmpAnimatingBounds);
 
                 // Calculate the current progress and interpolate the difference between the target
                 // and source bounds
@@ -1521,12 +1530,13 @@
                     + "," + mDsDy + "*" + w.mVScale + "]", false);
 
             boolean prepared =
-                mSurfaceController.prepareToShowInTransaction(mShownAlpha, mAnimLayer,
+                mSurfaceController.prepareToShowInTransaction(mShownAlpha,
                         mDsDx * w.mHScale * mExtraHScale,
                         mDtDx * w.mVScale * mExtraVScale,
                         mDtDy * w.mHScale * mExtraHScale,
                         mDsDy * w.mVScale * mExtraVScale,
                         recoveringMemory);
+            mSurfaceController.setLayer(mAnimLayer);
 
             if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
                 if (showSurfaceRobustlyLocked()) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index adf4501..edbdf8b 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -163,32 +163,6 @@
         }
     }
 
-    void setPositionAndLayer(float left, float top, int layerStack, int layer) {
-        mService.openSurfaceTransaction();
-        try {
-            mSurfaceX = left;
-            mSurfaceY = top;
-
-            try {
-                if (SHOW_TRANSACTIONS) logSurface(
-                        "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
-                mSurfaceControl.setPosition(left, top);
-                mSurfaceControl.setLayerStack(layerStack);
-
-                mSurfaceControl.setLayer(layer);
-                mSurfaceControl.setAlpha(0);
-                setShown(false);
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Error creating surface in " + this, e);
-                mAnimator.reclaimSomeSurfaceMemory("create-init", true);
-            }
-        } finally {
-            mService.closeSurfaceTransaction();
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                    "<<< CLOSE TRANSACTION setPositionAndLayer");
-        }
-    }
-
     void destroyInTransaction() {
         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
             Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
@@ -269,7 +243,15 @@
         if (mSurfaceControl != null) {
             mService.openSurfaceTransaction();
             try {
-                mSurfaceControl.setLayer(layer);
+                if (mAnimator.mWin.usesRelativeZOrdering()) {
+                    mSurfaceControl.setRelativeLayer(
+                            mAnimator.mWin.getParentWindow()
+                            .mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
+                            -1);
+                } else {
+                    mSurfaceLayer = layer;
+                    mSurfaceControl.setLayer(layer);
+                }
             } finally {
                 mService.closeSurfaceTransaction();
             }
@@ -363,15 +345,13 @@
         return false;
     }
 
-    boolean prepareToShowInTransaction(float alpha, int layer,
+    boolean prepareToShowInTransaction(float alpha,
             float dsdx, float dtdx, float dsdy,
             float dtdy, boolean recoveringMemory) {
         if (mSurfaceControl != null) {
             try {
                 mSurfaceAlpha = alpha;
                 mSurfaceControl.setAlpha(alpha);
-                mSurfaceLayer = layer;
-                mSurfaceControl.setLayer(layer);
                 mLastDsdx = dsdx;
                 mLastDtdx = dtdx;
                 mLastDsdy = dsdy;
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 23637de..3e167e4 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -18,6 +18,8 @@
     $(LOCAL_REL_DIR)/com_android_server_location_ContextHubService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_location_GnssLocationProvider.cpp \
     $(LOCAL_REL_DIR)/com_android_server_power_PowerManagerService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_radio_RadioService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_radio_Tuner.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SerialService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_SyntheticPasswordManager.cpp \
     $(LOCAL_REL_DIR)/com_android_server_storage_AppFuseBridge.cpp \
@@ -80,6 +82,8 @@
     libutils \
     libhwui \
     android.hardware.audio.common@2.0 \
+    android.hardware.broadcastradio@1.0 \
+    android.hardware.broadcastradio@1.1 \
     android.hardware.contexthub@1.0 \
     android.hardware.gnss@1.0 \
     android.hardware.ir@1.0 \
diff --git a/services/core/jni/com_android_server_location_ContextHubService.cpp b/services/core/jni/com_android_server_location_ContextHubService.cpp
index d834e25..20466eb 100644
--- a/services/core/jni/com_android_server_location_ContextHubService.cpp
+++ b/services/core/jni/com_android_server_location_ContextHubService.cpp
@@ -1129,6 +1129,8 @@
         if (appInstanceHandle == OS_APP_ID) {
             if (msgType == CONTEXT_HUB_LOAD_APP) {
                 result = sendLoadNanoAppRequest(hubId, data, dataBufferLength);
+            } else if (msgType == CONTEXT_HUB_QUERY_APPS) {
+                result = db.hubInfo.contextHub->queryApps(hubId);
             } else {
                 ALOGD("Dropping OS addresses message of type - %" PRIu32, msgType);
                 result = Result::BAD_PARAMS;
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 86662b9..74ecd11 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -68,12 +68,15 @@
 
 using android::OK;
 using android::sp;
+using android::wp;
 using android::status_t;
 using android::String16;
 
 using android::hardware::Return;
 using android::hardware::Void;
 using android::hardware::hidl_vec;
+using android::hardware::hidl_death_recipient;
+using android::hidl::base::V1_0::IBase;
 
 using android::hardware::gnss::V1_0::IAGnss;
 using android::hardware::gnss::V1_0::IAGnssCallback;
@@ -97,7 +100,18 @@
 using android::hardware::gnss::V1_0::IGnssXtra;
 using android::hardware::gnss::V1_0::IGnssXtraCallback;
 
+struct GnssDeathRecipient : virtual public hidl_death_recipient
+{
+    // hidl_death_recipient interface
+    virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override {
+      // TODO(gomo): implement a better death recovery mechanism without
+      // crashing system server process as described in go//treble-gnss-death
+      LOG_ALWAYS_FATAL("Abort due to IGNSS hidl service failure,"
+            " restarting system server");
+    }
+};
 
+sp<GnssDeathRecipient> gnssHalDeathRecipient = nullptr;
 sp<IGnss> gnssHal = nullptr;
 sp<IGnssXtra> gnssXtraIface = nullptr;
 sp<IAGnssRil> agnssRilIface = nullptr;
@@ -1038,6 +1052,18 @@
     // TODO(b/31632518)
     gnssHal = IGnss::getService();
     if (gnssHal != nullptr) {
+      gnssHalDeathRecipient = new GnssDeathRecipient();
+      hardware::Return<bool> linked = gnssHal->linkToDeath(
+          gnssHalDeathRecipient, /*cookie*/ 0);
+        if (!linked.isOk()) {
+            ALOGE("Transaction error in linking to GnssHAL death: %s",
+                    linked.description().c_str());
+        } else if (!linked) {
+            ALOGW("Unable to link to GnssHal death notifications");
+        } else {
+            ALOGD("Link to death notification successful");
+        }
+
         auto gnssXtra = gnssHal->getExtensionXtra();
         if (!gnssXtra.isOk()) {
             ALOGD("Unable to get a handle to Xtra");
diff --git a/services/core/jni/com_android_server_radio_RadioService.cpp b/services/core/jni/com_android_server_radio_RadioService.cpp
new file mode 100644
index 0000000..34dbf0c
--- /dev/null
+++ b/services/core/jni/com_android_server_radio_RadioService.cpp
@@ -0,0 +1,173 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "radio.RadioService.jni"
+#define LOG_NDEBUG 0
+
+#include "com_android_server_radio_RadioService.h"
+
+#include "com_android_server_radio_Tuner.h"
+
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
+#include <core_jni_helpers.h>
+#include <utils/Log.h>
+#include <JNIHelp.h>
+
+namespace android {
+
+using hardware::Return;
+using hardware::hidl_vec;
+
+namespace V1_0 = hardware::broadcastradio::V1_0;
+namespace V1_1 = hardware::broadcastradio::V1_1;
+
+using V1_0::Class;
+using V1_0::IBroadcastRadio;
+using V1_0::Result;
+
+using V1_0::BandConfig;
+using V1_0::ProgramInfo;
+using V1_0::MetaData;
+using V1_0::ITuner;
+
+static Mutex gContextMutex;
+
+static jclass gTunerClass;
+static jmethodID gTunerCstor;
+
+static jclass gServiceClass;
+
+struct ServiceContext {
+    ServiceContext() {}
+
+    sp<IBroadcastRadio> mModule;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(ServiceContext);
+};
+
+
+/**
+ * Always lock gContextMutex when using native context.
+ */
+static ServiceContext& getNativeContext(jlong nativeContextHandle) {
+    auto nativeContext = reinterpret_cast<ServiceContext*>(nativeContextHandle);
+    LOG_ALWAYS_FATAL_IF(nativeContext == nullptr, "Native context not initialized");
+    return *nativeContext;
+}
+
+static jlong nativeInit(JNIEnv *env, jobject obj) {
+    ALOGV("nativeInit()");
+    AutoMutex _l(gContextMutex);
+
+    auto nativeContext = new ServiceContext();
+    static_assert(sizeof(jlong) >= sizeof(nativeContext), "jlong is smaller than a pointer");
+    return reinterpret_cast<jlong>(nativeContext);
+}
+
+static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) {
+    ALOGV("nativeFinalize()");
+    AutoMutex _l(gContextMutex);
+
+    auto ctx = reinterpret_cast<ServiceContext*>(nativeContext);
+    delete ctx;
+}
+
+static sp<IBroadcastRadio> getModule(jlong nativeContext) {
+    ALOGV("getModule()");
+    AutoMutex _l(gContextMutex);
+    auto& ctx = getNativeContext(nativeContext);
+
+    if (ctx.mModule != nullptr) {
+        return ctx.mModule;
+    }
+
+    // TODO(b/36863239): what about other HAL implementations?
+    auto factory = V1_0::IBroadcastRadioFactory::getService();
+    if (factory == nullptr) {
+        ALOGE("Can't retrieve radio HAL implementation");
+        return nullptr;
+    }
+
+    sp<IBroadcastRadio> module = nullptr;
+    // TODO(b/36863239): not only AM/FM
+    factory->connectModule(Class::AM_FM, [&](Result retval, const sp<IBroadcastRadio>& result) {
+        if (retval == Result::OK) {
+            module = result;
+        }
+    });
+
+    ALOGE_IF(module == nullptr, "Couldn't connect module");
+    ctx.mModule = module;
+    return module;
+}
+
+static jobject openTunerNative(JNIEnv *env, jobject obj, long nativeContext, bool withAudio) {
+    ALOGV("openTunerNative()");
+
+    auto module = getModule(nativeContext);
+    if (module == nullptr) {
+        return nullptr;
+    }
+
+    jobject tuner = env->NewObject(gTunerClass, gTunerCstor);
+    if (tuner == nullptr) {
+        ALOGE("Unable to create new tuner object.");
+        return nullptr;
+    }
+
+    BandConfig bandConfig = {};  // TODO(b/36863239): convert from parameters
+    auto tunerCb = android_server_radio_Tuner_getCallback(env, tuner);
+    Result halResult;
+    sp<ITuner> halTuner = nullptr;
+
+    auto hidlResult = module->openTuner(bandConfig, withAudio, tunerCb,
+            [&](Result result, const sp<ITuner>& tuner) {
+                halResult = result;
+                halTuner = tuner;
+            });
+    if (!hidlResult.isOk() || halResult != Result::OK || halTuner == nullptr) {
+        ALOGE("Couldn't open tuner");
+        ALOGE_IF(hidlResult.isOk(), "halResult = %d", halResult);
+        ALOGE_IF(!hidlResult.isOk(), "hidlResult = %s", hidlResult.description().c_str());
+        env->DeleteLocalRef(tuner);
+        return nullptr;
+    }
+
+    android_server_radio_Tuner_setHalTuner(env, tuner, halTuner);
+    return tuner;
+}
+
+static const JNINativeMethod gRadioServiceMethods[] = {
+    { "nativeInit", "()J", (void*)nativeInit },
+    { "nativeFinalize", "(J)V", (void*)nativeFinalize },
+    { "openTunerNative", "(JZ)Lcom/android/server/radio/Tuner;", (void*)openTunerNative },
+};
+
+void register_android_server_radio_RadioService(JNIEnv *env) {
+    auto tunerClass = FindClassOrDie(env, "com/android/server/radio/Tuner");
+    gTunerClass = MakeGlobalRefOrDie(env, tunerClass);
+    gTunerCstor = GetMethodIDOrDie(env, tunerClass, "<init>", "()V");
+
+    auto serviceClass = FindClassOrDie(env, "com/android/server/radio/RadioService");
+    gServiceClass = MakeGlobalRefOrDie(env, serviceClass);
+
+    auto res = jniRegisterNativeMethods(env, "com/android/server/radio/RadioService",
+            gRadioServiceMethods, NELEM(gRadioServiceMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+}
+
+} /* namespace android */
diff --git a/services/core/jni/com_android_server_radio_RadioService.h b/services/core/jni/com_android_server_radio_RadioService.h
new file mode 100644
index 0000000..1fef9e6
--- /dev/null
+++ b/services/core/jni/com_android_server_radio_RadioService.h
@@ -0,0 +1,28 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_RADIO_RADIOSERVICE_H
+#define _ANDROID_SERVER_RADIO_RADIOSERVICE_H
+
+#include "jni.h"
+
+namespace android {
+
+void register_android_server_radio_RadioService(JNIEnv *env);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_RADIO_RADIOSERVICE_H
diff --git a/services/core/jni/com_android_server_radio_Tuner.cpp b/services/core/jni/com_android_server_radio_Tuner.cpp
new file mode 100644
index 0000000..f3180a0
--- /dev/null
+++ b/services/core/jni/com_android_server_radio_Tuner.cpp
@@ -0,0 +1,138 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "radio.Tuner.jni"
+#define LOG_NDEBUG 0
+
+#include "com_android_server_radio_Tuner.h"
+
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
+#include <core_jni_helpers.h>
+#include <utils/Log.h>
+#include <JNIHelp.h>
+
+namespace android {
+
+using hardware::Return;
+using hardware::hidl_vec;
+
+namespace V1_0 = hardware::broadcastradio::V1_0;
+namespace V1_1 = hardware::broadcastradio::V1_1;
+
+using V1_0::BandConfig;
+using V1_0::ITuner;
+using V1_0::MetaData;
+using V1_0::Result;
+using V1_1::ITunerCallback;
+using V1_1::ProgramListResult;
+
+static Mutex gContextMutex;
+
+static jclass gTunerClass;
+static jfieldID gNativeContextId;
+
+struct TunerContext {
+    TunerContext() {}
+
+    sp<ITuner> mHalTuner;
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(TunerContext);
+};
+
+// TODO(b/36863239): implement actual callback class which forwards calls to Java code.
+class DummyTunerCallback : public ITunerCallback {
+    virtual Return<void> hardwareFailure() { return Return<void>(); }
+    virtual Return<void> configChange(Result result, const BandConfig& config) {
+        return Return<void>();
+    }
+    virtual Return<void> tuneComplete(Result result, const V1_0::ProgramInfo& info) {
+        return Return<void>();
+    }
+    virtual Return<void> afSwitch(const V1_0::ProgramInfo& info) { return Return<void>(); }
+    virtual Return<void> antennaStateChange(bool connected) { return Return<void>(); }
+    virtual Return<void> trafficAnnouncement(bool active) { return Return<void>(); }
+    virtual Return<void> emergencyAnnouncement(bool active) { return Return<void>(); }
+    virtual Return<void> newMetadata(uint32_t channel, uint32_t subChannel,
+            const hidl_vec<MetaData>& metadata) { return Return<void>(); }
+    virtual Return<void> tuneComplete_1_1(Result result, const V1_1::ProgramInfo& info) {
+        return Return<void>();
+    }
+    virtual Return<void> afSwitch_1_1(const V1_1::ProgramInfo& info) { return Return<void>(); }
+    virtual Return<void> backgroundScanAvailable(bool isAvailable) { return Return<void>(); }
+    virtual Return<void> backgroundScanComplete(ProgramListResult result) { return Return<void>(); }
+    virtual Return<void> programListChanged() { return Return<void>(); }
+};
+
+/**
+ * Always lock gContextMutex when using native context.
+ */
+static TunerContext& getNativeContext(JNIEnv *env, jobject obj) {
+    auto nativeContext = reinterpret_cast<TunerContext*>(env->GetLongField(obj, gNativeContextId));
+    LOG_ALWAYS_FATAL_IF(nativeContext == nullptr, "Native context not initialized");
+    return *nativeContext;
+}
+
+static jlong nativeInit(JNIEnv *env, jobject obj) {
+    ALOGV("nativeInit()");
+    AutoMutex _l(gContextMutex);
+
+    auto nativeContext = new TunerContext();
+    static_assert(sizeof(jlong) >= sizeof(nativeContext), "jlong is smaller than a pointer");
+    return reinterpret_cast<jlong>(nativeContext);
+}
+
+static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) {
+    ALOGV("nativeFinalize()");
+    AutoMutex _l(gContextMutex);
+
+    auto ctx = reinterpret_cast<TunerContext*>(nativeContext);
+    delete ctx;
+}
+
+void android_server_radio_Tuner_setHalTuner(JNIEnv *env, jobject obj, sp<ITuner> halTuner) {
+    ALOGV("setHalTuner(%p)", halTuner.get());
+    AutoMutex _l(gContextMutex);
+
+    auto& ctx = getNativeContext(env, obj);
+    ctx.mHalTuner = halTuner;
+}
+
+sp<ITunerCallback> android_server_radio_Tuner_getCallback(JNIEnv *env, jobject obj) {
+    return new DummyTunerCallback();
+}
+
+static void close(JNIEnv *env, jobject obj) {
+    android_server_radio_Tuner_setHalTuner(env, obj, nullptr);
+}
+
+static const JNINativeMethod gTunerMethods[] = {
+    { "nativeInit", "()J", (void*)nativeInit },
+    { "nativeFinalize", "(J)V", (void*)nativeFinalize },
+    { "close", "()V", (void*)close },
+};
+
+void register_android_server_radio_Tuner(JNIEnv *env) {
+    auto tunerClass = FindClassOrDie(env, "com/android/server/radio/Tuner");
+    gTunerClass = MakeGlobalRefOrDie(env, tunerClass);
+    gNativeContextId = GetFieldIDOrDie(env, gTunerClass, "mNativeContext", "J");
+
+    auto res = jniRegisterNativeMethods(env, "com/android/server/radio/Tuner",
+            gTunerMethods, NELEM(gTunerMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+}
+
+} /* namespace android */
diff --git a/services/core/jni/com_android_server_radio_Tuner.h b/services/core/jni/com_android_server_radio_Tuner.h
new file mode 100644
index 0000000..ec16a18
--- /dev/null
+++ b/services/core/jni/com_android_server_radio_Tuner.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SERVER_RADIO_TUNER_H
+#define _ANDROID_SERVER_RADIO_TUNER_H
+
+#include "jni.h"
+
+#include <android/hardware/broadcastradio/1.1/ITuner.h>
+#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+void register_android_server_radio_Tuner(JNIEnv *env);
+
+void android_server_radio_Tuner_setHalTuner(JNIEnv *env, jobject obj,
+        sp<hardware::broadcastradio::V1_0::ITuner> halTuner);
+
+sp<hardware::broadcastradio::V1_1::ITunerCallback>
+android_server_radio_Tuner_getCallback(JNIEnv *env, jobject obj);
+
+} // namespace android
+
+#endif // _ANDROID_SERVER_RADIO_TUNER_H
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index f22b330..13ff28c 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -19,6 +19,9 @@
 #include "utils/Log.h"
 #include "utils/misc.h"
 
+#include "com_android_server_radio_RadioService.h"
+#include "com_android_server_radio_Tuner.h"
+
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_BatteryStatsService(JNIEnv* env);
@@ -62,6 +65,8 @@
     }
     ALOG_ASSERT(env, "Could not retrieve the env!");
 
+    register_android_server_radio_RadioService(env);
+    register_android_server_radio_Tuner(env);
     register_android_server_PowerManagerService(env);
     register_android_server_SerialService(env);
     register_android_server_InputApplicationHandle(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 58646fa2..6b77fae 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -744,8 +744,8 @@
         boolean forceEphemeralUsers = false; // Can only be set by a device owner.
         boolean isNetworkLoggingEnabled = false; // Can only be set by a device owner.
 
-        // one notification after enabling + 3 more after reboots
-        static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 4;
+        // one notification after enabling + one more after reboots
+        static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2;
         int numNetworkLoggingNotifications = 0;
         long lastNetworkLoggingNotificationTimeMs = 0; // Time in milliseconds since epoch
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f95037c..71781ac 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -83,6 +83,7 @@
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
 import com.android.server.notification.NotificationManagerService;
+import com.android.server.oemlock.OemLockService;
 import com.android.server.om.OverlayManagerService;
 import com.android.server.os.DeviceIdentifiersPolicyService;
 import com.android.server.os.SchedulingPolicyService;
@@ -982,12 +983,20 @@
                 }
                 traceEnd();
 
-                if (!SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("")) {
+                final boolean hasPdb = !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("");
+                if (hasPdb) {
                     traceBeginAndSlog("StartPersistentDataBlock");
                     mSystemServiceManager.startService(PersistentDataBlockService.class);
                     traceEnd();
                 }
 
+                if (hasPdb || OemLockService.isHalPresent()) {
+                    // Implementation depends on pdb or the OemLock HAL
+                    traceBeginAndSlog("StartOemLockService");
+                    mSystemServiceManager.startService(OemLockService.class);
+                    traceEnd();
+                }
+
                 traceBeginAndSlog("StartDeviceIdleController");
                 mSystemServiceManager.startService(DeviceIdleController.class);
                 traceEnd();
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
index 2c38f97..122a954 100644
--- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -17,12 +17,15 @@
 
 package com.android.server.print;
 
+import static com.android.internal.util.CollectionUtils.size;
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.internal.util.Preconditions.checkState;
 
 import android.Manifest;
 import android.annotation.CheckResult;
 import android.annotation.Nullable;
+import android.app.PendingIntent;
 import android.companion.AssociationRequest;
 import android.companion.CompanionDeviceManager;
 import android.companion.ICompanionDeviceDiscoveryService;
@@ -46,13 +49,18 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.SettingsStringUtil.ComponentNameSet;
+import android.text.BidiFormatter;
 import android.util.AtomicFile;
 import android.util.ExceptionUtils;
+import android.util.Log;
 import android.util.Slog;
 import android.util.Xml;
 
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.notification.NotificationAccessConfirmationActivityContract;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
 import com.android.server.FgThread;
@@ -79,6 +87,7 @@
 //TODO schedule stopScan on activity destroy(except if configuration change)
 //TODO on associate called again after configuration change -> replace old callback with new
 //TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example)
+//TODO check user-feature present in manifest on API calls
 /** @hide */
 public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
 
@@ -216,12 +225,13 @@
                     a -> a.deviceAddress);
         }
 
+        //TODO also revoke notification access
         @Override
         public void disassociate(String deviceMacAddress, String callingPackage)
                 throws RemoteException {
             checkNotNull(deviceMacAddress);
             checkCallerIsSystemOr(callingPackage);
-            updateAssociations(associations -> ArrayUtils.remove(associations,
+            updateAssociations(associations -> CollectionUtils.remove(associations,
                     new Association(getCallingUserId(), deviceMacAddress, callingPackage)));
         }
 
@@ -236,11 +246,49 @@
 
             checkArgument(getCallingUserId() == userId,
                     "Must be called by either same user or system");
-
             mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
         }
+
+        @Override
+        public PendingIntent requestNotificationAccess(ComponentName component)
+                throws RemoteException {
+            String callingPackage = component.getPackageName();
+            checkCanCallNotificationApi(callingPackage);
+            int userId = getCallingUserId();
+            String packageTitle = BidiFormatter.getInstance().unicodeWrap(
+                    getPackageInfo(callingPackage, userId)
+                            .applicationInfo
+                            .loadSafeLabel(getContext().getPackageManager())
+                            .toString());
+            long identity = Binder.clearCallingIdentity();
+            try {
+                return PendingIntent.getActivity(getContext(),
+                        0 /* request code */,
+                        NotificationAccessConfirmationActivityContract.launcherIntent(
+                                userId, component, packageTitle),
+                        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT
+                                | PendingIntent.FLAG_CANCEL_CURRENT);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public boolean hasNotificationAccess(ComponentName component) throws RemoteException {
+            checkCanCallNotificationApi(component.getPackageName());
+            String setting = Settings.Secure.getString(getContext().getContentResolver(),
+                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+            return new ComponentNameSet(setting).contains(component);
+        }
+
+        private void checkCanCallNotificationApi(String callingPackage) throws RemoteException {
+            checkCallerIsSystemOr(callingPackage);
+            checkState(!ArrayUtils.isEmpty(readAllAssociations(getCallingUserId(), callingPackage)),
+                    "App must have an association before calling this API");
+        }
     }
 
+
     private int getCallingUserId() {
         return UserHandle.getUserId(Binder.getCallingUid());
     }
@@ -290,6 +338,17 @@
         return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
 
             @Override
+            public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+                    throws RemoteException {
+                try {
+                    return super.onTransact(code, data, reply, flags);
+                } catch (Throwable e) {
+                    Slog.e(LOG_TAG, "Error during IPC", e);
+                    throw ExceptionUtils.propagate(e, RemoteException.class);
+                }
+            }
+
+            @Override
             public void onDeviceSelected(String packageName, int userId, String deviceAddress) {
                 updateSpecialAccessPermissionForAssociatedPackage(packageName, userId);
                 recordAssociation(packageName, deviceAddress);
@@ -300,7 +359,6 @@
             public void onDeviceSelectionCancel() {
                 cleanup();
             }
-
         };
     }
 
@@ -350,22 +408,29 @@
     }
 
     private void recordAssociation(String priviledgedPackage, String deviceAddress) {
-        updateAssociations((associations) -> ArrayUtils.add(associations,
-                new Association(getCallingUserId(), deviceAddress, priviledgedPackage)));
+        if (DEBUG) {
+            Log.i(LOG_TAG, "recordAssociation(priviledgedPackage = " + priviledgedPackage
+                    + ", deviceAddress = " + deviceAddress + ")");
+        }
+        int userId = getCallingUserId();
+        updateAssociations(associations -> CollectionUtils.add(associations,
+                new Association(userId, deviceAddress, priviledgedPackage)));
     }
 
-    private void updateAssociations(Function<ArrayList<Association>, List<Association>> update) {
+    private void updateAssociations(Function<List<Association>, List<Association>> update) {
         updateAssociations(update, getCallingUserId());
     }
 
-    private void updateAssociations(Function<ArrayList<Association>, List<Association>> update,
+    private void updateAssociations(Function<List<Association>, List<Association>> update,
             int userId) {
         final AtomicFile file = getStorageFileForUser(userId);
         synchronized (file) {
-            final ArrayList<Association> old = readAllAssociations(userId);
-            final List<Association> associations = update.apply(old);
-            if (Objects.equals(old, associations)) return;
+            List<Association> associations = readAllAssociations(userId);
+            final List<Association> old = CollectionUtils.copyOf(associations);
+            associations = update.apply(associations);
+            if (size(old) == size(associations)) return;
 
+            List<Association> finalAssociations = associations;
             file.write((out) -> {
                 XmlSerializer xml = Xml.newSerializer();
                 try {
@@ -374,8 +439,8 @@
                     xml.startDocument(null, true);
                     xml.startTag(null, XML_TAG_ASSOCIATIONS);
 
-                    for (int i = 0; i < CollectionUtils.size(associations); i++) {
-                        Association association = associations.get(i);
+                    for (int i = 0; i < size(finalAssociations); i++) {
+                        Association association = finalAssociations.get(i);
                         xml.startTag(null, XML_TAG_ASSOCIATION)
                             .attribute(null, XML_ATTR_PACKAGE, association.companionAppPackage)
                             .attribute(null, XML_ATTR_DEVICE, association.deviceAddress)
@@ -391,15 +456,6 @@
 
             });
         }
-
-
-        //TODO Show dialog before recording notification access
-//        final SettingStringHelper setting =
-//                new SettingStringHelper(
-//                        getContext().getContentResolver(),
-//                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-//                        getUserId());
-//        setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage));
     }
 
     private AtomicFile getStorageFileForUser(int uid) {
diff --git a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
index d14f4eb..013eab8 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
@@ -67,7 +67,7 @@
     @Override
     public void show() {
         super.show();
-        final TextView messageView = (TextView) findViewById(R.id.message);
+        final TextView messageView = findViewById(R.id.message);
         messageView.post(new Runnable() {
             @Override
             public void run() {
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index e285669..d383aea 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -215,6 +215,8 @@
                 builder.setSound(CUSTOM_SOUND);
                 channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
             }
+        } else {
+            channel.setSound(null, null);
         }
         if (buzzy) {
             if (defaultVibration) {
diff --git a/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
new file mode 100644
index 0000000..24cb72e
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.notification;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class GlobalSortKeyComparatorTest {
+
+    private final String PKG = "PKG";
+    private final int UID = 1111111;
+    private static final String TEST_CHANNEL_ID = "test_channel_id";
+
+    @Test
+    public void testComparator() throws Exception {
+        Notification n = new Notification.Builder(
+                InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+                .build();
+        NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+                new StatusBarNotification(PKG,
+                        PKG, 1, "media", UID, UID, n,
+                        new UserHandle(UserHandle.myUserId()),
+                        "", 1499), getDefaultChannel());
+        left.setGlobalSortKey("first");
+
+        NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+                new StatusBarNotification(PKG,
+                        PKG, 1, "media", UID, UID, n,
+                        new UserHandle(UserHandle.myUserId()),
+                        "", 1499), getDefaultChannel());
+        right.setGlobalSortKey("second");
+
+        NotificationRecord last = new NotificationRecord(InstrumentationRegistry.getContext(),
+                new StatusBarNotification(PKG,
+                        PKG, 1, "media", UID, UID, n,
+                        new UserHandle(UserHandle.myUserId()),
+                        "", 1499), getDefaultChannel());
+
+
+        final List<NotificationRecord> expected = new ArrayList<>();
+        expected.add(left);
+        expected.add(right);
+        expected.add(last);
+
+        List<NotificationRecord> actual = new ArrayList<>();
+        actual.addAll(expected);
+        Collections.shuffle(actual);
+
+        Collections.sort(actual, new GlobalSortKeyComparator());
+
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testNoCrash_leftNull() throws Exception {
+        Notification n = new Notification.Builder(
+                InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+                .build();
+        NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+                new StatusBarNotification(PKG,
+                        PKG, 1, "media", UID, UID, n,
+                        new UserHandle(UserHandle.myUserId()),
+                        "", 1499), getDefaultChannel());
+
+        NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+                new StatusBarNotification(PKG,
+                        PKG, 1, "media", UID, UID, n,
+                        new UserHandle(UserHandle.myUserId()),
+                        "", 1499), getDefaultChannel());
+        right.setGlobalSortKey("not null");
+
+        final List<NotificationRecord> expected = new ArrayList<>();
+        expected.add(right);
+        expected.add(left);
+
+        List<NotificationRecord> actual = new ArrayList<>();
+        actual.addAll(expected);
+        Collections.shuffle(actual);
+
+        Collections.sort(actual, new GlobalSortKeyComparator());
+
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testNoCrash_rightNull() throws Exception {
+        Notification n = new Notification.Builder(
+                InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+                .build();
+        NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+                new StatusBarNotification(PKG,
+                        PKG, 1, "media", UID, UID, n,
+                        new UserHandle(UserHandle.myUserId()),
+                        "", 1499), getDefaultChannel());
+        left.setGlobalSortKey("not null");
+
+        NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+                new StatusBarNotification(PKG,
+                        PKG, 1, "media", UID, UID, n,
+                        new UserHandle(UserHandle.myUserId()),
+                        "", 1499), getDefaultChannel());
+
+        final List<NotificationRecord> expected = new ArrayList<>();
+        expected.add(left);
+        expected.add(right);
+
+        List<NotificationRecord> actual = new ArrayList<>();
+        actual.addAll(expected);
+        Collections.shuffle(actual);
+
+        Collections.sort(actual, new GlobalSortKeyComparator());
+
+        assertEquals(expected, actual);
+    }
+
+    private NotificationChannel getDefaultChannel() {
+        return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
+                NotificationManager.IMPORTANCE_LOW);
+    }
+}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
index 176342b..84945ab 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
@@ -75,6 +75,7 @@
     private NotificationRecord mRecordContact;
     private NotificationRecord mRecordUrgent;
     private NotificationRecord mRecordCheater;
+    private NotificationRecord mRecordCheaterColorized;
 
 
     @Before
@@ -174,6 +175,7 @@
                 pkg2, 1, "cheater", uid2, uid2, n9, new UserHandle(userId),
                 "", 9258), getDefaultChannel());
         mRecordCheater.setUserImportance(NotificationManager.IMPORTANCE_LOW);
+        mRecordCheater.setPackagePriority(Notification.PRIORITY_MAX);
 
         Notification n10 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setStyle(new Notification.InboxStyle().setSummaryText("message!")).build();
@@ -181,6 +183,15 @@
                 pkg2, 1, "email", uid2, uid2, n10, new UserHandle(userId),
                 "", 1599), getDefaultChannel());
         mRecordEmail.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+
+        Notification n11 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setCategory(Notification.CATEGORY_MESSAGE)
+                .setColorized(true)
+                .build();
+        mRecordCheaterColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+                pkg2, 1, "cheater", uid2, uid2, n11, new UserHandle(userId),
+                "", 9258), getDefaultChannel());
+        mRecordCheaterColorized.setUserImportance(NotificationManager.IMPORTANCE_LOW);
     }
 
     @Test
@@ -195,6 +206,7 @@
         expected.add(mRecordEmail);
         expected.add(mRecordUrgent);
         expected.add(mRecordCheater);
+        expected.add(mRecordCheaterColorized);
         expected.add(mRecordMinCall);
 
         List<NotificationRecord> actual = new ArrayList<>();
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index f666727..57ee928 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -49,6 +49,7 @@
 import android.content.pm.ParceledListSlice;
 import android.graphics.Color;
 import android.os.Binder;
+import android.os.Process;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
@@ -460,10 +461,10 @@
         mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
         verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
-                eq(mTestNotificationChannel),
+                eq(Process.myUserHandle()), eq(mTestNotificationChannel),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
         verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
-                eq(channel2),
+                eq(Process.myUserHandle()), eq(channel2),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
     }
 
@@ -481,10 +482,10 @@
         mBinderService.createNotificationChannelGroups(PKG,
                 new ParceledListSlice(Arrays.asList(group1, group2)));
         verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
-                eq(group1),
+                eq(Process.myUserHandle()), eq(group1),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
         verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
-                eq(group2),
+                eq(Process.myUserHandle()), eq(group2),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
     }
 
@@ -503,7 +504,7 @@
         reset(mNotificationListeners);
         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
         verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
-                eq(mTestNotificationChannel),
+                eq(Process.myUserHandle()), eq(mTestNotificationChannel),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
     }
 
@@ -520,7 +521,7 @@
         reset(mNotificationListeners);
         mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
         verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
-                eq(mTestNotificationChannel),
+                eq(Process.myUserHandle()), eq(mTestNotificationChannel),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
     }
 
@@ -537,7 +538,7 @@
         reset(mNotificationListeners);
         mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
         verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
-                eq(ncg),
+                eq(Process.myUserHandle()), eq(ncg),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
     }
 
@@ -550,12 +551,12 @@
         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
 
         mBinderService.updateNotificationChannelFromPrivilegedListener(
-                null, PKG, mTestNotificationChannel);
+                null, PKG, Process.myUserHandle(), mTestNotificationChannel);
 
         verify(mRankingHelper, times(1)).updateNotificationChannel(anyString(), anyInt(), any());
 
         verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
-                eq(mTestNotificationChannel),
+                eq(Process.myUserHandle()), eq(mTestNotificationChannel),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
     }
 
@@ -568,7 +569,7 @@
 
         try {
             mBinderService.updateNotificationChannelFromPrivilegedListener(
-                    null, PKG, mTestNotificationChannel);
+                    null, PKG, Process.myUserHandle(), mTestNotificationChannel);
             fail("listeners that don't have a companion device shouldn't be able to call this");
         } catch (SecurityException e) {
             // pass
@@ -577,7 +578,33 @@
         verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any());
 
         verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
-                eq(mTestNotificationChannel),
+                eq(Process.myUserHandle()), eq(mTestNotificationChannel),
+                eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
+    }
+
+    @Test
+    @UiThreadTest
+    public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
+        mNotificationManagerService.setRankingHelper(mRankingHelper);
+        List<String> associations = new ArrayList<>();
+        associations.add("a");
+        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        mListener = mock(ManagedServices.ManagedServiceInfo.class);
+        when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
+        when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+
+        try {
+            mBinderService.updateNotificationChannelFromPrivilegedListener(
+                    null, PKG, UserHandle.ALL, mTestNotificationChannel);
+            fail("incorrectly allowed a change to a user listener cannot see");
+        } catch (SecurityException e) {
+            // pass
+        }
+
+        verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any());
+
+        verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
+                eq(Process.myUserHandle()), eq(mTestNotificationChannel),
                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
     }
 
@@ -589,7 +616,8 @@
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
 
-        mBinderService.getNotificationChannelsFromPrivilegedListener(null, PKG);
+        mBinderService.getNotificationChannelsFromPrivilegedListener(
+                null, PKG, Process.myUserHandle());
 
         verify(mRankingHelper, times(1)).getNotificationChannels(
                 anyString(), anyInt(), anyBoolean());
@@ -603,7 +631,8 @@
         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
 
         try {
-            mBinderService.getNotificationChannelsFromPrivilegedListener(null, PKG);
+            mBinderService.getNotificationChannelsFromPrivilegedListener(
+                    null, PKG, Process.myUserHandle());
             fail("listeners that don't have a companion device shouldn't be able to call this");
         } catch (SecurityException e) {
             // pass
@@ -615,13 +644,37 @@
 
     @Test
     @UiThreadTest
+    public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
+        mNotificationManagerService.setRankingHelper(mRankingHelper);
+        List<String> associations = new ArrayList<>();
+        associations.add("a");
+        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        mListener = mock(ManagedServices.ManagedServiceInfo.class);
+        when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
+        when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+
+        try {
+            mBinderService.getNotificationChannelsFromPrivilegedListener(
+                    null, PKG, Process.myUserHandle());
+            fail("listener getting channels from a user they cannot see");
+        } catch (SecurityException e) {
+            // pass
+        }
+
+        verify(mRankingHelper, never()).getNotificationChannels(
+                anyString(), anyInt(), anyBoolean());
+    }
+
+    @Test
+    @UiThreadTest
     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
 
-        mBinderService.getNotificationChannelGroupsFromPrivilegedListener(null, PKG);
+        mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
+                null, PKG, Process.myUserHandle());
 
         verify(mRankingHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
     }
@@ -634,7 +687,29 @@
         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
 
         try {
-            mBinderService.getNotificationChannelGroupsFromPrivilegedListener(null, PKG);
+            mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
+                    null, PKG, Process.myUserHandle());
+            fail("listeners that don't have a companion device shouldn't be able to call this");
+        } catch (SecurityException e) {
+            // pass
+        }
+
+        verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
+        mNotificationManagerService.setRankingHelper(mRankingHelper);
+        List<String> associations = new ArrayList<>();
+        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        mListener = mock(ManagedServices.ManagedServiceInfo.class);
+        when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
+        when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
+
+        try {
+            mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
+                    null, PKG, Process.myUserHandle());
             fail("listeners that don't have a companion device shouldn't be able to call this");
         } catch (SecurityException e) {
             // pass
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 946044d..b2e6ef9 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -124,6 +124,9 @@
                 builder.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
                 channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
             }
+        } else {
+            channel.setSound(null, null);
+            builder.setSound(null, null);
         }
         if (buzzy) {
             if (defaultVibration) {
@@ -206,6 +209,18 @@
     }
 
     @Test
+    public void testSound_noSound_preUpgrade() throws Exception {
+        // pre upgrade, default sound.
+        StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /*defaultLights */);
+
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
+        assertEquals(null, record.getSound());
+        assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
+    }
+
+    @Test
     public void testSound_default_upgradeUsesChannel() throws Exception {
         channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
         // post upgrade, default sound.
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 885eb2e..303054e 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -738,15 +738,6 @@
     }
 
     @Test
-    public void testCreateChannel_addMissingSound() throws Exception {
-        final NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
-        mHelper.createNotificationChannel(PKG, UID, channel, true);
-        assertNotNull(mHelper.getNotificationChannel(
-                PKG, UID, channel.getId(), false).getSound());
-    }
-
-    @Test
     public void testCreateChannel_noOverrideSound() throws Exception {
         Uri sound = new Uri.Builder().scheme("test").build();
         final NotificationChannel channel = new NotificationChannel("id2", "name2",
diff --git a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
index 9343449..2a9f556 100644
--- a/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/BaseLockSettingsServiceTests.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
@@ -82,6 +83,7 @@
     IActivityManager mActivityManager;
     DevicePolicyManager mDevicePolicyManager;
     KeyStore mKeyStore;
+    MockSyntheticPasswordManager mSpManager;
 
     @Override
     protected void setUp() throws Exception {
@@ -94,6 +96,7 @@
         mStorageManager = new MockStorageManager();
         mActivityManager = mock(IActivityManager.class);
         mDevicePolicyManager = mock(DevicePolicyManager.class);
+
         mContext = new MockLockSettingsContext(getContext(), mUserManager, mNotificationManager,
                 mDevicePolicyManager);
         mStorage = new LockSettingsStorageTestable(mContext,
@@ -105,12 +108,15 @@
             storageDir.mkdirs();
         }
 
+        mSpManager = new MockSyntheticPasswordManager(mStorage, mGateKeeperService);
         mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils,
-                mStorage, mGateKeeperService, mKeyStore, mStorageManager, mActivityManager);
+                mStorage, mGateKeeperService, mKeyStore, mStorageManager, mActivityManager,
+                mSpManager);
         when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO);
         mPrimaryUserProfiles.add(PRIMARY_USER_INFO);
         installChildProfile(MANAGED_PROFILE_USER_ID);
         installQuietModeChildProfile(TURNED_OFF_PROFILE_USER_ID);
+        when(mUserManager.getUsers(anyBoolean())).thenReturn(mPrimaryUserProfiles);
         when(mUserManager.getProfiles(eq(PRIMARY_USER_ID))).thenReturn(mPrimaryUserProfiles);
         when(mUserManager.getUserInfo(eq(SECONDARY_USER_ID))).thenReturn(SECONDARY_USER_INFO);
         when(mUserManager.isUserRunning(eq(MANAGED_PROFILE_USER_ID))).thenReturn(true);
diff --git a/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java b/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java
new file mode 100644
index 0000000..362c47ad
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/BootReceiverFixFsckFsStatTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static junit.framework.Assert.*;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BootReceiverFixFsckFsStatTest {
+
+    private static final String PARTITION = "userdata";
+
+    @Test
+    public void testTreeOptimization() {
+        final String[] logs = {
+                "e2fsck 1.43.3 (04-Sep-2016)",
+                "Pass 1: Checking inodes, blocks, and sizes",
+                "Inode 877141 extent tree (at level 1) could be shorter.  Fix? yes",
+                " ",
+                "Pass 1E: Optimizing extent trees",
+                "Pass 2: Checking directory structure",
+                "Pass 3: Checking directory connectivity",
+                "Pass 4: Checking reference counts",
+                "Pass 5: Checking group summary information",
+                "[QUOTA WARNING] Usage inconsistent for ID 10038:actual (71667712, 1000) != expected (71671808, 1000)",
+                "Update quota info for quota type 0? yes",
+                " ",
+                "[QUOTA WARNING] Usage inconsistent for ID 10038:actual (59555840, 953) != expected (59559936, 953)",
+                "Update quota info for quota type 1? yes",
+                " ",
+                "/dev/block/platform/soc/624000.ufshc/by-name/userdata: ***** FILE SYSTEM WAS MODIFIED *****"
+        };
+        doTestFsckFsStat(logs, 0x405, 5, 0, logs.length);
+
+        final String[] doubleLogs = new String[logs.length * 2];
+        System.arraycopy(logs, 0, doubleLogs, 0, logs.length);
+        System.arraycopy(logs, 0, doubleLogs, logs.length, logs.length);
+        doTestFsckFsStat(doubleLogs, 0x401, 1, 0, logs.length);
+        doTestFsckFsStat(doubleLogs, 0x402, 2, logs.length, logs.length * 2);
+    }
+
+    @Test
+    public void testQuotaOnly() {
+        final String[] logs = {
+                "e2fsck 1.43.3 (04-Sep-2016)",
+                "Pass 1: Checking inodes, blocks, and sizes",
+                "Pass 1E: Optimizing extent trees",
+                "Pass 2: Checking directory structure",
+                "Pass 3: Checking directory connectivity",
+                "Pass 4: Checking reference counts",
+                "Pass 5: Checking group summary information",
+                "[QUOTA WARNING] Usage inconsistent for ID 10038:actual (71667712, 1000) != expected (71671808, 1000)",
+                "Update quota info for quota type 0? yes",
+                " ",
+                "[QUOTA WARNING] Usage inconsistent for ID 10038:actual (59555840, 953) != expected (59559936, 953)",
+                "Update quota info for quota type 1? yes",
+                " ",
+                "/dev/block/platform/soc/624000.ufshc/by-name/userdata: ***** FILE SYSTEM WAS MODIFIED *****"
+        };
+        doTestFsckFsStat(logs, 0x405, 0x405, 0, logs.length);
+    }
+
+    @Test
+    public void testOrphaned() {
+        final String[] logs = {
+                "e2fsck 1.43.3 (04-Sep-2016)",
+                "Pass 1: Checking inodes, blocks, and sizes",
+                "Inodes that were part of a corrupted orphan linked list found.  Fix? yes",
+                " ",
+                "Inode 589877 was part of the orphaned inode list.  FIXED.",
+                " ",
+                "Inode 589878 was part of the orphaned inode list.  FIXED.",
+                " ",
+                "Pass 2: Checking directory structure",
+                "Pass 3: Checking directory connectivity",
+                "Pass 4: Checking reference counts",
+                "Pass 5: Checking group summary information",
+                " ",
+                "/dev/block/platform/soc/624000.ufshc/by-name/userdata: ***** FILE SYSTEM WAS MODIFIED *****"
+        };
+        doTestFsckFsStat(logs, 0x405, 0x405, 0, logs.length);
+    }
+
+    private void doTestFsckFsStat(String[] lines, int statOrg, int statUpdated, int startLineNumber,
+            int endLineNumber) {
+        assertEquals(statUpdated, BootReceiver.fixFsckFsStat(PARTITION, statOrg, lines,
+                startLineNumber, endLineNumber));
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/LockSettingsServiceTestable.java
index cfdb5b1..be88927 100644
--- a/services/tests/servicestests/src/com/android/server/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/LockSettingsServiceTestable.java
@@ -40,18 +40,18 @@
         private IActivityManager mActivityManager;
         private LockPatternUtils mLockPatternUtils;
         private IStorageManager mStorageManager;
-        private MockGateKeeperService mGatekeeper;
+        private SyntheticPasswordManager mSpManager;
 
         public MockInjector(Context context, LockSettingsStorage storage, KeyStore keyStore,
                 IActivityManager activityManager, LockPatternUtils lockPatternUtils,
-                IStorageManager storageManager, MockGateKeeperService gatekeeper) {
+                IStorageManager storageManager, SyntheticPasswordManager spManager) {
             super(context);
             mLockSettingsStorage = storage;
             mKeyStore = keyStore;
             mActivityManager = activityManager;
             mLockPatternUtils = lockPatternUtils;
             mStorageManager = storageManager;
-            mGatekeeper = gatekeeper;
+            mSpManager = spManager;
         }
 
         @Override
@@ -96,7 +96,7 @@
 
         @Override
         public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) {
-            return new MockSyntheticPasswordManager(storage, mGatekeeper);
+            return mSpManager;
         }
 
         @Override
@@ -109,9 +109,10 @@
 
     protected LockSettingsServiceTestable(Context context, LockPatternUtils lockPatternUtils,
             LockSettingsStorage storage, MockGateKeeperService gatekeeper, KeyStore keystore,
-            IStorageManager storageManager, IActivityManager mActivityManager) {
+            IStorageManager storageManager, IActivityManager mActivityManager,
+            SyntheticPasswordManager spManager) {
         super(new MockInjector(context, storage, keystore, mActivityManager, lockPatternUtils,
-                storageManager, gatekeeper));
+                storageManager, spManager));
         mGateKeeperService = gatekeeper;
     }
 
@@ -121,7 +122,8 @@
     }
 
     @Override
-    protected String getDecryptedPasswordForTiedProfile(int userId) throws FileNotFoundException, KeyPermanentlyInvalidatedException {
+    protected String getDecryptedPasswordForTiedProfile(int userId) throws FileNotFoundException,
+            KeyPermanentlyInvalidatedException {
         byte[] storedData = mStorage.readChildProfileLock(userId);
         if (storedData == null) {
             throw new FileNotFoundException("Child profile lock file not found");
diff --git a/services/tests/servicestests/src/com/android/server/MockSyntheticPasswordManager.java b/services/tests/servicestests/src/com/android/server/MockSyntheticPasswordManager.java
index 93e3fc6..9389e48 100644
--- a/services/tests/servicestests/src/com/android/server/MockSyntheticPasswordManager.java
+++ b/services/tests/servicestests/src/com/android/server/MockSyntheticPasswordManager.java
@@ -15,6 +15,8 @@
  */
 package com.android.server;
 
+import android.hardware.weaver.V1_0.IWeaver;
+import android.os.RemoteException;
 import android.util.ArrayMap;
 
 import junit.framework.AssertionFailedError;
@@ -30,6 +32,7 @@
 public class MockSyntheticPasswordManager extends SyntheticPasswordManager {
 
     private MockGateKeeperService mGateKeeper;
+    private IWeaver mWeaverService;
 
     public MockSyntheticPasswordManager(LockSettingsStorage storage,
             MockGateKeeperService gatekeeper) {
@@ -99,4 +102,14 @@
         }
     }
 
+    @Override
+    protected IWeaver getWeaverService() throws RemoteException {
+        return mWeaverService;
+    }
+
+    public void enableWeaver() {
+        mWeaverService = new MockWeaverService();
+        initWeaverService();
+    }
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/MockWeaverService.java b/services/tests/servicestests/src/com/android/server/MockWeaverService.java
new file mode 100644
index 0000000..0de50ab
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/MockWeaverService.java
@@ -0,0 +1,108 @@
+package com.android.server;
+
+import android.hardware.weaver.V1_0.IWeaver;
+import android.hardware.weaver.V1_0.WeaverConfig;
+import android.hardware.weaver.V1_0.WeaverReadResponse;
+import android.hardware.weaver.V1_0.WeaverStatus;
+import android.hidl.base.V1_0.DebugInfo;
+import android.os.IHwBinder;
+import android.os.IHwBinder.DeathRecipient;
+import android.os.RemoteException;
+import android.util.Pair;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class MockWeaverService implements IWeaver {
+
+    private static final int MAX_SLOTS = 8;
+    private static final int KEY_LENGTH = 256 / 8;
+    private static final int VALUE_LENGTH = 256 / 8;
+
+    private Pair<ArrayList<Byte>, ArrayList<Byte>>[] slots = new Pair[MAX_SLOTS];
+    @Override
+    public void getConfig(getConfigCallback cb) throws RemoteException {
+        WeaverConfig config = new WeaverConfig();
+        config.keySize = KEY_LENGTH;
+        config.valueSize = VALUE_LENGTH;
+        config.slots = MAX_SLOTS;
+        cb.onValues(WeaverStatus.OK, config);
+    }
+
+    @Override
+    public int write(int slotId, ArrayList<Byte> key, ArrayList<Byte> value)
+            throws RemoteException {
+        if (slotId < 0 || slotId >= MAX_SLOTS) {
+            throw new RuntimeException("Invalid slot id");
+        }
+        slots[slotId] = Pair.create((ArrayList<Byte>) key.clone(), (ArrayList<Byte>) value.clone());
+        return WeaverStatus.OK;
+    }
+
+    @Override
+    public void read(int slotId, ArrayList<Byte> key, readCallback cb) throws RemoteException {
+        if (slotId < 0 || slotId >= MAX_SLOTS) {
+            throw new RuntimeException("Invalid slot id");
+        }
+
+        WeaverReadResponse response = new WeaverReadResponse();
+        if (key.equals(slots[slotId].first)) {
+            response.value.addAll(slots[slotId].second);
+            cb.onValues(WeaverStatus.OK, response);
+        } else {
+            cb.onValues(WeaverStatus.FAILED, response);
+        }
+    }
+
+    @Override
+    public IHwBinder asBinder() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ArrayList<String> interfaceChain() throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String interfaceDescriptor() throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setHALInstrumentation() throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean linkToDeath(DeathRecipient recipient, long cookie) throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void ping() throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public DebugInfo getDebugInfo() throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void notifySyspropsChanged() throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean unlinkToDeath(DeathRecipient recipient) throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ArrayList<byte[]> getHashChain() throws RemoteException {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 353199a..985e5ea 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -23,7 +23,6 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertSame;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
@@ -37,7 +36,7 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -49,7 +48,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.net.INetworkRecommendationProvider;
@@ -94,8 +92,6 @@
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -138,11 +134,13 @@
     @Mock private Context mContext;
     @Mock private Resources mResources;
     @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
-    @Mock private IBinder mIBinder, mIBinder2;
+    @Mock private IBinder mScoreCacheIBinder, mScoreCacheIBinder2;
+    @Mock private IBinder mServiceConnectionIBinder;
     @Mock private INetworkRecommendationProvider mRecommendationProvider;
     @Mock private UnaryOperator<List<ScoredNetwork>> mCurrentNetworkFilter;
     @Mock private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
     @Mock private WifiInfo mWifiInfo;
+    @Mock private NetworkScoreService.ScoringServiceConnection mServiceConnection;
     @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
 
     private ContentResolver mContentResolver;
@@ -160,17 +158,22 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder);
-        when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2);
+        when(mNetworkScoreCache.asBinder()).thenReturn(mScoreCacheIBinder);
+        when(mNetworkScoreCache2.asBinder()).thenReturn(mScoreCacheIBinder2);
+        when(mServiceConnectionIBinder.queryLocalInterface(anyString()))
+                .thenReturn(mRecommendationProvider);
         mContentResolver = InstrumentationRegistry.getContext().getContentResolver();
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
         when(mContext.getResources()).thenReturn(mResources);
         when(mWifiInfo.getSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.ssid);
         when(mWifiInfo.getBSSID()).thenReturn(SCORED_NETWORK.networkKey.wifiKey.bssid);
+        when(mServiceConnection.getAppData()).thenReturn(NEW_SCORER);
+        when(mServiceConnection.getRecommendationProvider()).thenReturn(mRecommendationProvider);
+        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
         mHandlerThread = new HandlerThread("NetworkScoreServiceTest");
         mHandlerThread.start();
         mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager,
-                mHandlerThread.getLooper());
+                networkScorerAppData -> mServiceConnection, mHandlerThread.getLooper());
         WifiConfiguration configuration = new WifiConfiguration();
         configuration.SSID = "NetworkScoreServiceTest_SSID";
         configuration.BSSID = "NetworkScoreServiceTest_BSSID";
@@ -209,12 +212,10 @@
 
         mNetworkScoreService.onUserUnlocked(0);
 
-        verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
-                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
-                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
-                any(ServiceConnection.class),
-                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
-                eq(UserHandle.SYSTEM));
+        verify(mNetworkScorerAppManager).updateState();
+        verify(mNetworkScorerAppManager).migrateNetworkScorerAppSettingIfNeeded();
+        verify(mServiceConnection).bind(mContext);
+
     }
 
     @Test
@@ -238,16 +239,16 @@
 
     @Test
     public void testRequestScores_providerThrowsRemoteException() throws Exception {
-        injectProvider();
         doThrow(new RemoteException()).when(mRecommendationProvider)
             .requestScores(any(NetworkKey[].class));
+        mNetworkScoreService.onUserUnlocked(0);
 
         assertFalse(mNetworkScoreService.requestScores(new NetworkKey[0]));
     }
 
     @Test
     public void testRequestScores_providerAvailable() throws Exception {
-        injectProvider();
+        mNetworkScoreService.onUserUnlocked(0);
 
         final NetworkKey[] networks = new NetworkKey[0];
         assertTrue(mNetworkScoreService.requestScores(networks));
@@ -291,11 +292,11 @@
 
     @Test
     public void testRequestRecommendation_providerThrowsRemoteException() throws Exception {
-        injectProvider();
         when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
         doThrow(new RemoteException()).when(mRecommendationProvider)
                 .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
                         anyInt());
+        mNetworkScoreService.onUserUnlocked(0);
 
         final RecommendationResult result =
                 mNetworkScoreService.requestRecommendation(mRecommendationRequest);
@@ -306,7 +307,6 @@
 
     @Test
     public void testRequestRecommendation_resultReturned() throws Exception {
-        injectProvider();
         when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
         final WifiConfiguration wifiConfiguration = new WifiConfiguration();
         wifiConfiguration.SSID = "testRequestRecommendation_resultReturned_SSID";
@@ -322,6 +322,7 @@
         }).when(mRecommendationProvider)
                 .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
                         anyInt());
+        mNetworkScoreService.onUserUnlocked(0);
 
         final RecommendationResult result =
                 mNetworkScoreService.requestRecommendation(mRecommendationRequest);
@@ -357,7 +358,7 @@
 
     @Test
     public void testRequestRecommendationAsync_requestTimesOut() throws Exception {
-        injectProvider();
+        mNetworkScoreService.onUserUnlocked(0);
         Settings.Global.putLong(mContentResolver,
                 Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS, 1L);
         mNetworkScoreService.refreshRecommendationRequestTimeoutMs();
@@ -378,7 +379,7 @@
 
     @Test
     public void testRequestRecommendationAsync_requestSucceeds() throws Exception {
-        injectProvider();
+        mNetworkScoreService.onUserUnlocked(0);
         final Bundle bundle = new Bundle();
         doAnswer(invocation -> {
             invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
@@ -397,7 +398,7 @@
 
     @Test
     public void testRequestRecommendationAsync_requestThrowsRemoteException() throws Exception {
-        injectProvider();
+        mNetworkScoreService.onUserUnlocked(0);
         doThrow(new RemoteException()).when(mRecommendationProvider)
                 .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
                         anyInt());
@@ -657,9 +658,13 @@
 
     @Test
     public void testIsCallerActiveScorer_noBoundService() throws Exception {
+        // No active scorer.
+        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
         mNetworkScoreService.onUserUnlocked(0);
 
-        assertFalse(mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid()));
+        mNetworkScoreService.isCallerActiveScorer(Binder.getCallingUid());
+
+        verify(mServiceConnection, never()).getAppData();
     }
 
     @Test
@@ -678,9 +683,13 @@
 
     @Test
     public void testGetActiveScorerPackage_notActive() throws Exception {
+        // No active scorer.
+        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
         mNetworkScoreService.onUserUnlocked(0);
 
-        assertNull(mNetworkScoreService.getActiveScorerPackage());
+        mNetworkScoreService.getActiveScorerPackage();
+
+        verify(mServiceConnection, never()).getPackageName();
     }
 
     @Test
@@ -688,10 +697,9 @@
         when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
         mNetworkScoreService.onUserUnlocked(0);
 
-        assertEquals(NEW_SCORER.getRecommendationServicePackageName(),
-                mNetworkScoreService.getActiveScorerPackage());
-        assertEquals(NEW_SCORER.getEnableUseOpenWifiActivity(),
-                mNetworkScoreService.getActiveScorer().getEnableUseOpenWifiActivity());
+        mNetworkScoreService.getActiveScorerPackage();
+
+        verify(mServiceConnection).getPackageName();
     }
 
     @Test
@@ -931,7 +939,12 @@
     public void testGetActiveScorer_notConnected_canRequestScores() throws Exception {
         when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                 .thenReturn(PackageManager.PERMISSION_GRANTED);
-        assertNull(mNetworkScoreService.getActiveScorer());
+        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(null);
+        mNetworkScoreService.onUserUnlocked(0);
+
+        mNetworkScoreService.getActiveScorer();
+
+        verify(mServiceConnection, never()).getAppData();
     }
 
     @Test
@@ -951,11 +964,11 @@
             throws Exception {
         when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES))
                 .thenReturn(PackageManager.PERMISSION_GRANTED);
-        NetworkScorerAppData expectedAppData = new NetworkScorerAppData(Binder.getCallingUid(),
-                RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
-                USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
-        bindToScorer(expectedAppData);
-        assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer());
+        mNetworkScoreService.onUserUnlocked(0);
+
+        mNetworkScoreService.getActiveScorer();
+
+        verify(mServiceConnection).getAppData();
     }
 
     @Test
@@ -972,23 +985,98 @@
         }
     }
 
-    // "injects" the mock INetworkRecommendationProvider into the NetworkScoreService.
-    private void injectProvider() {
-        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER);
-        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
-                isA(UserHandle.class))).thenAnswer(new Answer<Boolean>() {
-            @Override
-            public Boolean answer(InvocationOnMock invocation) throws Throwable {
-                IBinder mockBinder = mock(IBinder.class);
-                when(mockBinder.queryLocalInterface(anyString()))
-                        .thenReturn(mRecommendationProvider);
-                invocation.<ServiceConnection>getArgument(1)
-                        .onServiceConnected(NEW_SCORER.getRecommendationServiceComponent(),
-                                mockBinder);
-                return true;
-            }
-        });
-        mNetworkScoreService.onUserUnlocked(0);
+    @Test
+    public void testServiceConnection_bind_notBound() throws Exception {
+        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+                .ScoringServiceConnection(NEW_SCORER);
+        connection.bind(mContext);
+
+        verify(mContext).bindServiceAsUser(MockUtils.checkIntent(
+                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
+                eq(connection),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.SYSTEM));
+    }
+
+    @Test
+    public void testServiceConnection_bind_alreadyBound() throws Exception {
+        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+                .ScoringServiceConnection(NEW_SCORER);
+
+        when(mContext.bindServiceAsUser(MockUtils.checkIntent(
+                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
+                eq(connection),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.SYSTEM))).thenReturn(true /*bound*/);
+
+        // Calling bind more than once should only result in 1 bindService call.
+        connection.bind(mContext);
+        connection.bind(mContext);
+
+        verify(mContext, times(1)).bindServiceAsUser(MockUtils.checkIntent(
+                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
+                eq(connection),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.SYSTEM));
+    }
+
+    @Test
+    public void testServiceConnection_bindFails() throws Exception {
+        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+                .ScoringServiceConnection(NEW_SCORER);
+
+        when(mContext.bindServiceAsUser(MockUtils.checkIntent(
+                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
+                eq(connection),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.SYSTEM))).thenReturn(false /*bound*/);
+
+        connection.bind(mContext);
+
+        verify(mContext).unbindService(connection);
+    }
+
+    @Test
+    public void testServiceConnection_unbind_notBound() throws Exception {
+        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+                .ScoringServiceConnection(NEW_SCORER);
+
+        connection.unbind(mContext);
+
+        verify(mContext, never()).unbindService(connection);
+    }
+
+    @Test
+    public void testServiceConnection_unbind_alreadyBound() throws Exception {
+        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+                .ScoringServiceConnection(NEW_SCORER);
+
+        when(mContext.bindServiceAsUser(MockUtils.checkIntent(
+                new Intent(NetworkScoreManager.ACTION_RECOMMEND_NETWORKS)
+                        .setComponent(RECOMMENDATION_SERVICE_COMP)),
+                eq(connection),
+                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE),
+                eq(UserHandle.SYSTEM))).thenReturn(true /*bound*/);
+
+        connection.bind(mContext);
+        connection.unbind(mContext);
+
+        verify(mContext).unbindService(connection);
+    }
+
+    @Test
+    public void testServiceConnection_dump_doesNotCrash() throws Exception {
+        NetworkScoreService.ScoringServiceConnection connection = new NetworkScoreService
+                .ScoringServiceConnection(NEW_SCORER);
+        final StringWriter stringWriter = new StringWriter();
+
+        connection.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
+
+        assertFalse(stringWriter.toString().isEmpty());
     }
 
     private void bindToScorer(boolean callerIsScorer) {
@@ -996,13 +1084,7 @@
         NetworkScorerAppData appData = new NetworkScorerAppData(callingUid,
                 RECOMMENDATION_SERVICE_COMP, RECOMMENDATION_SERVICE_LABEL,
                 USE_WIFI_ENABLE_ACTIVITY_COMP, NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
-        bindToScorer(appData);
-    }
-
-    private void bindToScorer(NetworkScorerAppData appData) {
-        when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData);
-        when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(),
-                isA(UserHandle.class))).thenReturn(true);
+        when(mServiceConnection.getAppData()).thenReturn(appData);
         mNetworkScoreService.onUserUnlocked(0);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/WeaverBasedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/WeaverBasedSyntheticPasswordTests.java
new file mode 100644
index 0000000..d85a815
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/WeaverBasedSyntheticPasswordTests.java
@@ -0,0 +1,11 @@
+package com.android.server;
+
+public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mSpManager.enableWeaver();
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 00f6273..20839c5 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -117,6 +117,7 @@
     @Captor private ArgumentCaptor<Bundle> mBundleCaptor;
     private int mVisibleAccountsChangedBroadcasts;
     private int mLoginAccountsChangedBroadcasts;
+    private int mAccountRemovedBroadcasts;
 
     private static final int LATCH_TIMEOUT_MS = 500;
     private static final String PREN_DB = "pren.db";
@@ -2510,6 +2511,7 @@
         updateBroadcastCounters(2);
         assertEquals(mVisibleAccountsChangedBroadcasts, 0); // broadcast was not sent
         assertEquals(mLoginAccountsChangedBroadcasts, 2);
+        assertEquals(mAccountRemovedBroadcasts, 0);
     }
 
     @SmallTest
@@ -2533,9 +2535,10 @@
         mAms.registerAccountListener( null /* accountTypes */, "testpackage");
         mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE);
 
-        updateBroadcastCounters(6);
+        updateBroadcastCounters(8);
         assertEquals(mVisibleAccountsChangedBroadcasts, 2);
         assertEquals(mLoginAccountsChangedBroadcasts, 4);
+        assertEquals(mAccountRemovedBroadcasts, 2);
     }
 
     @SmallTest
@@ -2560,17 +2563,19 @@
             "testpackage3"); // opPackageName
         // Remove account with 2 active listeners.
         mAms.removeAccountInternal(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS);
-        updateBroadcastCounters(7);
+        updateBroadcastCounters(8);
         assertEquals(mVisibleAccountsChangedBroadcasts, 5);
         assertEquals(mLoginAccountsChangedBroadcasts, 2); // 3 add, 2 remove
+        assertEquals(mAccountRemovedBroadcasts, 1);
 
         // Add account of another type.
         mAms.addAccountExplicitly(
             AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_TYPE_2, "p11", null);
 
-        updateBroadcastCounters(8);
+        updateBroadcastCounters(9);
         assertEquals(mVisibleAccountsChangedBroadcasts, 5);
         assertEquals(mLoginAccountsChangedBroadcasts, 3);
+        assertEquals(mAccountRemovedBroadcasts, 1);
     }
 
     @SmallTest
@@ -2602,16 +2607,20 @@
     private void updateBroadcastCounters (int expectedBroadcasts){
         mVisibleAccountsChangedBroadcasts = 0;
         mLoginAccountsChangedBroadcasts = 0;
+        mAccountRemovedBroadcasts = 0;
         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
         verify(mMockContext, times(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(),
             any(UserHandle.class));
         for (Intent intent : captor.getAllValues()) {
-            if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED. equals(intent.getAction())) {
+            if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) {
                 mVisibleAccountsChangedBroadcasts++;
             }
-            if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION. equals(intent.getAction())) {
+            if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.equals(intent.getAction())) {
                 mLoginAccountsChangedBroadcasts++;
             }
+            if (AccountManager.ACTION_ACCOUNT_REMOVED.equals(intent.getAction())) {
+                mAccountRemovedBroadcasts++;
+            }
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 54ecab3..f75d49c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -16,7 +16,8 @@
 
 package com.android.server.am;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import android.content.ComponentName;
 import android.platform.test.annotations.Presubmit;
@@ -36,50 +37,61 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityRecordTests extends ActivityTestsBase {
+    private static final int TEST_STACK_ID = 100;
+
     private final ComponentName testActivityComponent =
             ComponentName.unflattenFromString("com.foo/.BarActivity");
     @Test
     public void testStackCleanupOnClearingTask() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord record = createActivity(service, testActivityComponent, task);
 
         record.setTask(null);
-        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+        assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 1);
     }
 
     @Test
     public void testStackCleanupOnActivityRemoval() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord record = createActivity(service, testActivityComponent, task);
 
         task.removeActivity(record);
-        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+        assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID),  1);
     }
 
     @Test
     public void testStackCleanupOnTaskRemoval() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord record = createActivity(service, testActivityComponent, task);
 
-        testStack.removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
-        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 1);
+        service.mStackSupervisor.getStack(TEST_STACK_ID)
+                .removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
+
+        // Stack should be gone on task removal.
+        assertNull(service.mStackSupervisor.getStack(TEST_STACK_ID));
     }
 
     @Test
     public void testNoCleanupMovingActivityInSameStack() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord oldTask = createTask(service, testActivityComponent, testStack);
+        final TaskRecord oldTask = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord record = createActivity(service, testActivityComponent, oldTask);
-        final TaskRecord newTask = createTask(service, testActivityComponent, testStack);
+        final TaskRecord newTask = createTask(service, testActivityComponent, TEST_STACK_ID);
 
         record.reparent(newTask, 0, null /*reason*/);
-        assertTrue(testStack.onActivityRemovedFromStackInvocationCount() == 0);
+        assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 0);
+    }
+
+    private static int getActivityRemovedFromStackCount(ActivityManagerService service,
+            int stackId) {
+        final ActivityStack stack = service.mStackSupervisor.getStack(stackId);
+        if (stack instanceof ActivityStackReporter) {
+            return ((ActivityStackReporter) stack).onActivityRemovedFromStackInvocationCount();
+        }
+
+        return -1;
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 8423aff..fc9ab96 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -16,8 +16,14 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
+import android.content.ComponentName;
+import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -25,6 +31,10 @@
 import org.junit.runner.RunWith;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
 
 /**
@@ -37,6 +47,9 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStackSupervisorTests extends ActivityTestsBase {
+    private final ComponentName testActivityComponent =
+            ComponentName.unflattenFromString("com.foo/.BarActivity");
+
     /**
      * This test ensures that we do not try to restore a task based off an invalid task id. The
      * stack supervisor is a test version so there will be no tasks present. We should expect
@@ -49,4 +62,59 @@
                 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
         assertNull(task);
     }
+
+    /**
+     * This test ensures that an existing task in the pinned stack is moved to the fullscreen
+     * activity stack when a new task is added.
+     */
+    @Test
+    public void testReplacingTaskInPinnedStack() throws Exception {
+        final ActivityManagerService service = createActivityManagerService();
+        final TaskRecord firstTask = createTask(service, testActivityComponent,
+                FULLSCREEN_WORKSPACE_STACK_ID);
+        final ActivityRecord firstActivity = createActivity(service, testActivityComponent,
+                firstTask);
+        // Create a new task on the full screen stack
+        final TaskRecord secondTask = createTask(service, testActivityComponent,
+                FULLSCREEN_WORKSPACE_STACK_ID);
+        final ActivityRecord secondActivity = createActivity(service, testActivityComponent,
+                secondTask);
+        service.mStackSupervisor.setFocusStackUnchecked("testReplacingTaskInPinnedStack",
+                service.mStackSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID));
+
+        // Ensure full screen stack has both tasks.
+        ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, firstTask,
+                secondTask);
+
+        // Move first activity to pinned stack.
+        service.mStackSupervisor.moveActivityToPinnedStackLocked(firstActivity,
+                new Rect() /*sourceBounds*/, 0f /*aspectRatio*/, false, "initialMove");
+
+        // Ensure a task has moved over.
+        ensureStackPlacement(service.mStackSupervisor, PINNED_STACK_ID, firstTask);
+        ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, secondTask);
+
+        // Move second activity to pinned stack.
+        service.mStackSupervisor.moveActivityToPinnedStackLocked(secondActivity,
+                new Rect() /*sourceBounds*/, 0f /*aspectRatio*/ /*destBounds*/, false, "secondMove");
+
+        // Ensure stacks have swapped tasks.
+        ensureStackPlacement(service.mStackSupervisor, PINNED_STACK_ID, secondTask);
+        ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, firstTask);
+    }
+
+    private static void ensureStackPlacement(ActivityStackSupervisor supervisor, int stackId,
+            TaskRecord... tasks) {
+        final ActivityStack stack = supervisor.getStack(stackId);
+        final ArrayList<TaskRecord> stackTasks = stack.getAllTasks();
+        assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0);
+
+        if (tasks == null) {
+            return;
+        }
+
+        for (TaskRecord task : tasks) {
+            assertTrue(stackTasks.contains(task));
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 1d80b33..f42abf1 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -37,28 +37,27 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityStackTests extends ActivityTestsBase {
-    private final ComponentName testActivityComponent =
+    private static final int TEST_STACK_ID = 100;
+    private static final ComponentName testActivityComponent =
             ComponentName.unflattenFromString("com.foo/.BarActivity");
 
     @Test
     public void testEmptyTaskCleanupOnRemove() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         assertNotNull(task.getWindowContainerController());
-        testStack.removeTask(task, "testEmptyTaskCleanupOnRemove",
-                ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+        service.mStackSupervisor.getStack(TEST_STACK_ID).removeTask(task,
+                "testEmptyTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
         assertNull(task.getWindowContainerController());
     }
     @Test
     public void testOccupiedTaskCleanupOnRemove() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
-        final TestActivityStack testStack = new ActivityStackBuilder(service).build();
-        final TaskRecord task = createTask(service, testActivityComponent, testStack);
+        final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
         final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
         assertNotNull(task.getWindowContainerController());
-        testStack.removeTask(task, "testOccupiedTaskCleanupOnRemove",
-                ActivityStack.REMOVE_TASK_MODE_DESTROYING);
+        service.mStackSupervisor.getStack(TEST_STACK_ID).removeTask(task,
+                "testOccupiedTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
         assertNotNull(task.getWindowContainerController());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 3bf0e5f..0827084 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -17,6 +17,11 @@
 package com.android.server.am;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+
+import org.mockito.invocation.InvocationOnMock;
 
 import android.app.ActivityManager;
 import android.content.ComponentName;
@@ -33,6 +38,7 @@
 import com.android.server.wm.AppWindowContainerController;
 import com.android.server.wm.StackWindowController;
 
+import com.android.server.wm.TaskWindowContainerController;
 import com.android.server.wm.WindowManagerService;
 import com.android.server.wm.WindowTestUtils;
 import org.junit.After;
@@ -64,16 +70,15 @@
 
     protected ActivityManagerService createActivityManagerService() {
         final ActivityManagerService service = new TestActivityManagerService(mContext);
-        service.mWindowManager = WindowTestUtils.getWindowManagerService(mContext);
+        service.mWindowManager = WindowTestUtils.getMockWindowManagerService();
         return service;
     }
 
-    protected static TestActivityStack createActivityStack(ActivityManagerService service,
+    protected static ActivityStack createActivityStack(ActivityManagerService service,
             int stackId, int displayId, boolean onTop) {
         if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
-            final TestActivityStack stack = ((TestActivityStackSupervisor) service.mStackSupervisor)
+            return ((TestActivityStackSupervisor) service.mStackSupervisor)
                     .createTestStack(service, stackId, onTop);
-            return stack;
         }
 
         return null;
@@ -103,7 +108,7 @@
     }
 
     protected static TaskRecord createTask(ActivityManagerService service,
-            ComponentName component, ActivityStack stack) {
+            ComponentName component, int stackId) {
         final ActivityInfo aInfo = new ActivityInfo();
         aInfo.applicationInfo = new ApplicationInfo();
         aInfo.applicationInfo.packageName = component.getPackageName();
@@ -113,13 +118,16 @@
 
         final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
                 null /*_taskDescription*/, new ActivityManager.TaskThumbnailInfo());
+        final ActivityStack stack = service.mStackSupervisor.getStack(stackId,
+                true /*createStaticStackIfNeeded*/, true /*onTop*/);
         stack.addTask(task, true, "creating test task");
         task.setStack(stack);
-        task.createWindowContainer(true, true);
+        task.setWindowContainerController(mock(TaskWindowContainerController.class));
 
         return task;
     }
 
+
     /**
      * An {@link ActivityManagerService} subclass which provides a test
      * {@link ActivityStackSupervisor}.
@@ -127,6 +135,9 @@
     protected static class TestActivityManagerService extends ActivityManagerService {
         public TestActivityManagerService(Context context) {
             super(context);
+            mSupportsMultiWindow = true;
+            mSupportsMultiDisplay = true;
+            mWindowManager = WindowTestUtils.getWindowManagerService(context);
         }
 
         @Override
@@ -142,6 +153,12 @@
     protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
         public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
             super(service, looper);
+            mWindowManager = prepareMockWindowManager();
+        }
+
+        // No home stack is set.
+        @Override
+        void moveHomeStackToFront(String reason) {
         }
 
         // Invoked during {@link ActivityStack} creation.
@@ -149,18 +166,45 @@
         void updateUIDsPresentOnDisplay() {
         }
 
-        public TestActivityStack createTestStack(ActivityManagerService service, int stackId,
-                boolean onTop) {
+        // Just return the current front task.
+        @Override
+        ActivityStack getNextFocusableStackLocked(ActivityStack currentFocus) {
+            return mFocusedStack;
+        }
+
+        // Called when moving activity to pinned stack.
+        @Override
+        void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+                boolean preserveWindows) {
+        }
+
+        public <T extends ActivityStack> T createTestStack(ActivityManagerService service,
+                int stackId, boolean onTop) {
             final ActivityDisplay display = new ActivityDisplay();
             final TestActivityContainer container =
                     new TestActivityContainer(service, stackId, display, onTop);
-            return container.getStack();
+            mActivityContainers.put(stackId, container);
+            return (T) container.getStack();
+        }
+
+        @Override
+        protected <T extends ActivityStack> T getStack(int stackId,
+                boolean createStaticStackIfNeeded, boolean createOnTop) {
+            final T stack = super.getStack(stackId, createStaticStackIfNeeded, createOnTop);
+
+            if (stack != null || !createStaticStackIfNeeded) {
+                return stack;
+            }
+
+            return createTestStack(mService, stackId, createOnTop);
         }
 
         private class TestActivityContainer extends ActivityContainer {
-            private ActivityManagerService mService;
-            private TestActivityStack mStack;
+            private final ActivityManagerService mService;
+
             private boolean mOnTop;
+            private int mStackId;
+            private ActivityStack mStack;
 
             TestActivityContainer(ActivityManagerService service, int stackId,
                     ActivityDisplay activityDisplay, boolean onTop) {
@@ -174,12 +218,16 @@
                 // we cannot set {@link mService} by the time the super constructor calling this
                 // method is invoked.
                 mOnTop = onTop;
+                mStackId = stackId;
             }
 
-            public TestActivityStack getStack() {
+            public ActivityStack getStack() {
                 if (mStack == null) {
-                    mStack = new TestActivityStack(this,
-                            new RecentTasks(mService, mService.mStackSupervisor), mOnTop);
+                    final RecentTasks recents =
+                            new RecentTasks(mService, mService.mStackSupervisor);
+                    mStack = mStackId == ActivityManager.StackId.PINNED_STACK_ID
+                    ? new PinnedActivityStack(this, recents, mOnTop)
+                    : new TestActivityStack(this, recents, mOnTop);
                 }
 
                 return mStack;
@@ -187,13 +235,31 @@
         }
     }
 
+    private static WindowManagerService prepareMockWindowManager() {
+        final WindowManagerService service = mock(WindowManagerService.class);
+
+        doAnswer((InvocationOnMock invocationOnMock) -> {
+            final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
+            if (runnable != null) {
+                runnable.run();
+            }
+            return null;
+        }).when(service).inSurfaceTransaction(any());
+
+        return service;
+    }
+
+    protected interface ActivityStackReporter {
+        int onActivityRemovedFromStackInvocationCount();
+    }
+
     /**
      * Override of {@link ActivityStack} that tracks test metrics, such as the number of times a
      * method is called. Note that its functionality depends on the implementations of the
      * construction arguments.
      */
     protected static class TestActivityStack<T extends StackWindowController>
-            extends ActivityStack<T> {
+            extends ActivityStack<T> implements ActivityStackReporter {
         private int mOnActivityRemovedFromStackCount = 0;
         private T mContainerController;
         TestActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer,
@@ -208,6 +274,7 @@
         }
 
         // Returns the number of times {@link #onActivityRemovedFromStack} has been called
+        @Override
         public int onActivityRemovedFromStackInvocationCount() {
             return mOnActivityRemovedFromStackCount;
         }
@@ -225,6 +292,7 @@
         }
     }
 
+
     protected static class ActivityStackBuilder {
         private boolean mOnTop = true;
         private int mStackId = 0;
@@ -251,7 +319,7 @@
             return this;
         }
 
-        public TestActivityStack build() {
+        public ActivityStack build() {
             return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
         }
     }
diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
new file mode 100644
index 0000000..243c1b3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.Context;
+import android.os.Handler;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.AppOpsService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+/**
+ * runtest -c com.android.server.am.AppErrorDialogTest frameworks-services
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AppErrorDialogTest {
+
+    private Context mContext;
+    private ActivityManagerService mService;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mService = new ActivityManagerService(new ActivityManagerService.Injector() {
+            @Override
+            public AppOpsService getAppOpsService(File file, Handler handler) {
+                return null;
+            }
+
+            @Override
+            public Handler getUiHandler(ActivityManagerService service) {
+                return null;
+            }
+
+            @Override
+            public boolean isNetworkRestrictedForUid(int uid) {
+                return false;
+            }
+        });
+    }
+
+    @Test
+    @UiThreadTest
+    public void testCreateWorks() throws Exception {
+        AppErrorDialog.Data data = new AppErrorDialog.Data();
+        data.proc = new ProcessRecord(null, mContext.getApplicationInfo(), "name", 12345);
+        data.result = new AppErrorResult();
+
+        AppErrorDialog dialog = new AppErrorDialog(mContext, mService, data);
+
+        dialog.create();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
new file mode 100644
index 0000000..8f2f34e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.IIntentReceiver;
+
+import android.os.Bundle;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.io.File;
+
+// runtest -c com.android.server.pm.PackageManagerServiceTest frameworks-services
+
+@SmallTest
+public class PackageManagerServiceTest extends AndroidTestCase {
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testPackageRemoval() throws Exception {
+      class PackageSenderImpl implements PackageSender {
+        public void sendPackageBroadcast(final String action, final String pkg,
+            final Bundle extras, final int flags, final String targetPkg,
+            final IIntentReceiver finishedReceiver, final int[] userIds) {
+        }
+
+        public void sendPackageAddedForNewUsers(String packageName,
+            boolean isSystem, int appId, int... userIds) {
+        }
+      }
+
+      PackageSenderImpl sender = new PackageSenderImpl();
+      PackageSetting setting = null;
+      PackageManagerService.PackageRemovedInfo pri =
+          new PackageManagerService.PackageRemovedInfo(sender);
+
+      // Initial conditions: nothing there
+      assertNull(pri.removedUsers);
+      assertNull(pri.broadcastUsers);
+
+      // populateUsers with nothing leaves nothing
+      pri.populateUsers(null, setting);
+      assertNull(pri.broadcastUsers);
+
+      // Create a real (non-null) PackageSetting and confirm that the removed
+      // users are copied properly
+      setting = new PackageSetting("name", "realName", new File("codePath"),
+          new File("resourcePath"), "legacyNativeLibraryPathString",
+          "primaryCpuAbiString", "secondaryCpuAbiString",
+          "cpuAbiOverrideString", 0, 0, 0, "parentPackageName", null, 0,
+          null, null);
+      pri.populateUsers(new int[] {1, 2, 3, 4, 5}, setting);
+      assertNotNull(pri.broadcastUsers);
+      assertEquals(5, pri.broadcastUsers.length);
+
+      // Exclude a user
+      pri.broadcastUsers = null;
+      final int EXCLUDED_USER_ID = 4;
+      setting.setInstantApp(true, EXCLUDED_USER_ID);
+      pri.populateUsers(new int[] {1, 2, 3, EXCLUDED_USER_ID, 5}, setting);
+      assertNotNull(pri.broadcastUsers);
+      assertEquals(5 - 1, pri.broadcastUsers.length);
+
+      // TODO: test that sendApplicationHiddenForUser() actually fills in
+      // broadcastUsers
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 9861aa1..cd39d88 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -708,7 +708,7 @@
         Drawable dr = mLauncherApps.getShortcutIconDrawable(
             makeShortcutWithIcon("bmp64x64", bmp64x64_maskable), 0);
         assertTrue(dr instanceof AdaptiveIconDrawable);
-        float viewportPercentage = 1 / (1 + 2 * AdaptiveIconDrawable.getExtraInsetPercentage());
+        float viewportPercentage = 1 / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
         assertEquals((int) (bmp64x64_maskable.getBitmap().getWidth() * viewportPercentage),
             dr.getIntrinsicWidth());
         assertEquals((int) (bmp64x64_maskable.getBitmap().getHeight() * viewportPercentage),
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
index 929a73d..c314de4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
@@ -27,6 +27,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.util.IconDrawableFactory;
 
 import com.android.server.LocalServices;
 
@@ -155,9 +156,9 @@
     public void testNumberOfBadges() {
         assertTrue("Max profiles greater than number of badges",
                 UserManagerService.MAX_MANAGED_PROFILES
-                <= ApplicationPackageManager.CORP_BADGE_COLORS.length);
+                <= IconDrawableFactory.CORP_BADGE_COLORS.length);
         assertEquals("Num colors doesn't match number of badge labels",
-                ApplicationPackageManager.CORP_BADGE_COLORS.length,
+                IconDrawableFactory.CORP_BADGE_COLORS.length,
                 ApplicationPackageManager.CORP_BADGE_LABEL_RES_ID.length);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
new file mode 100644
index 0000000..7f150a2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -0,0 +1,563 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
+import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
+import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
+import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
+
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManagerInternal.AppTransitionListener;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.android.server.wm.BoundsAnimationController.BoundsAnimator;
+
+/**
+ * Test class for {@link BoundsAnimationController} to ensure that it sends the right callbacks
+ * depending on the various interactions.
+ *
+ * We are really concerned about only three of the transition states [F = fullscreen, !F = floating]
+ * F->!F, !F->!F, and !F->F. Each animation can only be cancelled from the target mid-transition,
+ * or if a new animation starts on the same target.  The tests below verifies that the target is
+ * notified of all the cases where it is animating and cancelled so that it can respond
+ * appropriately.
+ *
+ * Build/Install/Run:
+ *  bit FrameworksServicesTests:com.android.server.wm.BoundsAnimationControllerTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BoundsAnimationControllerTests extends WindowTestsBase {
+
+    /**
+     * Mock value animator to simulate updates with.
+     */
+    private class MockValueAnimator extends ValueAnimator {
+
+        private float mFraction;
+
+        public MockValueAnimator getWithValue(float fraction) {
+            mFraction = fraction;
+            return this;
+        }
+
+        @Override
+        public Object getAnimatedValue() {
+            return mFraction;
+        }
+    }
+
+    /**
+     * Mock app transition to fire notifications to the bounds animator.
+     */
+    private class MockAppTransition extends AppTransition {
+
+        private AppTransitionListener mListener;
+
+        MockAppTransition(Context context) {
+            super(context, null);
+        }
+
+        @Override
+        void registerListenerLocked(AppTransitionListener listener) {
+            mListener = listener;
+        }
+
+        public void notifyTransitionPending() {
+            mListener.onAppTransitionPendingLocked();
+        }
+
+        public void notifyTransitionCancelled(int transit) {
+            mListener.onAppTransitionCancelledLocked(transit);
+        }
+
+        public void notifyTransitionStarting(int transit) {
+            mListener.onAppTransitionStartingLocked(transit, null, null, null, null);
+        }
+
+        public void notifyTransitionFinished() {
+            mListener.onAppTransitionFinishedLocked(null);
+        }
+    }
+
+    /**
+     * A test animate bounds user to track callbacks from the bounds animation.
+     */
+    private class TestBoundsAnimationTarget implements BoundsAnimationTarget {
+
+        boolean mAwaitingAnimationStart;
+        boolean mMovedToFullscreen;
+        boolean mAnimationStarted;
+        boolean mSchedulePipModeChangedOnStart;
+        boolean mAnimationEnded;
+        Rect mAnimationEndFinalStackBounds;
+        boolean mSchedulePipModeChangedOnEnd;
+        boolean mBoundsUpdated;
+        boolean mCancelRequested;
+        Rect mStackBounds;
+        Rect mTaskBounds;
+
+        void initialize(Rect from) {
+            mAwaitingAnimationStart = true;
+            mMovedToFullscreen = false;
+            mAnimationStarted = false;
+            mAnimationEnded = false;
+            mAnimationEndFinalStackBounds = null;
+            mSchedulePipModeChangedOnStart = false;
+            mSchedulePipModeChangedOnEnd = false;
+            mStackBounds = from;
+            mTaskBounds = null;
+            mBoundsUpdated = false;
+        }
+
+        @Override
+        public void onAnimationStart(boolean schedulePipModeChangedCallback) {
+            mAwaitingAnimationStart = false;
+            mAnimationStarted = true;
+            mSchedulePipModeChangedOnStart = schedulePipModeChangedCallback;
+        }
+
+        @Override
+        public boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds) {
+            // TODO: Once we break the runs apart, we should fail() here if this is called outside
+            //       of onAnimationStart() and onAnimationEnd()
+            if (mCancelRequested) {
+                mCancelRequested = false;
+                return false;
+            } else {
+                mBoundsUpdated = true;
+                mStackBounds = stackBounds;
+                mTaskBounds = taskBounds;
+                return true;
+            }
+        }
+
+        @Override
+        public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackBounds,
+                boolean moveToFullscreen) {
+            mAnimationEnded = true;
+            mAnimationEndFinalStackBounds = finalStackBounds;
+            mSchedulePipModeChangedOnEnd = schedulePipModeChangedCallback;
+            mMovedToFullscreen = moveToFullscreen;
+            mTaskBounds = null;
+        }
+    }
+
+    /**
+     * Drives the animations, makes common assertions along the way.
+     */
+    private class BoundsAnimationDriver {
+
+        private BoundsAnimationController mController;
+        private TestBoundsAnimationTarget mTarget;
+        private BoundsAnimator mAnimator;
+
+        private Rect mFrom;
+        private Rect mTo;
+        private Rect mLargerBounds;
+        private Rect mExpectedFinalBounds;
+
+        BoundsAnimationDriver(BoundsAnimationController controller,
+                TestBoundsAnimationTarget target) {
+            mController = controller;
+            mTarget = target;
+        }
+
+        BoundsAnimationDriver start(Rect from, Rect to) {
+            if (mAnimator != null) {
+                throw new IllegalArgumentException("Call restart() to restart an animation");
+            }
+
+            mTarget.initialize(from);
+
+            // Started, not running
+            assertTrue(mTarget.mAwaitingAnimationStart);
+            assertTrue(!mTarget.mAnimationStarted);
+
+            startImpl(from, to);
+
+            // Started and running
+            assertTrue(!mTarget.mAwaitingAnimationStart);
+            assertTrue(mTarget.mAnimationStarted);
+
+            return this;
+        }
+
+        BoundsAnimationDriver restart(Rect to) {
+            if (mAnimator == null) {
+                throw new IllegalArgumentException("Call start() to start a new animation");
+            }
+
+            BoundsAnimator oldAnimator = mAnimator;
+            boolean toSameBounds = mAnimator.isStarted() && to.equals(mTo);
+
+            // Reset the animation start state
+            mTarget.mAnimationStarted = false;
+
+            // Start animation
+            startImpl(mTarget.mStackBounds, to);
+
+            if (toSameBounds) {
+                // Same animator if same final bounds
+                assertSame(oldAnimator, mAnimator);
+            }
+
+            // No animation start for replacing animation
+            assertTrue(!mTarget.mAnimationStarted);
+            mTarget.mAnimationStarted = true;
+            return this;
+        }
+
+        private BoundsAnimationDriver startImpl(Rect from, Rect to) {
+            boolean fromFullscreen = from.equals(BOUNDS_FULL);
+            boolean toFullscreen = to.equals(BOUNDS_FULL);
+            mFrom = new Rect(from);
+            mTo = new Rect(to);
+            mExpectedFinalBounds = new Rect(to);
+            mLargerBounds = getLargerBounds(mFrom, mTo);
+
+            // Start animation
+            final @SchedulePipModeChangedState int schedulePipModeChangedState = toFullscreen
+                    ? SCHEDULE_PIP_MODE_CHANGED_ON_START
+                    : fromFullscreen
+                            ? SCHEDULE_PIP_MODE_CHANGED_ON_END
+                            : NO_PIP_MODE_CHANGED_CALLBACKS;
+            mAnimator = mController.animateBoundsImpl(mTarget, from, to, DURATION,
+                    schedulePipModeChangedState, toFullscreen);
+
+            // Original stack bounds, frozen task bounds
+            assertEquals(mFrom, mTarget.mStackBounds);
+            assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
+
+            // Animating to larger size
+            if (mFrom.equals(mLargerBounds)) {
+                assertTrue(!mAnimator.animatingToLargerSize());
+            } else if (mTo.equals(mLargerBounds)) {
+                assertTrue(mAnimator.animatingToLargerSize());
+            }
+
+            return this;
+        }
+
+        BoundsAnimationDriver expectStarted(boolean schedulePipModeChanged) {
+            // Callback made
+            assertTrue(mTarget.mAnimationStarted);
+
+            assertEquals(schedulePipModeChanged, mTarget.mSchedulePipModeChangedOnStart);
+            return this;
+        }
+
+        BoundsAnimationDriver update(float t) {
+            mAnimator.onAnimationUpdate(mMockAnimator.getWithValue(t));
+
+            // Temporary stack bounds, frozen task bounds
+            if (t == 0f) {
+                assertEquals(mFrom, mTarget.mStackBounds);
+            } else if (t == 1f) {
+                assertEquals(mTo, mTarget.mStackBounds);
+            } else {
+                assertNotEquals(mFrom, mTarget.mStackBounds);
+                assertNotEquals(mTo, mTarget.mStackBounds);
+            }
+            assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
+            return this;
+        }
+
+        BoundsAnimationDriver cancel() {
+            // Cancel
+            mTarget.mCancelRequested = true;
+            mTarget.mBoundsUpdated = false;
+            mExpectedFinalBounds = null;
+
+            // Update
+            mAnimator.onAnimationUpdate(mMockAnimator.getWithValue(0.5f));
+
+            // Not started, not running, cancel reset
+            assertTrue(!mTarget.mCancelRequested);
+
+            // Stack/task bounds not updated
+            assertTrue(!mTarget.mBoundsUpdated);
+
+            // Callback made
+            assertTrue(mTarget.mAnimationEnded);
+            assertNull(mTarget.mAnimationEndFinalStackBounds);
+
+            return this;
+        }
+
+        BoundsAnimationDriver end() {
+            mAnimator.end();
+
+            // Final stack bounds
+            assertEquals(mTo, mTarget.mStackBounds);
+            assertEquals(mExpectedFinalBounds, mTarget.mAnimationEndFinalStackBounds);
+            assertNull(mTarget.mTaskBounds);
+
+            return this;
+        }
+
+        BoundsAnimationDriver expectEnded(boolean schedulePipModeChanged,
+                boolean moveToFullscreen) {
+            // Callback made
+            assertTrue(mTarget.mAnimationEnded);
+
+            assertEquals(schedulePipModeChanged, mTarget.mSchedulePipModeChangedOnEnd);
+            assertEquals(moveToFullscreen, mTarget.mMovedToFullscreen);
+            return this;
+        }
+
+        private Rect getLargerBounds(Rect r1, Rect r2) {
+            int r1Area = r1.width() * r1.height();
+            int r2Area = r2.width() * r2.height();
+            if (r1Area <= r2Area) {
+                return r2;
+            } else {
+                return r1;
+            }
+        }
+    }
+
+    // Constants
+    private static final boolean SCHEDULE_PIP_MODE_CHANGED = true;
+    private static final boolean MOVE_TO_FULLSCREEN = true;
+    private static final int DURATION = 100;
+
+    // Some dummy bounds to represent fullscreen and floating bounds
+    private static final Rect BOUNDS_FULL = new Rect(0, 0, 100, 100);
+    private static final Rect BOUNDS_FLOATING = new Rect(60, 60, 95, 95);
+    private static final Rect BOUNDS_SMALLER_FLOATING = new Rect(80, 80, 95, 95);
+
+    // Common
+    private MockAppTransition mMockAppTransition;
+    private MockValueAnimator mMockAnimator;
+    private TestBoundsAnimationTarget mTarget;
+    private BoundsAnimationController mController;
+    private BoundsAnimationDriver mDriver;
+
+    // Temp
+    private Rect mTmpRect = new Rect();
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        final Context context = InstrumentationRegistry.getTargetContext();
+        final Handler handler = new Handler(Looper.getMainLooper());
+        mMockAppTransition = new MockAppTransition(context);
+        mMockAnimator = new MockValueAnimator();
+        mTarget = new TestBoundsAnimationTarget();
+        mController = new BoundsAnimationController(context, mMockAppTransition, handler);
+        mDriver = new BoundsAnimationDriver(mController, mTarget);
+    }
+
+    /** BASE TRANSITIONS **/
+
+    @UiThreadTest
+    @Test
+    public void testFullscreenToFloatingTransition() throws Exception {
+        mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0f)
+                .update(0.5f)
+                .update(1f)
+                .end()
+                .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFloatingToFullscreenTransition() throws Exception {
+        mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+                .expectStarted(SCHEDULE_PIP_MODE_CHANGED)
+                .update(0f)
+                .update(0.5f)
+                .update(1f)
+                .end()
+                .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFloatingToSmallerFloatingTransition() throws Exception {
+        mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0f)
+                .update(0.5f)
+                .update(1f)
+                .end()
+                .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFloatingToLargerFloatingTransition() throws Exception {
+        mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0f)
+                .update(0.5f)
+                .update(1f)
+                .end()
+                .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    /** F->!F w/ CANCEL **/
+
+    @UiThreadTest
+    @Test
+    public void testFullscreenToFloatingCancelFromTarget() throws Exception {
+        mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .cancel()
+                .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFullscreenToFloatingCancelFromAnimationToSameBounds() throws Exception {
+        mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .restart(BOUNDS_FLOATING)
+                .end()
+                .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFullscreenToFloatingCancelFromAnimationToFloatingBounds() throws Exception {
+        mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .restart(BOUNDS_SMALLER_FLOATING)
+                .end()
+                .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFullscreenToFloatingCancelFromAnimationToFullscreenBounds() throws Exception {
+        mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .restart(BOUNDS_FULL)
+                .end()
+                .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, MOVE_TO_FULLSCREEN);
+    }
+
+    /** !F->F w/ CANCEL **/
+
+    @UiThreadTest
+    @Test
+    public void testFloatingToFullscreenCancelFromTarget() throws Exception {
+        mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+                .expectStarted(SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .cancel()
+                .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFloatingToFullscreenCancelFromAnimationToSameBounds() throws Exception {
+        mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+                .expectStarted(SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .restart(BOUNDS_FULL)
+                .end()
+                .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFloatingToFullscreenCancelFromAnimationToFloatingBounds() throws Exception {
+        mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+                .expectStarted(SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .restart(BOUNDS_SMALLER_FLOATING)
+                .end()
+                .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    /** !F->!F w/ CANCEL **/
+
+    @UiThreadTest
+    @Test
+    public void testFloatingToSmallerFloatingCancelFromTarget() throws Exception {
+        mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .cancel()
+                .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testFloatingToLargerFloatingCancelFromTarget() throws Exception {
+        mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING)
+                .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+                .update(0.25f)
+                .cancel()
+                .expectEnded(!SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+    }
+
+    /** MISC **/
+
+    @UiThreadTest
+    @Test
+    public void testBoundsAreCopied() throws Exception {
+        Rect from = new Rect(0, 0, 100, 100);
+        Rect to = new Rect(25, 25, 75, 75);
+        mDriver.start(from, to)
+                .update(0.25f)
+                .end();
+        assertEquals(new Rect(0, 0, 100, 100), from);
+        assertEquals(new Rect(25, 25, 75, 75), to);
+    }
+
+    /**
+     * @return whether the task and stack bounds would be the same if they were at the same offset.
+     */
+    private boolean assertEqualSizeAtOffset(Rect stackBounds, Rect taskBounds) {
+        mTmpRect.set(taskBounds);
+        mTmpRect.offsetTo(stackBounds.left, stackBounds.top);
+        return stackBounds.equals(mTmpRect);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 0270bb9..837ce56 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -289,6 +290,24 @@
         verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity);
     }
 
+    /**
+     * This test enforces that the pinned stack is always kept as the top stack.
+     */
+    @Test
+    public void testPinnedStackLocation() {
+        createStackControllerOnStackOnDisplay(PINNED_STACK_ID, sDisplayContent);
+        final int initialStackCount = sDisplayContent.getStackCount();
+        // Ensure that the pinned stack was placed at the end
+        assertEquals(initialStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID));
+        // By default, this should try to create a new stack on top
+        createTaskStackOnDisplay(sDisplayContent);
+        final int afterStackCount = sDisplayContent.getStackCount();
+        // Make sure the stack count has increased
+        assertEquals(initialStackCount + 1, afterStackCount);
+        // Ensure that the pinned stack is still on top
+        assertEquals(afterStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID));
+    }
+
     private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
                              int expectedBaseHeight, int expectedBaseDensity) {
         assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index fbeda0a..9392e8e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -90,6 +90,7 @@
                     return null;
                 }).when(am).notifyKeyguardFlagsChanged(any());
             }
+
             sWm = WindowManagerService.main(context, mock(InputManagerService.class), true, false,
                     false, new TestWindowManagerPolicy());
         }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 3a44357..ae3eb52 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -48,6 +48,13 @@
     }
 
     /**
+     * Retrieves an instance of a mock {@link WindowManagerService}.
+     */
+    public static WindowManagerService getMockWindowManagerService() {
+        return mock(WindowManagerService.class);
+    }
+
+    /**
      * Creates a mock instance of {@link StackWindowController}.
      */
     public static StackWindowController createMockStackWindowContainerController() {
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 5ad7f80..094c7bd 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -35,6 +35,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelableException;
 import android.os.StatFs;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -150,7 +151,7 @@
         try {
             return mInstaller.isQuotaSupported(volumeUuid);
         } catch (InstallerException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(new IOException(e.getMessage()));
         }
     }
 
@@ -163,7 +164,8 @@
         } else {
             final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
             if (vol == null) {
-                throw new IllegalStateException("Volume was unexpected null");
+                throw new ParcelableException(
+                        new IOException("Failed to find storage device for UUID " + volumeUuid));
             }
             return FileUtils.roundStorageSize(vol.disk.size);
         }
@@ -189,7 +191,8 @@
         } else {
             final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
             if (vol == null) {
-                throw new IllegalStateException("Volume was unexpected null");
+                throw new ParcelableException(
+                        new IOException("Failed to find storage device for UUID " + volumeUuid));
             }
             return vol.getPath().getUsableSpace() + cacheBytes;
         }
@@ -221,7 +224,7 @@
             appInfo = mPackage.getApplicationInfoAsUser(packageName,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
         } catch (NameNotFoundException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(e);
         }
 
         if (mPackage.getPackagesForUid(appInfo.uid).length == 1) {
@@ -239,7 +242,7 @@
                 mInstaller.getAppSize(volumeUuid, packageNames, userId, 0,
                         appId, ceDataInodes, codePaths, stats);
             } catch (InstallerException e) {
-                throw new IllegalStateException(e);
+                throw new ParcelableException(new IOException(e.getMessage()));
             }
             return translate(stats);
         }
@@ -265,7 +268,7 @@
                 codePaths[i] = mPackage.getApplicationInfoAsUser(packageNames[i],
                         PackageManager.MATCH_UNINSTALLED_PACKAGES, userId).getCodePath();
             } catch (NameNotFoundException e) {
-                throw new IllegalStateException(e);
+                throw new ParcelableException(e);
             }
         }
 
@@ -281,7 +284,7 @@
                 checkEquals("UID " + uid, manualStats, stats);
             }
         } catch (InstallerException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(new IOException(e.getMessage()));
         }
         return translate(stats);
     }
@@ -313,7 +316,7 @@
                 checkEquals("User " + userId, manualStats, stats);
             }
         } catch (InstallerException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(new IOException(e.getMessage()));
         }
         return translate(stats);
     }
@@ -336,7 +339,7 @@
                 checkEquals("External " + userId, manualStats, stats);
             }
         } catch (InstallerException e) {
-            throw new IllegalStateException(e);
+            throw new ParcelableException(new IOException(e.getMessage()));
         }
 
         final ExternalStorageStats res = new ExternalStorageStats();
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
index f560e71..f6d212b 100644
--- a/services/usb/Android.mk
+++ b/services/usb/Android.mk
@@ -8,7 +8,7 @@
       $(call all-java-files-under,java)
 
 LOCAL_JAVA_LIBRARIES := services.core
-LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb@1.0-java-static \
-android.hidl.manager@1.0-java-static
+LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java-static \
+android.hidl.manager-V1.0-java-static
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b98febe..b2becc9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -135,6 +135,7 @@
     private static final int MSG_ACCESSORY_MODE_ENTER_TIMEOUT = 8;
     private static final int MSG_UPDATE_CHARGING_STATE = 9;
     private static final int MSG_UPDATE_HOST_STATE = 10;
+    private static final int MSG_LOCALE_CHANGED = 11;
 
     private static final int AUDIO_MODE_SOURCE = 1;
 
@@ -255,6 +256,13 @@
         }
     };
 
+    private final BroadcastReceiver mLanguageChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mHandler.sendEmptyMessage(MSG_LOCALE_CHANGED);
+        }
+    };
+
     public UsbDeviceManager(Context context, UsbAlsaManager alsaManager,
             UsbSettingsManager settingsManager) {
         mContext = context;
@@ -288,6 +296,9 @@
                 new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
         filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
         mContext.registerReceiver(mHostReceiver, filter);
+
+        mContext.registerReceiver(mLanguageChangedReceiver,
+                new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
     }
 
     private UsbProfileGroupSettingsManager getCurrentSettings() {
@@ -593,7 +604,7 @@
                 }
 
                 setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked);
-                updateAdbNotification();
+                updateAdbNotification(false);
             }
 
             if (mDebuggingManager != null) {
@@ -613,7 +624,7 @@
 
             if (usbDataUnlocked != mUsbDataUnlocked) {
                 mUsbDataUnlocked = usbDataUnlocked;
-                updateUsbNotification();
+                updateUsbNotification(false);
                 forceRestart = true;
             }
 
@@ -893,8 +904,8 @@
                     mConnected = (msg.arg1 == 1);
                     mConfigured = (msg.arg2 == 1);
 
-                    updateUsbNotification();
-                    updateAdbNotification();
+                    updateUsbNotification(false);
+                    updateAdbNotification(false);
                     if (UsbManager.containsFunction(mCurrentFunctions,
                             UsbManager.USB_FUNCTION_ACCESSORY)) {
                         updateCurrentAccessory();
@@ -917,7 +928,7 @@
                     mSinkPower = (args.argi3 == 1);
                     mSupportsAllCombinations = (args.argi4 == 1);
                     args.recycle();
-                    updateUsbNotification();
+                    updateUsbNotification(false);
                     if (mBootCompleted) {
                         updateUsbStateBroadcastIfNeeded(false);
                     } else {
@@ -926,7 +937,7 @@
                     break;
                 case MSG_UPDATE_CHARGING_STATE:
                     mUsbCharging = (msg.arg1 == 1);
-                    updateUsbNotification();
+                    updateUsbNotification(false);
                     break;
                 case MSG_UPDATE_HOST_STATE:
                     Iterator devices = (Iterator) msg.obj;
@@ -963,7 +974,7 @@
                             }
                         }
                     }
-                    updateUsbNotification();
+                    updateUsbNotification(false);
                     break;
                 case MSG_ENABLE_ADB:
                     setAdbEnabled(msg.arg1 == 1);
@@ -981,10 +992,14 @@
                             mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart);
                     break;
                 case MSG_SYSTEM_READY:
-                    updateUsbNotification();
-                    updateAdbNotification();
+                    updateUsbNotification(false);
+                    updateAdbNotification(false);
                     updateUsbFunctions();
                     break;
+                case MSG_LOCALE_CHANGED:
+                    updateAdbNotification(true);
+                    updateUsbNotification(true);
+                    break;
                 case MSG_BOOT_COMPLETED:
                     mBootCompleted = true;
                     if (mPendingBootBroadcast) {
@@ -1035,7 +1050,7 @@
             return mCurrentAccessory;
         }
 
-        private void updateUsbNotification() {
+        private void updateUsbNotification(boolean force) {
             if (mNotificationManager == null || !mUseUsbNotification
                     || ("0".equals(SystemProperties.get("persist.charging.notify")))
                     // Dont show the notification when connected to a USB peripheral
@@ -1085,7 +1100,7 @@
                 titleRes = com.android.internal.R.string.usb_charging_notification_title;
                 id = SystemMessage.NOTE_USB_CHARGING;
             }
-            if (id != mUsbNotificationId) {
+            if (id != mUsbNotificationId || force) {
                 // clear notification if title needs changing
                 if (mUsbNotificationId != 0) {
                     mNotificationManager.cancelAsUser(null, mUsbNotificationId,
@@ -1125,13 +1140,19 @@
             }
         }
 
-        private void updateAdbNotification() {
+        private void updateAdbNotification(boolean force) {
             if (mNotificationManager == null) return;
             final int id = SystemMessage.NOTE_ADB_ACTIVE;
             final int titleRes = com.android.internal.R.string.adb_active_notification_title;
+
             if (mAdbEnabled && mConnected) {
                 if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
 
+                if (force && mAdbNotificationShown) {
+                    mAdbNotificationShown = false;
+                    mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
+                }
+
                 if (!mAdbNotificationShown) {
                     Resources r = mContext.getResources();
                     CharSequence title = r.getText(titleRes);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 1aa952cd..cb44471 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -300,7 +300,11 @@
 
             // Load the model if it is not loaded.
             if (!modelData.isModelLoaded()) {
-                // Load the model
+                // Before we try and load this model, we should first make sure that any other
+                // models that don't have an active recognition/dead callback are unloaded. Since
+                // there is a finite limit on the number of models that the hardware may be able to
+                // have loaded, we want to make sure there's room for our model.
+                stopAndUnloadDeadModelsLocked();
                 int[] handle = new int[] { INVALID_VALUE };
                 int status = mModule.loadSoundModel(soundModel, handle);
                 if (status != SoundTrigger.STATUS_OK) {
@@ -899,7 +903,29 @@
         }
     }
 
+    /**
+     * Stops and unloads a sound model, and removes any reference to the model if successful.
+     *
+     * @param modelData The model data to remove.
+     * @param exception Optional exception to print in logcat. May be null.
+     */
     private void forceStopAndUnloadModel(ModelData modelData, Exception exception) {
+      forceStopAndUnloadModel(modelData, exception, null /* modelDataIterator */);
+    }
+
+    /**
+     * Stops and unloads a sound model, and removes any reference to the model if successful.
+     *
+     * @param modelData The model data to remove.
+     * @param exception Optional exception to print in logcat. May be null.
+     * @param modelDataIterator If this function is to be used while iterating over the
+     *        mModelDataMap, you can provide the iterator for the current model data to be used to
+     *        remove the modelData from the map. This avoids generating a
+     *        ConcurrentModificationException, since this function will try and remove the model
+     *        data from the mModelDataMap when it can successfully unload the model.
+     */
+    private void forceStopAndUnloadModel(ModelData modelData, Exception exception,
+            Iterator modelDataIterator) {
         if (exception != null) {
           Slog.e(TAG, "forceStopAndUnloadModel", exception);
         }
@@ -916,7 +942,11 @@
             Slog.d(TAG, "Unloading previously loaded dangling model " + modelData.getHandle());
             if (mModule.unloadSoundModel(modelData.getHandle()) == STATUS_OK) {
                 // Remove the model data from existence.
-                mModelDataMap.remove(modelData.getModelId());
+                if (modelDataIterator != null) {
+                    modelDataIterator.remove();
+                } else {
+                    mModelDataMap.remove(modelData.getModelId());
+                }
                 Iterator it = mKeyphraseUuidMap.entrySet().iterator();
                 while (it.hasNext()) {
                     Map.Entry pair = (Map.Entry) it.next();
@@ -931,6 +961,23 @@
         }
     }
 
+    private void stopAndUnloadDeadModelsLocked() {
+        Iterator it = mModelDataMap.entrySet().iterator();
+        while (it.hasNext()) {
+            ModelData modelData = (ModelData) ((Map.Entry) it.next()).getValue();
+            if (!modelData.isModelLoaded()) {
+                continue;
+            }
+            if (modelData.getCallback() == null
+                    || (modelData.getCallback().asBinder() != null
+                        && !modelData.getCallback().asBinder().pingBinder())) {
+                // No one is listening on this model, so we might as well evict it.
+                Slog.w(TAG, "Removing model " + modelData.getHandle() + " that has no clients");
+                forceStopAndUnloadModel(modelData, null /* exception */, it);
+            }
+        }
+    }
+
     private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
         ModelData modelData = mModelDataMap.get(modelId);
         if (modelData == null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index dc4b41c..6c4ced4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -302,9 +302,13 @@
                 ComponentName curInteractor = !TextUtils.isEmpty(curInteractorStr)
                         ? ComponentName.unflattenFromString(curInteractorStr) : null;
                 try {
-                    recognizerInfo = pm.getServiceInfo(curRecognizer, 0, userHandle);
+                    recognizerInfo = pm.getServiceInfo(curRecognizer,
+                            PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
                     if (curInteractor != null) {
-                        interactorInfo = pm.getServiceInfo(curInteractor, 0, userHandle);
+                        interactorInfo = pm.getServiceInfo(curInteractor,
+                                PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
                     }
                 } catch (RemoteException e) {
                 }
@@ -492,7 +496,9 @@
         ComponentName findAvailRecognizer(String prefPackage, int userHandle) {
             List<ResolveInfo> available =
                     mContext.getPackageManager().queryIntentServicesAsUser(
-                            new Intent(RecognitionService.SERVICE_INTERFACE), 0, userHandle);
+                            new Intent(RecognitionService.SERVICE_INTERFACE),
+                            PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
             int numAvailable = available.size();
 
             if (numAvailable == 0) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 47f3fbe..852610e 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -112,20 +112,26 @@
             "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
 
     /**
-     * The {@link android.content.Intent} action used indicate that a new phone account was
-     * just registered.
-     * @hide
+     * {@link android.content.Intent} action used indicate that a new phone account was just
+     * registered.
+     * <p>
+     * The Intent {@link Intent#getExtras() extras} will contain {@link #EXTRA_PHONE_ACCOUNT_HANDLE}
+     * to indicate which {@link PhoneAccount} was registered.
+     * <p>
+     * Will only be sent to the default dialer app (see {@link #getDefaultDialerPackage()}).
      */
-    @SystemApi
     public static final String ACTION_PHONE_ACCOUNT_REGISTERED =
             "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
 
     /**
-     * The {@link android.content.Intent} action used indicate that a phone account was
-     * just unregistered.
-     * @hide
+     * {@link android.content.Intent} action used indicate that a phone account was just
+     * unregistered.
+     * <p>
+     * The Intent {@link Intent#getExtras() extras} will contain {@link #EXTRA_PHONE_ACCOUNT_HANDLE}
+     * to indicate which {@link PhoneAccount} was unregistered.
+     * <p>
+     * Will only be sent to the default dialer app (see {@link #getDefaultDialerPackage()}).
      */
-    @SystemApi
     public static final String ACTION_PHONE_ACCOUNT_UNREGISTERED =
             "android.telecom.action.PHONE_ACCOUNT_UNREGISTERED";
 
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
index 943a6ca..eeaf2c1 100644
--- a/telephony/java/android/telephony/Telephony.java
+++ b/telephony/java/android/telephony/Telephony.java
@@ -19,18 +19,21 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.TestApi;
+import android.app.job.JobService;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
+import android.database.ContentObserver;
 import android.database.sqlite.SqliteWrapper;
 import android.net.Uri;
+import android.telephony.Rlog;
+import android.telephony.ServiceState;
 import android.telephony.SmsMessage;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
-import android.telephony.Rlog;
 import android.util.Patterns;
 
 import com.android.internal.telephony.PhoneConstants;
@@ -44,7 +47,7 @@
 
 /**
  * The Telephony provider contains data related to phone operation, specifically SMS and MMS
- * messages and access to the APN list, including the MMSC to use.
+ * messages, access to the APN list, including the MMSC to use, and the service state.
  *
  * <p class="note"><strong>Note:</strong> These APIs are not available on all Android-powered
  * devices. If your app depends on telephony features such as for managing SMS messages, include
@@ -2972,4 +2975,272 @@
                 CMAS_CERTAINTY
         };
     }
+
+    /**
+     * Constants for interfacing with the ServiceStateProvider and the different fields of the
+     * {@link ServiceState} class accessible through the provider.
+     */
+    public static final class ServiceStateTable {
+
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private ServiceStateTable() {}
+
+        /**
+         * The authority string for the ServiceStateProvider
+         */
+        public static final String AUTHORITY = "service-state";
+
+        /**
+         * The {@code content://} style URL for the ServiceStateProvider
+         */
+        public static final Uri CONTENT_URI = Uri.parse("content://service-state/");
+
+        /**
+         * Generates a content {@link Uri} used to receive updates on a specific field in the
+         * ServiceState provider.
+         * <p>
+         * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+         * {@link ServiceState} while your app is running.  You can also use a {@link JobService} to
+         * ensure your app is notified of changes to the {@link Uri} even when it is not running.
+         * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+         * updates to the {@link Uri}.
+         *
+         * @param subId the subId to receive updates on
+         * @param field the ServiceState field to receive updates on
+         * @return the Uri used to observe {@link ServiceState} changes
+         */
+        public static Uri getUriForSubIdAndField(int subId, String field) {
+            return CONTENT_URI.buildUpon().appendEncodedPath(String.valueOf(subId))
+                    .appendEncodedPath(field).build();
+        }
+
+        /**
+         * Generates a content {@link Uri} used to receive updates on every field in the
+         * ServiceState provider.
+         * <p>
+         * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+         * {@link ServiceState} while your app is running.  You can also use a {@link JobService} to
+         * ensure your app is notified of changes to the {@link Uri} even when it is not running.
+         * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+         * updates to the {@link Uri}.
+         *
+         * @param subId the subId to receive updates on
+         * @return the Uri used to observe {@link ServiceState} changes
+         */
+        public static Uri getUriForSubId(int subId) {
+            return CONTENT_URI.buildUpon().appendEncodedPath(String.valueOf(subId)).build();
+        }
+
+        /**
+         * Used to insert a ServiceState into the ServiceStateProvider as a ContentValues instance.
+         *
+         * @param state the ServiceState to convert into ContentValues
+         * @return the convertedContentValues instance
+         * @hide
+         */
+        public static ContentValues getContentValuesForServiceState(ServiceState state) {
+            ContentValues values = new ContentValues();
+            values.put(VOICE_REG_STATE, state.getVoiceRegState());
+            values.put(DATA_REG_STATE, state.getDataRegState());
+            values.put(VOICE_ROAMING_TYPE, state.getVoiceRoamingType());
+            values.put(DATA_ROAMING_TYPE, state.getDataRoamingType());
+            values.put(VOICE_OPERATOR_ALPHA_LONG, state.getVoiceOperatorAlphaLong());
+            values.put(VOICE_OPERATOR_ALPHA_SHORT, state.getVoiceOperatorAlphaShort());
+            values.put(VOICE_OPERATOR_NUMERIC, state.getVoiceOperatorNumeric());
+            values.put(DATA_OPERATOR_ALPHA_LONG, state.getDataOperatorAlphaLong());
+            values.put(DATA_OPERATOR_ALPHA_SHORT, state.getDataOperatorAlphaShort());
+            values.put(DATA_OPERATOR_NUMERIC, state.getDataOperatorNumeric());
+            values.put(IS_MANUAL_NETWORK_SELECTION, state.getIsManualSelection());
+            values.put(RIL_VOICE_RADIO_TECHNOLOGY, state.getRilVoiceRadioTechnology());
+            values.put(RIL_DATA_RADIO_TECHNOLOGY, state.getRilDataRadioTechnology());
+            values.put(CSS_INDICATOR, state.getCssIndicator());
+            values.put(NETWORK_ID, state.getNetworkId());
+            values.put(SYSTEM_ID, state.getSystemId());
+            values.put(CDMA_ROAMING_INDICATOR, state.getCdmaRoamingIndicator());
+            values.put(CDMA_DEFAULT_ROAMING_INDICATOR, state.getCdmaDefaultRoamingIndicator());
+            values.put(CDMA_ERI_ICON_INDEX, state.getCdmaEriIconIndex());
+            values.put(CDMA_ERI_ICON_MODE, state.getCdmaEriIconMode());
+            values.put(IS_EMERGENCY_ONLY, state.isEmergencyOnly());
+            values.put(IS_DATA_ROAMING_FROM_REGISTRATION, state.getDataRoamingFromRegistration());
+            values.put(IS_USING_CARRIER_AGGREGATION, state.isUsingCarrierAggregation());
+            return values;
+        }
+
+        /**
+         * An integer value indicating the current voice service state.
+         * <p>
+         * Valid values: {@link ServiceState#STATE_IN_SERVICE},
+         * {@link ServiceState#STATE_OUT_OF_SERVICE}, {@link ServiceState#STATE_EMERGENCY_ONLY},
+         * {@link ServiceState#STATE_POWER_OFF}.
+         * <p>
+         * This is the same as {@link ServiceState#getState()}.
+         */
+        public static final String VOICE_REG_STATE = "voice_reg_state";
+
+        /**
+         * An integer value indicating the current data service state.
+         * <p>
+         * Valid values: {@link ServiceState#STATE_IN_SERVICE},
+         * {@link ServiceState#STATE_OUT_OF_SERVICE}, {@link ServiceState#STATE_EMERGENCY_ONLY},
+         * {@link ServiceState#STATE_POWER_OFF}.
+         * <p>
+         * This is the same as {@link ServiceState#getDataRegState()}.
+         * @hide
+         */
+        public static final String DATA_REG_STATE = "data_reg_state";
+
+        /**
+         * An integer value indicating the current voice roaming type.
+         * <p>
+         * This is the same as {@link ServiceState#getVoiceRoamingType()}.
+         * @hide
+         */
+        public static final String VOICE_ROAMING_TYPE = "voice_roaming_type";
+
+        /**
+         * An integer value indicating the current data roaming type.
+         * <p>
+         * This is the same as {@link ServiceState#getDataRoamingType()}.
+         * @hide
+         */
+        public static final String DATA_ROAMING_TYPE = "data_roaming_type";
+
+        /**
+         * The current registered voice network operator name in long alphanumeric format.
+         * <p>
+         * This is the same as {@link ServiceState#getVoiceOperatorAlphaLong()}.
+         * @hide
+         */
+        public static final String VOICE_OPERATOR_ALPHA_LONG = "voice_operator_alpha_long";
+
+        /**
+         * The current registered operator name in short alphanumeric format.
+         * <p>
+         * In GSM/UMTS, short format can be up to 8 characters long. The current registered voice
+         * network operator name in long alphanumeric format.
+         * <p>
+         * This is the same as {@link ServiceState#getVoiceOperatorAlphaShort()}.
+         * @hide
+         */
+        public static final String VOICE_OPERATOR_ALPHA_SHORT = "voice_operator_alpha_short";
+
+
+        /**
+         * The current registered operator numeric id.
+         * <p>
+         * In GSM/UMTS, numeric format is 3 digit country code plus 2 or 3 digit
+         * network code.
+         * <p>
+         * This is the same as {@link ServiceState#getOperatorNumeric()}.
+         */
+        public static final String VOICE_OPERATOR_NUMERIC = "voice_operator_numeric";
+
+        /**
+         * The current registered data network operator name in long alphanumeric format.
+         * <p>
+         * This is the same as {@link ServiceState#getDataOperatorAlphaLong()}.
+         * @hide
+         */
+        public static final String DATA_OPERATOR_ALPHA_LONG = "data_operator_alpha_long";
+
+        /**
+         * The current registered data network operator name in short alphanumeric format.
+         * <p>
+         * This is the same as {@link ServiceState#getDataOperatorAlphaShort()}.
+         * @hide
+         */
+        public static final String DATA_OPERATOR_ALPHA_SHORT = "data_operator_alpha_short";
+
+        /**
+         * The current registered data network operator numeric id.
+         * <p>
+         * This is the same as {@link ServiceState#getDataOperatorNumeric()}.
+         * @hide
+         */
+        public static final String DATA_OPERATOR_NUMERIC = "data_operator_numeric";
+
+        /**
+         * The current network selection mode.
+         * <p>
+         * This is the same as {@link ServiceState#getIsManualSelection()}.
+         */
+        public static final String IS_MANUAL_NETWORK_SELECTION = "is_manual_network_selection";
+
+        /**
+         * This is the same as {@link ServiceState#getRilVoiceRadioTechnology()}.
+         * @hide
+         */
+        public static final String RIL_VOICE_RADIO_TECHNOLOGY = "ril_voice_radio_technology";
+
+        /**
+         * This is the same as {@link ServiceState#getRilDataRadioTechnology()}.
+         * @hide
+         */
+        public static final String RIL_DATA_RADIO_TECHNOLOGY = "ril_data_radio_technology";
+
+        /**
+         * This is the same as {@link ServiceState#getCssIndicator()}.
+         * @hide
+         */
+        public static final String CSS_INDICATOR = "css_indicator";
+
+        /**
+         * This is the same as {@link ServiceState#getNetworkId()}.
+         * @hide
+         */
+        public static final String NETWORK_ID = "network_id";
+
+        /**
+         * This is the same as {@link ServiceState#getSystemId()}.
+         * @hide
+         */
+        public static final String SYSTEM_ID = "system_id";
+
+        /**
+         * This is the same as {@link ServiceState#getCdmaRoamingIndicator()}.
+         * @hide
+         */
+        public static final String CDMA_ROAMING_INDICATOR = "cdma_roaming_indicator";
+
+        /**
+         * This is the same as {@link ServiceState#getCdmaDefaultRoamingIndicator()}.
+         * @hide
+         */
+        public static final String CDMA_DEFAULT_ROAMING_INDICATOR =
+                "cdma_default_roaming_indicator";
+
+        /**
+         * This is the same as {@link ServiceState#getCdmaEriIconIndex()}.
+         * @hide
+         */
+        public static final String CDMA_ERI_ICON_INDEX = "cdma_eri_icon_index";
+
+        /**
+         * This is the same as {@link ServiceState#getCdmaEriIconMode()}.
+         * @hide
+         */
+        public static final String CDMA_ERI_ICON_MODE = "cdma_eri_icon_mode";
+
+        /**
+         * This is the same as {@link ServiceState#isEmergencyOnly()}.
+         * @hide
+         */
+        public static final String IS_EMERGENCY_ONLY = "is_emergency_only";
+
+        /**
+         * This is the same as {@link ServiceState#getDataRoamingFromRegistration()}.
+         * @hide
+         */
+        public static final String IS_DATA_ROAMING_FROM_REGISTRATION =
+                "is_data_roaming_from_registration";
+
+        /**
+         * This is the same as {@link ServiceState#isUsingCarrierAggregation()}.
+         * @hide
+         */
+        public static final String IS_USING_CARRIER_AGGREGATION = "is_using_carrier_aggregation";
+    }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d60f25c..8ee6454 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -911,7 +911,7 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getDeviceSoftwareVersion() {
-        return getDeviceSoftwareVersion(getDefaultSim());
+        return getDeviceSoftwareVersion(getSlotIndex());
     }
 
     /**
@@ -997,7 +997,7 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getImei() {
-        return getImei(getDefaultSim());
+        return getImei(getSlotIndex());
     }
 
     /**
@@ -1029,7 +1029,7 @@
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getMeid() {
-        return getMeid(getDefaultSim());
+        return getMeid(getSlotIndex());
     }
 
     /**
@@ -1059,7 +1059,7 @@
      */
     /** {@hide}*/
     public String getNai() {
-        return getNai(getDefaultSim());
+        return getNai(getSlotIndex());
     }
 
     /**
@@ -1303,7 +1303,7 @@
     }
 
     private int getPhoneTypeFromProperty() {
-        return getPhoneTypeFromProperty(getDefaultPhone());
+        return getPhoneTypeFromProperty(getPhoneId());
     }
 
     /** {@hide} */
@@ -1317,7 +1317,7 @@
     }
 
     private int getPhoneTypeFromNetworkType() {
-        return getPhoneTypeFromNetworkType(getDefaultPhone());
+        return getPhoneTypeFromNetworkType(getPhoneId());
     }
 
     /** {@hide} */
@@ -1500,7 +1500,7 @@
      * on a CDMA network).
      */
     public String getNetworkOperator() {
-        return getNetworkOperatorForPhone(getDefaultPhone());
+        return getNetworkOperatorForPhone(getPhoneId());
     }
 
     /**
@@ -1546,7 +1546,7 @@
      * @see #createForPhoneAccountHandle(PhoneAccountHandle)
      */
     public String getNetworkSpecifier() {
-        return String.valueOf(mSubId);
+        return String.valueOf(getSubId());
     }
 
     /**
@@ -1565,7 +1565,7 @@
     public PersistableBundle getCarrierConfig() {
         CarrierConfigManager carrierConfigManager = mContext
                 .getSystemService(CarrierConfigManager.class);
-        return carrierConfigManager.getConfigForSubId(mSubId);
+        return carrierConfigManager.getConfigForSubId(getSubId());
     }
 
     /**
@@ -1602,7 +1602,7 @@
      * on a CDMA network).
      */
     public String getNetworkCountryIso() {
-        return getNetworkCountryIsoForPhone(getDefaultPhone());
+        return getNetworkCountryIsoForPhone(getPhoneId());
     }
 
     /**
@@ -1748,6 +1748,9 @@
      * Returns a constant indicating the radio technology (network type)
      * currently in use on the device for data transmission.
      *
+     * If this object has been created with {@link #createForSubscriptionId}, applies to the given
+     * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
@@ -1772,7 +1775,7 @@
      * @see #NETWORK_TYPE_HSPAP
      */
     public int getDataNetworkType() {
-        return getDataNetworkType(getSubId());
+        return getDataNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
     }
 
     /**
@@ -1996,7 +1999,7 @@
      * @return true if a ICC card is present
      */
     public boolean hasIccCard() {
-        return hasIccCard(getDefaultSim());
+        return hasIccCard(getSlotIndex());
     }
 
     /**
@@ -2037,7 +2040,7 @@
      * @see #SIM_STATE_CARD_RESTRICTED
      */
     public int getSimState() {
-        int slotIndex = getDefaultSim();
+        int slotIndex = getSlotIndex();
         // slotIndex may be invalid due to sim being absent. In that case query all slots to get
         // sim state
         if (slotIndex < 0) {
@@ -2166,7 +2169,7 @@
      * @see #getSimState
      */
     public String getSimOperatorName() {
-        return getSimOperatorNameForPhone(getDefaultPhone());
+        return getSimOperatorNameForPhone(getPhoneId());
     }
 
     /**
@@ -2198,7 +2201,7 @@
      * Returns the ISO country code equivalent for the SIM provider's country code.
      */
     public String getSimCountryIso() {
-        return getSimCountryIsoForPhone(getDefaultPhone());
+        return getSimCountryIsoForPhone(getPhoneId());
     }
 
     /**
@@ -2710,19 +2713,12 @@
      * @param phoneAccountHandle the phone account to change the client state
      * @param enabled the new state of the client
      * @hide
+     * @deprecated Visual voicemail no longer in telephony. {@link VisualVoicemailService} should
+     * be implemented instead.
      */
     @SystemApi
     public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                telephony.setVisualVoicemailEnabled(mContext.getOpPackageName(), phoneAccountHandle,
-                    enabled);
-            }
-        } catch (RemoteException ex) {
-        } catch (NullPointerException ex) {
-            // This could happen before phone restarts due to crashing
-        }
+
     }
 
     /**
@@ -2734,19 +2730,11 @@
      * @param phoneAccountHandle the phone account to check for.
      * @return {@code true} when the visual voicemail client is enabled for this client
      * @hide
+     * @deprecated Visual voicemail no longer in telephony. {@link VisualVoicemailService} should
+     * be implemented instead.
      */
     @SystemApi
     public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
-        try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                return telephony.isVisualVoicemailEnabled(
-                    mContext.getOpPackageName(), phoneAccountHandle);
-            }
-        } catch (RemoteException ex) {
-        } catch (NullPointerException ex) {
-            // This could happen before phone restarts due to crashing
-        }
         return false;
     }
 
@@ -2769,7 +2757,7 @@
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 return telephony
-                        .getVisualVoicemailPackageName(mContext.getOpPackageName(), mSubId);
+                        .getVisualVoicemailPackageName(mContext.getOpPackageName(), getSubId());
             }
         } catch (RemoteException ex) {
         } catch (NullPointerException ex) {
@@ -4072,35 +4060,67 @@
      * subId is returned. Otherwise, the default subId will be returned.
      */
     private int getSubId() {
-      if (mSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
-        return getDefaultSubscription();
+      if (SubscriptionManager.isUsableSubIdValue(mSubId)) {
+        return mSubId;
       }
-      return mSubId;
+      return SubscriptionManager.getDefaultSubscriptionId();
     }
 
     /**
-     * Returns Default subscription.
+     * Return an appropriate subscription ID for any situation.
+     *
+     * If this object has been created with {@link #createForSubscriptionId}, then the provided
+     * subId is returned. Otherwise, the preferred subId which is based on caller's context is
+     * returned.
+     * {@see SubscriptionManager#getDefaultDataSubscriptionId()}
+     * {@see SubscriptionManager#getDefaultVoiceSubscriptionId()}
+     * {@see SubscriptionManager#getDefaultSmsSubscriptionId()}
      */
-    private static int getDefaultSubscription() {
-        return SubscriptionManager.getDefaultSubscriptionId();
+    private int getSubId(int preferredSubId) {
+        if (SubscriptionManager.isUsableSubIdValue(mSubId)) {
+            return mSubId;
+        }
+        return preferredSubId;
     }
 
     /**
-     * Returns Default phone.
+     * Return an appropriate phone ID for any situation.
+     *
+     * If this object has been created with {@link #createForSubscriptionId}, then the phoneId
+     * associated with the provided subId is returned. Otherwise, the default phoneId associated
+     * with the default subId will be returned.
      */
-    private static int getDefaultPhone() {
-        return SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultSubscriptionId());
+    private int getPhoneId() {
+        return SubscriptionManager.getPhoneId(getSubId());
     }
 
     /**
-     *  @return default SIM's slot index. If SIM is not inserted, return default SIM slot index.
+     * Return an appropriate phone ID for any situation.
+     *
+     * If this object has been created with {@link #createForSubscriptionId}, then the phoneId
+     * associated with the provided subId is returned. Otherwise, return the phoneId associated
+     * with the preferred subId based on caller's context.
+     * {@see SubscriptionManager#getDefaultDataSubscriptionId()}
+     * {@see SubscriptionManager#getDefaultVoiceSubscriptionId()}
+     * {@see SubscriptionManager#getDefaultSmsSubscriptionId()}
+     */
+    private int getPhoneId(int preferredSubId) {
+        return SubscriptionManager.getPhoneId(getSubId(preferredSubId));
+    }
+
+    /**
+     * Return an appropriate slot index for any situation.
+     *
+     * if this object has been created with {@link #createForSubscriptionId}, then the slot index
+     * associated with the provided subId is returned. Otherwise, return the slot index associated
+     * with the default subId.
+     * If SIM is not inserted, return default SIM slot index.
      *
      * {@hide}
      */
     @VisibleForTesting
-    public int getDefaultSim() {
-        int slotIndex = SubscriptionManager.getSlotIndex(
-                SubscriptionManager.getDefaultSubscriptionId());
+    public int getSlotIndex() {
+        int slotIndex = SubscriptionManager.getSlotIndex(getSubId());
         if (slotIndex == SubscriptionManager.SIM_NOT_INSERTED) {
             slotIndex = SubscriptionManager.DEFAULT_SIM_SLOT_INDEX;
         }
@@ -4408,7 +4428,7 @@
      * Returns null if the query fails.
      *
      *
-     * <p>Requires that the caller has READ_PRIVILEGED_PHONE_STATE
+     * <p>Requires that the caller has READ_PHONE_STATE
      *
      * @return an array of forbidden PLMNs or null if not available
      */
@@ -4421,7 +4441,7 @@
      * Returns null if the query fails.
      *
      *
-     * <p>Requires that the calling app has READ_PRIVILEGED_PHONE_STATE
+     * <p>Requires that the calling app has READ_PHONE_STATE
      *
      * @param subId subscription ID used for authentication
      * @param appType the icc application type, like {@link #APPTYPE_USIM}
@@ -4917,7 +4937,7 @@
     /** @hide */
     @SystemApi
     public List<String> getCarrierPackageNamesForIntent(Intent intent) {
-        return getCarrierPackageNamesForIntentAndPhone(intent, getDefaultPhone());
+        return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId());
     }
 
     /** @hide */
@@ -5179,7 +5199,7 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.handleUssdRequest(mSubId, ussdRequest, wrappedCallback);
+                telephony.handleUssdRequest(getSubId(), ussdRequest, wrappedCallback);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#sendUSSDCode", e);
@@ -5199,7 +5219,8 @@
     public boolean isConcurrentVoiceAndDataSupported() {
         try {
             ITelephony telephony = getITelephony();
-            return (telephony == null ? false : telephony.isConcurrentVoiceAndDataAllowed(mSubId));
+            return (telephony == null ? false : telephony.isConcurrentVoiceAndDataAllowed(
+                    getSubId()));
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#isConcurrentVoiceAndDataAllowed", e);
         }
@@ -5336,6 +5357,8 @@
 
     /**
      * Turns mobile data on or off.
+     * If this object has been created with {@link #createForSubscriptionId}, applies to the given
+     * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *
      * <p>Requires Permission:
      *     {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
@@ -5346,7 +5369,7 @@
      * @see #hasCarrierPrivileges
      */
     public void setDataEnabled(boolean enable) {
-        setDataEnabled(getSubId(), enable);
+        setDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
     }
 
     /** @hide */
@@ -5376,6 +5399,9 @@
     /**
      * Returns whether mobile data is enabled or not.
      *
+     * If this object has been created with {@link #createForSubscriptionId}, applies to the given
+     * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+     *
      * <p>Requires one of the following permissions:
      * {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
@@ -5391,7 +5417,7 @@
      */
     @SuppressWarnings("deprecation")
     public boolean isDataEnabled() {
-        return getDataEnabled(getSubId());
+        return getDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
     }
 
     /**
@@ -5641,7 +5667,7 @@
     * @hide
     */
     public void setSimOperatorNumeric(String numeric) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setSimOperatorNumericForPhone(phoneId, numeric);
     }
 
@@ -5661,7 +5687,7 @@
      * @hide
      */
     public void setSimOperatorName(String name) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setSimOperatorNameForPhone(phoneId, name);
     }
 
@@ -5681,7 +5707,7 @@
     * @hide
     */
     public void setSimCountryIso(String iso) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setSimCountryIsoForPhone(phoneId, iso);
     }
 
@@ -5701,7 +5727,7 @@
      * @hide
      */
     public void setSimState(String state) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setSimStateForPhone(phoneId, state);
     }
 
@@ -5726,7 +5752,7 @@
      * @hide
      **/
     public void setSimPowerState(boolean powerUp) {
-        setSimPowerStateForSlot(getDefaultSim(), powerUp);
+        setSimPowerStateForSlot(getSlotIndex(), powerUp);
     }
 
     /**
@@ -5760,7 +5786,7 @@
      * @hide
      */
     public void setBasebandVersion(String version) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setBasebandVersionForPhone(phoneId, version);
     }
 
@@ -5787,7 +5813,7 @@
      * @hide
      */
     public void setPhoneType(int type) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setPhoneType(phoneId, type);
     }
 
@@ -5815,7 +5841,7 @@
      * @hide
      */
     public String getOtaSpNumberSchema(String defaultValue) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         return getOtaSpNumberSchemaForPhone(phoneId, defaultValue);
     }
 
@@ -5846,7 +5872,7 @@
      * @hide
      */
     public boolean getSmsReceiveCapable(boolean defaultValue) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         return getSmsReceiveCapableForPhone(phoneId, defaultValue);
     }
 
@@ -5877,7 +5903,7 @@
      * @hide
      */
     public boolean getSmsSendCapable(boolean defaultValue) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         return getSmsSendCapableForPhone(phoneId, defaultValue);
     }
 
@@ -5905,7 +5931,7 @@
      * @hide
      */
     public void setNetworkOperatorName(String name) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setNetworkOperatorNameForPhone(phoneId, name);
     }
 
@@ -5927,7 +5953,7 @@
      * @hide
      */
     public void setNetworkOperatorNumeric(String numeric) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setNetworkOperatorNumericForPhone(phoneId, numeric);
     }
 
@@ -5947,7 +5973,7 @@
      * @hide
      */
     public void setNetworkRoaming(boolean isRoaming) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setNetworkRoamingForPhone(phoneId, isRoaming);
     }
 
@@ -5971,7 +5997,7 @@
      * @hide
      */
     public void setNetworkCountryIso(String iso) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId();
         setNetworkCountryIsoForPhone(phoneId, iso);
     }
 
@@ -5991,11 +6017,15 @@
 
     /**
      * Set the network type currently in use on the device for data transmission.
+     *
+     * If this object has been created with {@link #createForSubscriptionId}, applies to the
+     * phoneId associated with the given subId. Otherwise, applies to the phoneId associated with
+     * {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      * @param type the network type currently in use on the device for data transmission
      * @hide
      */
     public void setDataNetworkType(int type) {
-        int phoneId = getDefaultPhone();
+        int phoneId = getPhoneId(SubscriptionManager.getDefaultDataSubscriptionId());
         setDataNetworkTypeForPhone(phoneId, type);
     }
 
@@ -6215,7 +6245,7 @@
      * @hide
      */
     public String getAidForAppType(int appType) {
-        return getAidForAppType(getDefaultSubscription(), appType);
+        return getAidForAppType(getSubId(), appType);
     }
 
     /**
@@ -6249,7 +6279,7 @@
      * @hide
      */
     public String getEsn() {
-        return getEsn(getDefaultSubscription());
+        return getEsn(getSubId());
     }
 
     /**
@@ -6282,7 +6312,7 @@
      * @hide
      */
     public String getCdmaPrlVersion() {
-        return getCdmaPrlVersion(getDefaultSubscription());
+        return getCdmaPrlVersion(getSubId());
     }
 
     /**
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index b12864c..b5484e34 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -56,8 +56,6 @@
     // see getCarrierName and setCarrierName
     @Nullable
     private String carrierName;
-    // see isConsentGranted and setConsentGranted
-    private boolean consentGranted;
     // see getAccessRules and setAccessRules
     private UiccAccessRule[] accessRules;
 
@@ -69,7 +67,6 @@
     private DownloadableSubscription(Parcel in) {
         encodedActivationCode = in.readString();
         carrierName = in.readString();
-        consentGranted = in.readInt() == 1;
         accessRules = in.createTypedArray(UiccAccessRule.CREATOR);
     }
 
@@ -110,28 +107,6 @@
         return carrierName;
     }
 
-
-    /**
-     * Mark this download as being consented to by the user.
-     * @hide
-     */
-    public void setConsentGranted() {
-        consentGranted = true;
-    }
-
-    /**
-     * Returns whether the user has granted consent to download this subscription.
-     *
-     * <p>The {@link android.service.euicc.EuiccService} implementation should permit a subscription
-     * download if this is set, even if the calling app doesn't have permission to download it.
-     * @hide
-     *
-     * TODO(b/35851809): Make this a SystemApi.
-     */
-    public boolean isConsentGranted() {
-        return consentGranted;
-    }
-
     /**
      * Returns the {@link UiccAccessRule}s dictating access to this subscription.
      *
@@ -156,22 +131,10 @@
         this.accessRules = accessRules;
     }
 
-    /**
-     * Unset any untrusted fields.
-     *
-     * <p>Should be called by the platform whenever an instance is received from an untrusted
-     * source to reset any secure fields that may only be set by the platform.
-     * @hide
-     */
-    public final void clearUntrustedFields() {
-        this.consentGranted = false;
-    }
-
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(encodedActivationCode);
         dest.writeString(carrierName);
-        dest.writeInt(consentGranted ? 1 : 0);
         dest.writeTypedArray(accessRules, flags);
     }
 
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 10492c0..8bc0be6 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -22,7 +22,9 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentSender;
 import android.content.pm.PackageManager;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
@@ -71,6 +73,13 @@
             "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
 
     /**
+     * Intent action to handle a resolvable error.
+     * @hide
+     */
+    public static final String ACTION_RESOLVE_ERROR =
+            "android.telephony.euicc.action.RESOLVE_ERROR";
+
+    /**
      * Result code for an operation indicating that the operation succeeded.
      */
     public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0;
@@ -105,7 +114,7 @@
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE";
 
     /**
-     * The key for an extra set on {@link #getDownloadableSubscriptionMetadata} PendingIntent result
+     * Key for an extra set on {@link #getDownloadableSubscriptionMetadata} PendingIntent result
      * callbacks providing the downloadable subscription metadata.
      * @hide
      *
@@ -114,6 +123,30 @@
     public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION =
             "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION";
 
+    /**
+     * Key for an extra set on {@link PendingIntent} result callbacks providing the resolution
+     * pending intent for {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}s.
+     * @hide
+     */
+    public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT =
+            "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT";
+
+    /**
+     * Key for an extra set on the {@link #EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT} intent
+     * containing the EuiccService action to launch for resolution.
+     * @hide
+     */
+    public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION =
+            "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION";
+
+    /**
+     * Key for an extra set on the {@link #EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT} intent
+     * providing the callback to execute after resolution is completed.
+     * @hide
+     */
+    public static final String EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT =
+            "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT";
+
     private final Context mContext;
     private final IEuiccController mController;
 
@@ -191,6 +224,8 @@
      * <p>If an operation returns {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}, this
      * method may be called to prompt the user to resolve the issue.
      *
+     * <p>This method may only be called once for a particular error.
+     *
      * @param activity the calling activity (which should be in the foreground).
      * @param requestCode an application-specific request code which will be provided to
      *     {@link Activity#onActivityResult} upon completion. Note that the operation may still be
@@ -200,11 +235,49 @@
      *     {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}.
      * @param callbackIntent a PendingIntent to launch when the operation completes. This is
      *     trigered upon completion of the original operation that required user resolution.
+     * @throws android.content.IntentSender.SendIntentException if called more than once.
      */
     public void startResolutionActivity(Activity activity, int requestCode, Intent resultIntent,
-            PendingIntent callbackIntent) {
-        // TODO(b/33075886): Implement this API.
-        throw new UnsupportedOperationException("Not implemented");
+            PendingIntent callbackIntent) throws IntentSender.SendIntentException {
+        PendingIntent resolutionIntent =
+                resultIntent.getParcelableExtra(EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT);
+        if (resolutionIntent == null) {
+            throw new IllegalArgumentException("Invalid result intent");
+        }
+        Intent fillInIntent = new Intent();
+        fillInIntent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT,
+                callbackIntent);
+        activity.startIntentSenderForResult(resolutionIntent.getIntentSender(), requestCode,
+                fillInIntent, 0 /* flagsMask */, 0 /* flagsValues */, 0 /* extraFlags */);
+    }
+
+    /**
+     * Continue an operation after the user resolves an error.
+     *
+     * <p>To be called by the LUI upon completion of a resolvable error flow.
+     *
+     * @param resolutionIntent The original intent used to start the LUI.
+     * @param resolutionExtras Resolution-specific extras depending on the result of the resolution.
+     *     For example, this may indicate whether the user has consented or may include the input
+     *     they provided.
+     * @hide
+     */
+    @SystemApi
+    public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) {
+        if (!isEnabled()) {
+            PendingIntent callbackIntent =
+                    resolutionIntent.getParcelableExtra(
+                            EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT);
+            if (callbackIntent != null) {
+                sendUnavailableError(callbackIntent);
+            }
+            return;
+        }
+        try {
+            mController.continueOperation(resolutionIntent, resolutionExtras);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index b461a78..dd08f67 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -498,12 +498,6 @@
       */
     boolean isConcurrentVoiceAndDataAllowed(int subId);
 
-    oneway void setVisualVoicemailEnabled(String callingPackage,
-            in PhoneAccountHandle accountHandle, boolean enabled);
-
-    boolean isVisualVoicemailEnabled(String callingPackage,
-            in PhoneAccountHandle accountHandle);
-
     String getVisualVoicemailPackageName(String callingPackage, int subId);
 
     // Not oneway, caller needs to make sure the vaule is set before receiving a SMS
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index de198c1..5f03dd9 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -17,10 +17,13 @@
 package com.android.internal.telephony.euicc;
 
 import android.app.PendingIntent;
+import android.content.Intent;
+import android.os.Bundle;
 import android.telephony.euicc.DownloadableSubscription;
 
 /** @hide */
 interface IEuiccController {
+    oneway void continueOperation(in Intent resolutionIntent, in Bundle resolutionExtras);
     oneway void getDownloadableSubscriptionMetadata(in DownloadableSubscription subscription,
         in PendingIntent callbackIntent);
     String getEid();
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index a8eb986..b4e3a47 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -530,13 +530,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /** STOPSHIP remove when trial API is turned down */
-    @Override
-    public ComponentName startServiceInForeground(Intent service,
-            int id, Notification notification) {
-        throw new UnsupportedOperationException();
-    }
-
     @Override
     public boolean stopService(Intent service) {
         throw new UnsupportedOperationException();
@@ -554,13 +547,6 @@
         throw new UnsupportedOperationException();
     }
 
-    /** @hide STOPSHIP removed when trial API is turned down */
-    @Override
-    public ComponentName startServiceInForegroundAsUser(Intent service,
-            int id, Notification notification, UserHandle user) {
-        throw new UnsupportedOperationException();
-    }
-
     /** @hide */
     @Override
     public boolean stopServiceAsUser(Intent service, UserHandle user) {
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 960a2d9..20392e7 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -1126,4 +1126,12 @@
     public ComponentName getInstantAppResolverSettingsComponent() {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide
+     */
+    @Override
+    public ComponentName getInstantAppInstallerComponent() {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java b/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
index 6fe2cfb..fc1d47b 100644
--- a/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
+++ b/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
@@ -95,13 +95,13 @@
 
         setContentView(R.layout.sink_activity);
 
-        mLogTextView = (TextView) findViewById(R.id.logTextView);
+        mLogTextView = findViewById(R.id.logTextView);
         mLogTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
         mLogger = new TextLogger();
 
-        mFpsTextView = (TextView) findViewById(R.id.fpsTextView);
+        mFpsTextView = findViewById(R.id.fpsTextView);
 
-        mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
+        mSurfaceView = findViewById(R.id.surfaceView);
         mSurfaceView.setOnTouchListener(new View.OnTouchListener() {
             @Override
             public boolean onTouch(View v, MotionEvent event) {
diff --git a/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/SourceActivity.java b/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/SourceActivity.java
index c59c958..a216102 100644
--- a/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/SourceActivity.java
+++ b/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/SourceActivity.java
@@ -63,7 +63,7 @@
 
         setContentView(R.layout.source_activity);
 
-        mLogTextView = (TextView) findViewById(R.id.logTextView);
+        mLogTextView = findViewById(R.id.logTextView);
         mLogTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
         mLogger = new TextLogger();
         mPresenter = new Presenter();
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index 64cdcf7..b381cbf 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -87,5 +87,13 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <activity android:name="CustomSplashscreenActivity"
+            android:label="CustomSplashscreen"
+            android:theme="@style/CustomSplashscreen">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/tests/ActivityTests/res/drawable/splashscreen.xml b/tests/ActivityTests/res/drawable/splashscreen.xml
new file mode 100644
index 0000000..01fb646
--- /dev/null
+++ b/tests/ActivityTests/res/drawable/splashscreen.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@drawable/icon"/>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/tests/ActivityTests/res/values/themes.xml b/tests/ActivityTests/res/values/themes.xml
index b8dd830..c11d2e4 100644
--- a/tests/ActivityTests/res/values/themes.xml
+++ b/tests/ActivityTests/res/values/themes.xml
@@ -26,4 +26,7 @@
         <item name="android:colorBackground">@color/blue</item>
         <item name="android:windowBackground">@color/blue</item>
     </style>
+    <style name="CustomSplashscreen" parent="@android:style/Theme.Material.Light.NoActionBar">
+        <item name="android:windowSplashscreenContent">@drawable/splashscreen</item>
+    </style>
 </resources>
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java b/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java
new file mode 100644
index 0000000..0683df6
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/CustomSplashscreenActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.google.android.test.activity;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+/**
+ * Activity for which we set a custom splash screen.
+ */
+public class CustomSplashscreenActivity extends Activity {
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        SystemClock.sleep(2000);
+    }
+}
diff --git a/tests/AmSlam/Android.mk b/tests/AmSlam/Android.mk
index 8dafac7..934bae0 100644
--- a/tests/AmSlam/Android.mk
+++ b/tests/AmSlam/Android.mk
@@ -21,7 +21,7 @@
 
 LOCAL_PACKAGE_NAME := AmSlam
 
-LOCAL_SDK_VERSION := 21
+LOCAL_SDK_VERSION := current
 LOCAL_MIN_SDK_VERSION := 21
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 
diff --git a/tests/AmSlam/src/test/amslam/MainActivity.java b/tests/AmSlam/src/test/amslam/MainActivity.java
index cce955e..17fca09 100644
--- a/tests/AmSlam/src/test/amslam/MainActivity.java
+++ b/tests/AmSlam/src/test/amslam/MainActivity.java
@@ -60,7 +60,7 @@
         super.onCreate(savedInstanceState);
         sAppContext = getApplicationContext();
         setContentView(R.layout.activity_main);
-        mOutput = (TextView) findViewById(R.id.output);
+        mOutput = findViewById(R.id.output);
         PongReceiver.addListener(this);
 
         findViewById(R.id.run).setOnClickListener(view -> {
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index b88a885..f85e82d 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -75,7 +75,7 @@
 
         setContentView(R.layout.main);
 
-        mList = (ListView) findViewById(R.id.testlist);
+        mList = findViewById(R.id.testlist);
         mList.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
         mList.setFocusableInTouchMode(true);
         
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java
index 1ed4723..8ccd4e2 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/AutomaticActivity.java
@@ -111,8 +111,8 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.automatic_layout);
 
-        mSoftwareImageView = (ImageView) findViewById(R.id.software_image_view);
-        mHardwareImageView = (ImageView) findViewById(R.id.hardware_image_view);
+        mSoftwareImageView = findViewById(R.id.software_image_view);
+        mHardwareImageView = findViewById(R.id.hardware_image_view);
 
         onCreateCommon(mRunnable);
         beginTest();
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
index 8d8d9de..0dec1de 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
@@ -57,7 +57,7 @@
         getWindow().setBackgroundDrawable(new ColorDrawable(0xffefefef));
         ResourceModifiers.init(getResources());
 
-        mHardwareView = (MainView) findViewById(R.id.hardware_view);
+        mHardwareView = findViewById(R.id.hardware_view);
         mHardwareView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
         mHardwareView.setBackgroundColor(Color.WHITE);
         mHardwareView.addDrawCallback(mDrawCallback);
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 78e360b..723c460 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -162,19 +162,19 @@
         // in res/layout/hello_activity.xml
         setContentView(R.layout.main);
 
-        mFgSpinner = (Spinner) findViewById(R.id.fgspinner);
+        mFgSpinner = findViewById(R.id.fgspinner);
         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                 android.R.layout.simple_spinner_item, mAvailOpLabels);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         mFgSpinner.setAdapter(adapter);
         mFgSpinner.setOnItemSelectedListener(this);
-        mBgSpinner = (Spinner) findViewById(R.id.bgspinner);
+        mBgSpinner = findViewById(R.id.bgspinner);
         adapter = new ArrayAdapter<String>(this,
                 android.R.layout.simple_spinner_item, mAvailOpLabels);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         mBgSpinner.setAdapter(adapter);
         mBgSpinner.setOnItemSelectedListener(this);
-        mLimitSpinner = (Spinner) findViewById(R.id.limitspinner);
+        mLimitSpinner = findViewById(R.id.limitspinner);
         adapter = new ArrayAdapter<String>(this,
                 android.R.layout.simple_spinner_item, mLimitLabels);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
diff --git a/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java b/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java
index 84e31aa..83c27fb 100644
--- a/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java
+++ b/tests/HugeBackup/src/com/android/hugebackup/HugeBackupActivity.java
@@ -71,9 +71,9 @@
         setContentView(R.layout.backup_restore);
 
         /** Once the UI has been inflated, cache the controls for later */
-        mFillingGroup = (RadioGroup) findViewById(R.id.filling_group);
-        mAddMayoCheckbox = (CheckBox) findViewById(R.id.mayo);
-        mAddTomatoCheckbox = (CheckBox) findViewById(R.id.tomato);
+        mFillingGroup = findViewById(R.id.filling_group);
+        mAddMayoCheckbox = findViewById(R.id.mayo);
+        mAddTomatoCheckbox = findViewById(R.id.tomato);
 
         /** Set up our file bookkeeping */
         mDataFile = new File(getFilesDir(), HugeBackupActivity.DATA_FILE_NAME);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
index eb4e3fd..492d158 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
@@ -101,7 +101,7 @@
                         Context.LAYOUT_INFLATER_SERVICE);
         inflater.inflate(R.layout.date_picker, this, true);
 
-        mDayPicker = (NumberPicker) findViewById(R.id.day);
+        mDayPicker = findViewById(R.id.day);
         mDayPicker.setFormatter(NumberPicker.getTwoDigitFormatter());
         mDayPicker.setOnLongPressUpdateInterval(100);
         mDayPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@@ -110,7 +110,7 @@
                 notifyDateChanged();
             }
         });
-        mMonthPicker = (NumberPicker) findViewById(R.id.month);
+        mMonthPicker = findViewById(R.id.month);
         mMonthPicker.setFormatter(NumberPicker.getTwoDigitFormatter());
         DateFormatSymbols dfs = new DateFormatSymbols();
         String[] months = dfs.getShortMonths();
@@ -146,7 +146,7 @@
                 updateDaySpinner();
             }
         });
-        mYearPicker = (NumberPicker) findViewById(R.id.year);
+        mYearPicker = findViewById(R.id.year);
         mYearPicker.setOnLongPressUpdateInterval(100);
         mYearPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
             public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
@@ -158,7 +158,7 @@
             }
         });
 
-        mYearToggle = (CheckBox) findViewById(R.id.yearToggle);
+        mYearToggle = findViewById(R.id.yearToggle);
         mYearToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
             @Override
             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
@@ -229,7 +229,7 @@
         /* Remove the 3 pickers from their parent and then add them back in the
          * required order.
          */
-        LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
+        LinearLayout parent = findViewById(R.id.parent);
         parent.removeAllViews();
 
         boolean quoted = false;
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
index 0defe92..134c2e0 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ListActivity.java
@@ -82,7 +82,7 @@
 
         ListAdapter adapter = new SimpleListAdapter(this);
 
-        final ListView list = (ListView) findViewById(R.id.list);
+        final ListView list = findViewById(R.id.list);
         list.setAdapter(adapter);
         
         registerForContextMenu(list);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java
index 5655adf..262b0e9 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StackActivity.java
@@ -35,7 +35,7 @@
 
         setContentView(R.layout.stack);
 
-        StackView stack = (StackView) findViewById(R.id.stack_view);
+        StackView stack = findViewById(R.id.stack_view);
         stack.setAdapter(new ArrayAdapter<Drawable>(this, android.R.layout.simple_list_item_1,
                 android.R.id.text1, new Drawable[] {
             getResources().getDrawable(R.drawable.sunset1),
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java
index 684d179..b5a5e02 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransformsAndAnimationsActivity.java
@@ -55,23 +55,23 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.transforms_and_animations);
 
-        button1 = (Button) findViewById(R.id.button1);
-        button2 = (Button) findViewById(R.id.button2);
-        button3 = (Button) findViewById(R.id.button3);
-        button1a = (Button) findViewById(R.id.button1a);
-        button2a = (Button) findViewById(R.id.button2a);
-        button3a = (Button) findViewById(R.id.button3a);
-        button1b = (Button) findViewById(R.id.button1b);
-        button2b = (Button) findViewById(R.id.button2b);
-        button3b = (Button) findViewById(R.id.button3b);
-        button4 = (Button) findViewById(R.id.button4);
-        button5 = (Button) findViewById(R.id.button5);
-        button6 = (Button) findViewById(R.id.button6);
-        button7 = (Button) findViewById(R.id.button7);
-        button8 = (Button) findViewById(R.id.button8);
-        layersNoneCB = (CheckBox) findViewById(R.id.layersNoneCB);
-        layersHardwareCB = (CheckBox) findViewById(R.id.layersHwCB);
-        layersSoftwareCB = (CheckBox) findViewById(R.id.layersSwCB);
+        button1 = findViewById(R.id.button1);
+        button2 = findViewById(R.id.button2);
+        button3 = findViewById(R.id.button3);
+        button1a = findViewById(R.id.button1a);
+        button2a = findViewById(R.id.button2a);
+        button3a = findViewById(R.id.button3a);
+        button1b = findViewById(R.id.button1b);
+        button2b = findViewById(R.id.button2b);
+        button3b = findViewById(R.id.button3b);
+        button4 = findViewById(R.id.button4);
+        button5 = findViewById(R.id.button5);
+        button6 = findViewById(R.id.button6);
+        button7 = findViewById(R.id.button7);
+        button8 = findViewById(R.id.button8);
+        layersNoneCB = findViewById(R.id.layersNoneCB);
+        layersHardwareCB = findViewById(R.id.layersHwCB);
+        layersSoftwareCB = findViewById(R.id.layersSwCB);
 
         layersNoneCB.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
             @Override
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
index ffb8689..deb8585 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java
@@ -84,7 +84,7 @@
 
         ListAdapter adapter = new SimpleListAdapter(this);
 
-        ListView list = (ListView) findViewById(R.id.list);
+        ListView list = findViewById(R.id.list);
         list.setAdapter(adapter);
         list.setCacheColorHint(0);
         list.setVerticalFadingEdgeEnabled(true);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java
index 6d47d6c..a261fb7 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayerInvalidationActivity.java
@@ -49,13 +49,13 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.view_layer_invalidation);
 
-        container = (LinearLayout) findViewById(R.id.container);
-        final LinearLayout container1 = (LinearLayout) findViewById(R.id.container1);
-        final LinearLayout container2 = (LinearLayout) findViewById(R.id.container2);
-        final LinearLayout container3 = (LinearLayout) findViewById(R.id.container3);
-        nestedStatusTV = (TextView) findViewById(R.id.nestedStatus);
-        invalidateStatusTV = (TextView) findViewById(R.id.invalidateStatus);
-        final TextView tva = (TextView) findViewById(R.id.textviewa);
+        container = findViewById(R.id.container);
+        final LinearLayout container1 = findViewById(R.id.container1);
+        final LinearLayout container2 = findViewById(R.id.container2);
+        final LinearLayout container3 = findViewById(R.id.container3);
+        nestedStatusTV = findViewById(R.id.nestedStatus);
+        invalidateStatusTV = findViewById(R.id.invalidateStatus);
+        final TextView tva = findViewById(R.id.textviewa);
 
         topLayouts.add(container1);
         topLayouts.add(container2);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
index 7168478..07dc0a1 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java
@@ -94,7 +94,7 @@
     }
 
     private void setupList(int listId) {
-        final ListView list = (ListView) findViewById(listId);
+        final ListView list = findViewById(listId);
         list.setAdapter(new SimpleListAdapter(this));
     }
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
index e65dd63..96cf43e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity3.java
@@ -39,7 +39,7 @@
     }
 
     private void setupList(int listId) {
-        final ListView list = (ListView) findViewById(listId);
+        final ListView list = findViewById(listId);
         list.setAdapter(new SimpleListAdapter(this));
         list.setLayerType(View.LAYER_TYPE_HARDWARE, null);
         ((View) list.getParent()).setLayerType(View.LAYER_TYPE_HARDWARE, null);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
index 17f78af..1f3f874 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity4.java
@@ -47,7 +47,7 @@
     }
     
     private void setupList(int listId) {
-        final ListView list = (ListView) findViewById(listId);
+        final ListView list = findViewById(listId);
         list.setAdapter(new SimpleListAdapter(this));
         list.setLayerType(View.LAYER_TYPE_HARDWARE, null);
     }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index 2dd7b6a..715da20 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -113,7 +113,7 @@
     }
     
     private void setupList(int listId) {
-        final ListView list = (ListView) findViewById(listId);
+        final ListView list = findViewById(listId);
         list.setAdapter(new SimpleListAdapter(this));
     }
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java
index 738801d..9ae3811 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java
@@ -60,12 +60,12 @@
                 startAnim(R.id.imageview);
                 startAnim(myViewAlphaDefault);
                 startAnim(myViewAlphaHandled);
-                EditText selectedText = (EditText) findViewById(R.id.selectedtext);
+                EditText selectedText = findViewById(R.id.selectedtext);
                 selectedText.setSelection(3, 8);
             }
         }, 2000);
         
-        Button invalidator = (Button) findViewById(R.id.invalidateButton);
+        Button invalidator = findViewById(R.id.invalidateButton);
         invalidator.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -74,7 +74,7 @@
             }
         });
 
-        TextView textView = (TextView) findViewById(R.id.spantext);
+        TextView textView = findViewById(R.id.spantext);
         if (textView != null) {
             SpannableStringBuilder text =
                     new SpannableStringBuilder("Now this is a short text message with spans");
@@ -93,7 +93,7 @@
             textView.setText(text);
         }
         
-        LinearLayout container = (LinearLayout) findViewById(R.id.container);
+        LinearLayout container = findViewById(R.id.container);
         myViewAlphaDefault = new MyView(this, false);
         myViewAlphaDefault.setLayoutParams(new LinearLayout.LayoutParams(75, 75));
         container.addView(myViewAlphaDefault);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java
index 45e77ed..08979bc 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ZOrderingActivity.java
@@ -12,7 +12,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.z_ordering);
 
-        ViewGroup grandParent = (ViewGroup) findViewById(R.id.parent);
+        ViewGroup grandParent = findViewById(R.id.parent);
         if (grandParent == null) throw new IllegalStateException();
         View.OnClickListener l = new View.OnClickListener() {
             @Override
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
index 292bbd2..6115fd5 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityLandscape.java
@@ -50,7 +50,7 @@
 
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
                android.R.layout.simple_dropdown_item_1line, COUNTRIES);
-       AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit);
+       AutoCompleteTextView textView = findViewById(R.id.edit);
        textView.setAdapter(adapter);
    }
 
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
index 570cb6b..253c50f 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/AutoCompleteTextViewActivityPortrait.java
@@ -45,7 +45,7 @@
 
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
                android.R.layout.simple_dropdown_item_1line, COUNTRIES);
-       AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.edit);
+       AutoCompleteTextView textView = findViewById(R.id.edit);
        textView.setAdapter(adapter);
    }
 
diff --git a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
index 5aa0d4f..51cdbb5 100644
--- a/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
+++ b/tests/JobSchedulerTestApp/src/com/android/demo/jobSchedulerApp/MainActivity.java
@@ -56,16 +56,16 @@
         stopJobColor = getColor(R.color.stop_received);
 
         // Set up UI.
-        mShowStartView = (TextView) findViewById(R.id.onstart_textview);
-        mShowStopView = (TextView) findViewById(R.id.onstop_textview);
-        mParamsTextView = (TextView) findViewById(R.id.task_params);
-        mDelayEditText = (EditText) findViewById(R.id.delay_time);
-        mDeadlineEditText = (EditText) findViewById(R.id.deadline_time);
-        mWiFiConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_unmetered);
-        mAnyConnectivityRadioButton = (RadioButton) findViewById(R.id.checkbox_any);
-        mRequiresChargingCheckBox = (CheckBox) findViewById(R.id.checkbox_charging);
-        mRequiresIdleCheckbox = (CheckBox) findViewById(R.id.checkbox_idle);
-        mIsPersistedCheckbox = (CheckBox) findViewById(R.id.checkbox_persisted);
+        mShowStartView = findViewById(R.id.onstart_textview);
+        mShowStopView = findViewById(R.id.onstop_textview);
+        mParamsTextView = findViewById(R.id.task_params);
+        mDelayEditText = findViewById(R.id.delay_time);
+        mDeadlineEditText = findViewById(R.id.deadline_time);
+        mWiFiConnectivityRadioButton = findViewById(R.id.checkbox_unmetered);
+        mAnyConnectivityRadioButton = findViewById(R.id.checkbox_any);
+        mRequiresChargingCheckBox = findViewById(R.id.checkbox_charging);
+        mRequiresIdleCheckbox = findViewById(R.id.checkbox_idle);
+        mIsPersistedCheckbox = findViewById(R.id.checkbox_persisted);
 
         mServiceComponent = new ComponentName(this, TestJobService.class);
         // Start service and provide it a way to communicate with us.
diff --git a/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java b/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java
index e3a9cf4..612c53e 100644
--- a/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java
+++ b/tests/LargeAssetTest/src/com/android/largeassettest/LargeAssetTest.java
@@ -43,8 +43,8 @@
         super.onCreate(icicle);
         setContentView(R.layout.lat);
 
-        mResultText = (TextView) findViewById(R.id.result);
-        mValidateButton = (Button) findViewById(R.id.validate);
+        mResultText = findViewById(R.id.result);
+        mValidateButton = findViewById(R.id.validate);
 
         mValidateButton.setOnClickListener(mClickListener);
     }
diff --git a/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java b/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java
index 9f297aa..c0091ad 100644
--- a/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java
+++ b/tests/LowStorageTest/src/com/android/lowstoragetest/LowStorageTest.java
@@ -52,9 +52,9 @@
         StatFs stat = new StatFs(path.getPath());
         int totalBlocks = stat.getBlockCount();
         mBlockSize = (int) (stat.getBlockSize());
-        TextView startSizeTextView = (TextView) findViewById(R.id.totalsize);
+        TextView startSizeTextView = findViewById(R.id.totalsize);
         startSizeTextView.setText(Long.toString((totalBlocks * mBlockSize) / BYTE_SIZE));
-        Button button = (Button) findViewById(R.id.button_run);
+        Button button = findViewById(R.id.button_run);
         button.setOnClickListener(mStartListener);
     }
 
@@ -121,9 +121,9 @@
             File path = Environment.getDataDirectory();
             StatFs stat = new StatFs(path.getPath());
             long availableBlocks = stat.getAvailableBlocks();
-            TextView freeSizeTextView = (TextView) findViewById(R.id.freesize);
+            TextView freeSizeTextView = findViewById(R.id.freesize);
             freeSizeTextView.setText(Long.toString((availableBlocks * mBlockSize) / BYTE_SIZE));
-            TextView statusTextView = (TextView) findViewById(R.id.status);
+            TextView statusTextView = findViewById(R.id.status);
             statusTextView.setText("Finished. You can start the test now.");
         } catch (Exception e) {
             Log.v(TAG, e.toString());
diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
index 2ff3e20..85cc8fb 100644
--- a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
+++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
@@ -68,16 +68,16 @@
         mPlayer = new PlayerController(this, OnePlayerService.getServiceIntent(this));
 
 
-        mStartButton = (Button) findViewById(R.id.start_button);
-        mPlayButton = (Button) findViewById(R.id.play_button);
-        mRouteButton = (Button) findViewById(R.id.route_button);
-        mStatusView = (TextView) findViewById(R.id.status);
-        mContentText = (EditText) findViewById(R.id.content);
-        mNextContentText = (EditText) findViewById(R.id.next_content);
-        mHasVideo = (CheckBox) findViewById(R.id.has_video);
-        mArtView = (ImageView) findViewById(R.id.art);
+        mStartButton = findViewById(R.id.start_button);
+        mPlayButton = findViewById(R.id.play_button);
+        mRouteButton = findViewById(R.id.route_button);
+        mStatusView = findViewById(R.id.status);
+        mContentText = findViewById(R.id.content);
+        mNextContentText = findViewById(R.id.next_content);
+        mHasVideo = findViewById(R.id.has_video);
+        mArtView = findViewById(R.id.art);
 
-        final Button artPicker = (Button) findViewById(R.id.art_picker);
+        final Button artPicker = findViewById(R.id.art_picker);
         artPicker.setOnClickListener(mButtonListener);
 
         mStartButton.setOnClickListener(mButtonListener);
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index ee4c834..241206d 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -43,7 +43,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
-        ListView lv = (ListView) findViewById(android.R.id.list);
+        ListView lv = findViewById(android.R.id.list);
         lv.setDrawSelectorOnTop(true);
         lv.setAdapter(new SimpleAdapter(this, SAMPLES,
                 R.layout.item_layout, new String[] { KEY_NAME },
@@ -55,7 +55,7 @@
     @Override
     protected void onResume() {
         super.onResume();
-        ListView lv = (ListView) findViewById(android.R.id.list);
+        ListView lv = findViewById(android.R.id.list);
         for (int i = 0; i < lv.getChildCount(); i++) {
             lv.getChildAt(i).animate().translationY(0).setDuration(DURATION);
         }
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java
index 892cbae..22fc691 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java
@@ -39,7 +39,7 @@
     @Override
     protected void onResume() {
         super.onResume();
-        ViewGroup container = (ViewGroup) findViewById(R.id.my_container);
+        ViewGroup container = findViewById(R.id.my_container);
         int dx = getWindowManager().getDefaultDisplay().getWidth();
         for (int i = 0; i < container.getChildCount(); i++) {
             View child = container.getChildAt(i);
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java
index 4841bc5..c3c4cf5 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java
@@ -81,14 +81,14 @@
 
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
-        mDebugView = (TextView) findViewById(R.id.console);
-        mScrollView = (ScrollView) findViewById(R.id.scroller_id);
-        mRadioGroup = (RadioGroup) findViewById(R.id.model_group_id);
-        mPlayTriggerButton = (Button) findViewById(R.id.play_trigger_id);
+        mDebugView = findViewById(R.id.console);
+        mScrollView = findViewById(R.id.scroller_id);
+        mRadioGroup = findViewById(R.id.model_group_id);
+        mPlayTriggerButton = findViewById(R.id.play_trigger_id);
         mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE);
         mDebugView.setMovementMethod(new ScrollingMovementMethod());
-        mCaptureAudioCheckBox = (CheckBox) findViewById(R.id.caputre_check_box);
-        mPlayCapturedAudioButton = (Button) findViewById(R.id.play_captured_id);
+        mCaptureAudioCheckBox = findViewById(R.id.caputre_check_box);
+        mPlayCapturedAudioButton = findViewById(R.id.play_captured_id);
         mHandler = new Handler();
         mButtonModelUuidMap = new HashMap();
         mModelButtons = new HashMap();
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
index 7c13974..7632a6e 100644
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
+++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
@@ -180,7 +180,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_touch_latency);
 
-        mTouchView = (TouchLatencyView) findViewById(R.id.canvasView);
+        mTouchView = findViewById(R.id.canvasView);
     }
 
 
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java b/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java
index 54c44e2..9985357 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ClippingText.java
@@ -42,7 +42,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.clipping_text_1);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.clipping_text_1, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java b/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java
index f687da3..86ecf8e 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ContactsExpansion.java
@@ -49,7 +49,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.contacts_list);
-        ViewGroup contactsContainer = (ViewGroup) findViewById(R.id.contactsContainer);
+        ViewGroup contactsContainer = findViewById(R.id.contactsContainer);
 
         int contactsIndex = 0;
         addContact(contactsContainer, contactsIndex, R.drawable.self_portrait_square_100);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java b/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
index 5bb0e77..0d41d64 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/CrossFadeDemo.java
@@ -38,7 +38,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.crossfade);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.crossfade, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java
index 1f278b9..1fb732e 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeImage.java
@@ -41,10 +41,10 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.crossfade_image);
 
-        ViewGroup container = (ViewGroup) findViewById(R.id.container);
+        ViewGroup container = findViewById(R.id.container);
         mSceneRoot = container;
 
-        mImageView = (ImageView) findViewById(R.id.contact_picture);
+        mImageView = findViewById(R.id.contact_picture);
         mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
 
         Crossfade mCrossfade = new Crossfade();
diff --git a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java
index 469ee8b..15d15351 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/CrossfadeMultiple.java
@@ -49,12 +49,12 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.crossfade_multiple);
 
-        ViewGroup container = (ViewGroup) findViewById(R.id.container);
+        ViewGroup container = findViewById(R.id.container);
         mSceneRoot = container;
 
-        mButton = (Button) findViewById(R.id.button);
-        mImageView = (ImageView) findViewById(R.id.imageview);
-        mTextView = (TextView) findViewById(R.id.textview);
+        mButton = findViewById(R.id.button);
+        mImageView = findViewById(R.id.imageview);
+        mTextView = findViewById(R.id.textview);
 
         mCrossfade = new Crossfade();
         mCrossfade.addTarget(R.id.button).addTarget(R.id.textview).addTarget(R.id.imageview);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo0.java b/tests/TransitionTests/src/com/android/transitiontests/Demo0.java
index d52ab1d..e172904 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo0.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo0.java
@@ -35,7 +35,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mCurrentScene = SEARCH_SCREEN;
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo1.java b/tests/TransitionTests/src/com/android/transitiontests/Demo1.java
index 5b5eb15..e92dd03 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo1.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo1.java
@@ -40,7 +40,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
 //        mResultsScreen = new MyScene(mSceneRoot, R.layout.results_screen);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo2.java b/tests/TransitionTests/src/com/android/transitiontests/Demo2.java
index 0f3257b..c26723b 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo2.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo2.java
@@ -38,7 +38,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
     }
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo3.java b/tests/TransitionTests/src/com/android/transitiontests/Demo3.java
index 0ffa1f5..094ab97 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo3.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo3.java
@@ -38,7 +38,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo4.java b/tests/TransitionTests/src/com/android/transitiontests/Demo4.java
index 3aadbb0..af67f26 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo4.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo4.java
@@ -38,7 +38,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Demo5.java b/tests/TransitionTests/src/com/android/transitiontests/Demo5.java
index c36abda..f01a29d 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Demo5.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Demo5.java
@@ -33,7 +33,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java b/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java
index d497abe..40bf975 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/FadingHierarchy.java
@@ -34,11 +34,11 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.fading_hierarchy);
 
-        mContainer = (ViewGroup) findViewById(R.id.container);
-        mRemovingContainer = (ViewGroup) findViewById(R.id.removingContainer);
+        mContainer = findViewById(R.id.container);
+        mRemovingContainer = findViewById(R.id.removingContainer);
         mInnerContainerParent = (ViewGroup) mRemovingContainer.getParent();
 
-        mRemovingButton = (Button) findViewById(R.id.removingButton);
+        mRemovingButton = findViewById(R.id.removingButton);
     }
 
     public void sendMessage(View view) {
diff --git a/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java b/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java
index 29fb868..8307366 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/FadingTest.java
@@ -43,13 +43,13 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.fading_test);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
 
-        mRemovingButton = (Button) findViewById(R.id.removingButton);
-        mInvisibleButton = (Button) findViewById(R.id.invisibleButton);
-        mGoneButton = (Button) findViewById(R.id.goneButton);
+        mRemovingButton = findViewById(R.id.removingButton);
+        mInvisibleButton = findViewById(R.id.invisibleButton);
+        mGoneButton = findViewById(R.id.goneButton);
 
         mGoneButton.setOnClickListener(new View.OnClickListener() {
             @Override
diff --git a/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java b/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java
index a06ba8f..025e4e3 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/InstanceTargets.java
@@ -37,7 +37,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.instance_targets);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container;
     }
 
diff --git a/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java b/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java
index c26e93f..6186150 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/InterruptionTest.java
@@ -40,17 +40,17 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.interruption);
 
-        ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.sceneRoot);
+        ViewGroup sceneRoot = findViewById(R.id.sceneRoot);
 
         mScene1 = Scene.getSceneForLayout(sceneRoot, R.layout.interruption_inner_1, this);
         mScene2 = Scene.getSceneForLayout(sceneRoot, R.layout.interruption_inner_2, this);
         mScene3 = Scene.getSceneForLayout(sceneRoot, R.layout.interruption_inner_3, this);
         mScene4 = Scene.getSceneForLayout(sceneRoot, R.layout.interruption_inner_4, this);
 
-        mScene1RB = (RadioButton) findViewById(R.id.scene1RB);
-        mScene2RB = (RadioButton) findViewById(R.id.scene2RB);
-        mScene3RB = (RadioButton) findViewById(R.id.scene3RB);
-        mScene4RB = (RadioButton) findViewById(R.id.scene4RB);
+        mScene1RB = findViewById(R.id.scene1RB);
+        mScene2RB = findViewById(R.id.scene2RB);
+        mScene3RB = findViewById(R.id.scene3RB);
+        mScene4RB = findViewById(R.id.scene4RB);
 
         ChangeBounds changeBounds1 = new ChangeBounds();
         changeBounds1.addTarget(R.id.button);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java b/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
index 251bf24..45b8286 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ListViewAddRemove.java
@@ -47,9 +47,9 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.list_view_add_remove);
 
-        final LinearLayout container = (LinearLayout) findViewById(R.id.container);
+        final LinearLayout container = findViewById(R.id.container);
 
-        final ListView listview = (ListView) findViewById(R.id.listview);
+        final ListView listview = findViewById(R.id.listview);
         for (int i = 0; i < 200; ++i) {
             numList.add(Integer.toString(i));
         }
diff --git a/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java b/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java
index 92bbb85..96b018b 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/LoginActivity.java
@@ -40,7 +40,7 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_login);
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mLoginScene = Scene.getSceneForLayout(mSceneRoot, R.layout.activity_login, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java b/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java
index ef8cd37..384762b 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/OverlayTest.java
@@ -32,12 +32,12 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.overlay_test);
 
-        mContainer = (ViewGroup) findViewById(R.id.container);
+        mContainer = findViewById(R.id.container);
         mRoot = (ViewGroup) mContainer.getParent();
     }
 
     public void onClick(View view) {
-        final Button fadingButton = (Button) findViewById(R.id.fadingButton);
+        final Button fadingButton = findViewById(R.id.fadingButton);
         if (fadingButton != null) {
             mContainer.removeView(fadingButton);
             mRoot.getOverlay().add(fadingButton);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java b/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java
index 1ee8621..772ddc7 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/Reparenting.java
@@ -34,9 +34,9 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.reparenting);
 
-        ViewGroup container = (ViewGroup) findViewById(R.id.container);
-        mContainer1 = (ViewGroup) findViewById(R.id.container1);
-        mContainer2 = (ViewGroup) findViewById(R.id.container2);
+        ViewGroup container = findViewById(R.id.container);
+        mContainer1 = findViewById(R.id.container1);
+        mContainer2 = findViewById(R.id.container2);
         System.out.println("container 1 and 2 " + mContainer1 + ", " + mContainer2);
 
         setupButtons(0, mContainer1);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java b/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java
index 1aee258..96d3ae1 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ResourceLoadingTest.java
@@ -39,7 +39,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mCurrentScene = SEARCH_SCREEN;
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java
index 7504058..7ee4b3e7 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTargets.java
@@ -39,7 +39,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java
index 23b28ec..9333ea1 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestAutoTransition.java
@@ -37,7 +37,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java
index ecf5ef3..a01f638 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/ScenesTestv21.java
@@ -39,7 +39,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.search_screen);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
         mSearchScreen = Scene.getSceneForLayout(mSceneRoot, R.layout.search_screen, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java b/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java
index c550e92..5f4560cc 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/SequenceTest.java
@@ -41,12 +41,12 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.fading_test);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
-        mRemovingButton = (Button) findViewById(R.id.removingButton);
-        mInvisibleButton = (Button) findViewById(R.id.invisibleButton);
-        mGoneButton = (Button) findViewById(R.id.goneButton);
+        mRemovingButton = findViewById(R.id.removingButton);
+        mInvisibleButton = findViewById(R.id.invisibleButton);
+        mGoneButton = findViewById(R.id.goneButton);
 
         mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.fading_test, this);
         mScene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.fading_test_scene_2, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java b/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java
index 92b169e..f478cb8 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/SequenceTestSimple.java
@@ -42,10 +42,10 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.fading_test_simple);
 
-        View container = (View) findViewById(R.id.container);
+        View container = findViewById(R.id.container);
         mSceneRoot = (ViewGroup) container.getParent();
 
-        mRemovingButton = (Button) findViewById(R.id.removingButton);
+        mRemovingButton = findViewById(R.id.removingButton);
 
         mScene1 = Scene.getSceneForLayout(mSceneRoot, R.layout.fading_test_simple, this);
         mScene2 = Scene.getSceneForLayout(mSceneRoot, R.layout.fading_test_simple2, this);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java b/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java
index 9b246ad..8819c40 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/SurfaceAndTextureViews.java
@@ -48,8 +48,8 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.surface_texture_views);
 
-        final ViewGroup container = (ViewGroup) findViewById(R.id.container);
-        Button toggleButton = (Button) findViewById(R.id.toggleButton);
+        final ViewGroup container = findViewById(R.id.container);
+        Button toggleButton = findViewById(R.id.toggleButton);
 
         mView = new SimpleView(this);
         mView.setId(0);
diff --git a/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java b/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java
index c824956..b2b24bc 100644
--- a/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java
+++ b/tests/TransitionTests/src/com/android/transitiontests/UniqueIds.java
@@ -40,7 +40,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.unique_id_test);
 
-        LinearLayout container = (LinearLayout) findViewById(R.id.container);
+        LinearLayout container = findViewById(R.id.container);
         LayoutInflater inflater = getLayoutInflater();
         Button button = (Button) inflater.inflate(R.layout.button_template, null);
         container.addView(button);
diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
index 0a069c2..c212c4c 100644
--- a/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
+++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransition.java
@@ -94,7 +94,7 @@
         setupHero();
 
         // Ensure that all images are visible regardless of orientation.
-        GridLayout gridLayout = (GridLayout) findViewById(R.id.transition_grid_layout);
+        GridLayout gridLayout = findViewById(R.id.transition_grid_layout);
         boolean isPortrait =
                 getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
         gridLayout.setRowCount(isPortrait ? 4 : 2);
@@ -105,7 +105,7 @@
         String name = getIntent().getStringExtra(KEY_ID);
         mHero = null;
         if (name != null) {
-            mHero = (ImageView) findViewById(getIdForKey(name));
+            mHero = findViewById(getIdForKey(name));
             setEnterSharedElementCallback(new SharedElementCallback() {
                 @Override
                 public void onMapSharedElements(List<String> names,
diff --git a/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java b/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java
index a654c61..a4d57e1 100644
--- a/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java
+++ b/tests/UiBench/src/com/android/test/uibench/ActivityTransitionDetails.java
@@ -39,7 +39,7 @@
         super.onCreate(savedInstanceState);
         getWindow().setBackgroundDrawable(new ColorDrawable(Color.DKGRAY));
         setContentView(R.layout.activity_transition_details);
-        ImageView titleImage = (ImageView) findViewById(R.id.titleImage);
+        ImageView titleImage = findViewById(R.id.titleImage);
         titleImage.setImageDrawable(getHeroDrawable());
     }
 
diff --git a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
index e2bf897..235e0e6 100644
--- a/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/BitmapUploadActivity.java
@@ -80,7 +80,7 @@
         setContentView(R.layout.activity_bitmap_upload);
 
         // animate color to force bitmap uploads
-        UploadView uploadView = (UploadView) findViewById(R.id.upload_view);
+        UploadView uploadView = findViewById(R.id.upload_view);
         ObjectAnimator colorValueAnimator = ObjectAnimator.ofInt(uploadView, "colorValue", 0, 255);
         colorValueAnimator.setRepeatMode(ValueAnimator.REVERSE);
         colorValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
diff --git a/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java b/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
index 7454124..fee7480 100644
--- a/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
@@ -35,16 +35,16 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_navigation_drawer);
-        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+        Toolbar toolbar = findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
-        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        DrawerLayout drawer = findViewById(R.id.drawer_layout);
         ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                 this, drawer, toolbar, R.string.navigation_drawer_open,
                 R.string.navigation_drawer_close);
         drawer.setDrawerListener(toggle);
         toggle.syncState();
 
-        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
+        NavigationView navigationView = findViewById(R.id.nav_view);
         navigationView.setNavigationItemSelectedListener(this);
 
         FragmentManager fm = getSupportFragmentManager();
@@ -59,7 +59,7 @@
 
     @Override
     public boolean onNavigationItemSelected(MenuItem item) {
-        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        DrawerLayout drawer = findViewById(R.id.drawer_layout);
         drawer.closeDrawer(GravityCompat.START);
         return true;
     }
diff --git a/tests/UiBench/src/com/android/test/uibench/NavigationDrawerActivity.java b/tests/UiBench/src/com/android/test/uibench/NavigationDrawerActivity.java
index 1d68767..a541104 100644
--- a/tests/UiBench/src/com/android/test/uibench/NavigationDrawerActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/NavigationDrawerActivity.java
@@ -31,22 +31,22 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_navigation_drawer);
-        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+        Toolbar toolbar = findViewById(R.id.toolbar);
         setSupportActionBar(toolbar);
-        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        DrawerLayout drawer = findViewById(R.id.drawer_layout);
         ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                 this, drawer, toolbar, R.string.navigation_drawer_open,
                 R.string.navigation_drawer_close);
         drawer.setDrawerListener(toggle);
         toggle.syncState();
 
-        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
+        NavigationView navigationView = findViewById(R.id.nav_view);
         navigationView.setNavigationItemSelectedListener(this);
     }
 
     @Override
     public boolean onNavigationItemSelected(MenuItem item) {
-        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        DrawerLayout drawer = findViewById(R.id.drawer_layout);
         drawer.closeDrawer(GravityCompat.START);
         return true;
     }
diff --git a/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java b/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java
index e2a9bcb..e1df7d3 100644
--- a/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java
+++ b/tests/UiBench/src/com/android/test/uibench/RenderingJitter.java
@@ -85,12 +85,12 @@
         View content = findViewById(android.R.id.content);
         content.setBackground(new AnimatedBackgroundDrawable());
         content.setKeepScreenOn(true);
-        mJitterReport = (TextView) findViewById(R.id.jitter_mma);
-        mMostlyTotalFrameTimeReport = (TextView) findViewById(R.id.totalish_mma);
-        mUiFrameTimeReport = (TextView) findViewById(R.id.ui_frametime_mma);
-        mRenderThreadTimeReport = (TextView) findViewById(R.id.rt_frametime_mma);
-        mTotalFrameTimeReport = (TextView) findViewById(R.id.total_mma);
-        mGraph = (PointGraphView) findViewById(R.id.graph);
+        mJitterReport = findViewById(R.id.jitter_mma);
+        mMostlyTotalFrameTimeReport = findViewById(R.id.totalish_mma);
+        mUiFrameTimeReport = findViewById(R.id.ui_frametime_mma);
+        mRenderThreadTimeReport = findViewById(R.id.rt_frametime_mma);
+        mTotalFrameTimeReport = findViewById(R.id.total_mma);
+        mGraph = findViewById(R.id.graph);
         mJitterReport.setText("abcdefghijklmnopqrstuvwxyz");
         mMostlyTotalFrameTimeReport.setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
         mUiFrameTimeReport.setText("0123456789");
diff --git a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/src/com/android/hardware/usb/externalmanagementtest/UsbHostManagementActivity.java b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/src/com/android/hardware/usb/externalmanagementtest/UsbHostManagementActivity.java
index 2d9226f..af8b846 100644
--- a/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/src/com/android/hardware/usb/externalmanagementtest/UsbHostManagementActivity.java
+++ b/tests/UsbHostExternalManagmentTest/UsbHostExternalManagmentTestApp/src/com/android/hardware/usb/externalmanagementtest/UsbHostManagementActivity.java
@@ -68,12 +68,12 @@
         Log.i(TAG, "onCreate");
         super.onCreate(savedInstanceState);
         setContentView(R.layout.host_management);
-        mDeviceInfoText = (TextView) findViewById(R.id.device_info_text);
-        mStartAoapButton = (Button) findViewById(R.id.start_aoap_button);
-        mStartAoapActivityButton = (Button) findViewById(R.id.start_aoap_activity_button);
-        mAoapAppLog = (TextView) findViewById(R.id.aoap_apps_text);
-        mResetUsbButton = (Button) findViewById(R.id.reset_button);
-        mFinishButton = (Button) findViewById(R.id.finish_button);
+        mDeviceInfoText = findViewById(R.id.device_info_text);
+        mStartAoapButton = findViewById(R.id.start_aoap_button);
+        mStartAoapActivityButton = findViewById(R.id.start_aoap_activity_button);
+        mAoapAppLog = findViewById(R.id.aoap_apps_text);
+        mResetUsbButton = findViewById(R.id.reset_button);
+        mFinishButton = findViewById(R.id.finish_button);
 
         Intent intent = getIntent();
         if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java
index 8de2f6b..47ca482 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableAttr.java
@@ -25,7 +25,7 @@
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_animated_vector_drawable_attr);
 
-        ImageView avdIv = (ImageView) findViewById(R.id.avd);
+        ImageView avdIv = findViewById(R.id.avd);
         AnimatedVectorDrawable avd = (AnimatedVectorDrawable) avdIv.getDrawable();
         avd.start();
     }
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
index 41058c9..733f602 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
@@ -55,9 +55,9 @@
         mPickButton.setOnClickListener(this);
         mCancelButton = (Button)findViewById(R.id.cancel);
         mCancelButton.setOnClickListener(this);
-        mStartButton = (Button) findViewById(R.id.start);
+        mStartButton = findViewById(R.id.start);
         mStartButton.setOnClickListener(this);
-        mStopButton = (Button) findViewById(R.id.stop);
+        mStopButton = findViewById(R.id.stop);
         mStopButton.setOnClickListener(this);
 
         mLog.append("Local Voice Interaction Supported = " + isLocalVoiceInteractionSupported());
diff --git a/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
index 7880f67..63e11a7 100644
--- a/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
+++ b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
@@ -58,28 +58,28 @@
         mWallpaperManager = (WallpaperManager)getSystemService(Context.WALLPAPER_SERVICE);
         mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
 
-        mDimenWidthView = (TextView) findViewById(R.id.dimen_width);
+        mDimenWidthView = findViewById(R.id.dimen_width);
         mDimenWidthView.addTextChangedListener(mTextWatcher);
-        mDimenHeightView = (TextView) findViewById(R.id.dimen_height);
+        mDimenHeightView = findViewById(R.id.dimen_height);
         mDimenHeightView.addTextChangedListener(mTextWatcher);
 
-        mWallOffXView = (TextView) findViewById(R.id.walloff_x);
+        mWallOffXView = findViewById(R.id.walloff_x);
         mWallOffXView.addTextChangedListener(mTextWatcher);
-        mWallOffYView = (TextView) findViewById(R.id.walloff_y);
+        mWallOffYView = findViewById(R.id.walloff_y);
         mWallOffYView.addTextChangedListener(mTextWatcher);
 
-        mPaddingLeftView = (TextView) findViewById(R.id.padding_left);
+        mPaddingLeftView = findViewById(R.id.padding_left);
         mPaddingLeftView.addTextChangedListener(mTextWatcher);
-        mPaddingRightView = (TextView) findViewById(R.id.padding_right);
+        mPaddingRightView = findViewById(R.id.padding_right);
         mPaddingRightView.addTextChangedListener(mTextWatcher);
-        mPaddingTopView = (TextView) findViewById(R.id.padding_top);
+        mPaddingTopView = findViewById(R.id.padding_top);
         mPaddingTopView.addTextChangedListener(mTextWatcher);
-        mPaddingBottomView = (TextView) findViewById(R.id.padding_bottom);
+        mPaddingBottomView = findViewById(R.id.padding_bottom);
         mPaddingBottomView.addTextChangedListener(mTextWatcher);
 
-        mDispOffXView = (TextView) findViewById(R.id.dispoff_x);
+        mDispOffXView = findViewById(R.id.dispoff_x);
         mDispOffXView.addTextChangedListener(mTextWatcher);
-        mDispOffYView = (TextView) findViewById(R.id.dispoff_y);
+        mDispOffYView = findViewById(R.id.dispoff_y);
         mDispOffYView.addTextChangedListener(mTextWatcher);
 
         updateDimens();
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index b984bbf..ceb0135 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -36,21 +36,50 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
-
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.content.pm.ApplicationInfo;
+import android.os.Build.VERSION_CODES;
+import android.net.ConnectivityManager.NetworkCallback;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
-import org.junit.runner.RunWith;
+import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class ConnectivityManagerTest {
+
+    @Mock Context mCtx;
+    @Mock IConnectivityManager mService;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
     static NetworkCapabilities verifyNetworkCapabilities(
             int legacyType, int transportType, int... capabilities) {
         final NetworkCapabilities nc = ConnectivityManager.networkCapabilitiesForType(legacyType);
@@ -173,4 +202,124 @@
         verifyUnrestrictedNetworkCapabilities(
                 ConnectivityManager.TYPE_ETHERNET, TRANSPORT_ETHERNET);
     }
+
+    @Test
+    public void testCallbackRelease() throws Exception {
+        ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
+        NetworkRequest request = makeRequest(1);
+        NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class);
+        Handler handler = new Handler(Looper.getMainLooper());
+        ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
+
+        // register callback
+        when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt()))
+                .thenReturn(request);
+        manager.requestNetwork(request, callback, handler);
+
+        // callback triggers
+        captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_AVAILABLE));
+        verify(callback, timeout(500).times(1)).onAvailable(any());
+
+        // unregister callback
+        manager.unregisterNetworkCallback(callback);
+        verify(mService, times(1)).releaseNetworkRequest(request);
+
+        // callback does not trigger anymore.
+        captor.getValue().send(makeMessage(request, ConnectivityManager.CALLBACK_LOSING));
+        verify(callback, timeout(500).times(0)).onLosing(any(), anyInt());
+    }
+
+    @Test
+    public void testCallbackRecycling() throws Exception {
+        ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
+        NetworkRequest req1 = makeRequest(1);
+        NetworkRequest req2 = makeRequest(2);
+        NetworkCallback callback = mock(ConnectivityManager.NetworkCallback.class);
+        Handler handler = new Handler(Looper.getMainLooper());
+        ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
+
+        // register callback
+        when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt()))
+                .thenReturn(req1);
+        manager.requestNetwork(req1, callback, handler);
+
+        // callback triggers
+        captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_AVAILABLE));
+        verify(callback, timeout(100).times(1)).onAvailable(any());
+
+        // unregister callback
+        manager.unregisterNetworkCallback(callback);
+        verify(mService, times(1)).releaseNetworkRequest(req1);
+
+        // callback does not trigger anymore.
+        captor.getValue().send(makeMessage(req1, ConnectivityManager.CALLBACK_LOSING));
+        verify(callback, timeout(100).times(0)).onLosing(any(), anyInt());
+
+        // callback can be registered again
+        when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt()))
+                .thenReturn(req2);
+        manager.requestNetwork(req2, callback, handler);
+
+        // callback triggers
+        captor.getValue().send(makeMessage(req2, ConnectivityManager.CALLBACK_LOST));
+        verify(callback, timeout(100).times(1)).onLost(any());
+
+        // unregister callback
+        manager.unregisterNetworkCallback(callback);
+        verify(mService, times(1)).releaseNetworkRequest(req2);
+    }
+
+    // TODO: turn on this test when request  callback 1:1 mapping is enforced
+    //@Test
+    private void noDoubleCallbackRegistration() throws Exception {
+        ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
+        NetworkRequest request = makeRequest(1);
+        NetworkCallback callback = new ConnectivityManager.NetworkCallback();
+        ApplicationInfo info = new ApplicationInfo();
+        // TODO: update version when starting to enforce 1:1 mapping
+        info.targetSdkVersion = VERSION_CODES.N_MR1 + 1;
+
+        when(mCtx.getApplicationInfo()).thenReturn(info);
+        when(mService.requestNetwork(any(), any(), anyInt(), any(), anyInt())).thenReturn(request);
+
+        Handler handler = new Handler(Looper.getMainLooper());
+        manager.requestNetwork(request, callback, handler);
+
+        // callback is already registered, reregistration should fail.
+        Class<IllegalArgumentException> wantException = IllegalArgumentException.class;
+        expectThrowable(() -> manager.requestNetwork(request, callback), wantException);
+
+        manager.unregisterNetworkCallback(callback);
+        verify(mService, times(1)).releaseNetworkRequest(request);
+
+        // unregistering the callback should make it registrable again.
+        manager.requestNetwork(request, callback);
+    }
+
+    static Message makeMessage(NetworkRequest req, int messageType) {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(NetworkRequest.class.getSimpleName(), req);
+        Message msg = Message.obtain();
+        msg.what = messageType;
+        msg.setData(bundle);
+        return msg;
+    }
+
+    static NetworkRequest makeRequest(int requestId) {
+        NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
+        return new NetworkRequest(request.networkCapabilities, ConnectivityManager.TYPE_NONE,
+                requestId, NetworkRequest.Type.NONE);
+    }
+
+    static void expectThrowable(Runnable block, Class<? extends Throwable> throwableType) {
+        try {
+            block.run();
+        } catch (Throwable t) {
+            if (t.getClass().equals(throwableType)) {
+                return;
+            }
+            fail("expected exception of type " + throwableType + ", but was " + t.getClass());
+        }
+        fail("expected exception of type " + throwableType);
+    }
 }
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
new file mode 100644
index 0000000..e3b06c8
--- /dev/null
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
+import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+
+import android.net.NetworkCapabilities;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkCapabilitiesTest {
+    @Test
+    public void testMaybeMarkCapabilitiesRestricted() {
+        // verify EIMS is restricted
+        assertEquals((1 << NET_CAPABILITY_EIMS) & RESTRICTED_CAPABILITIES,
+                (1 << NET_CAPABILITY_EIMS));
+
+        // verify CBS is also restricted
+        assertEquals((1 << NET_CAPABILITY_CBS) & RESTRICTED_CAPABILITIES,
+                (1 << NET_CAPABILITY_CBS));
+
+        // verify default is not restricted
+        assertEquals((1 << NET_CAPABILITY_INTERNET) & RESTRICTED_CAPABILITIES, 0);
+
+        // just to see
+        assertEquals(RESTRICTED_CAPABILITIES & UNRESTRICTED_CAPABILITIES, 0);
+
+        // check that internet does not get restricted
+        NetworkCapabilities netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // metered-ness shouldn't matter
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.removeCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // add EIMS - bundled with unrestricted means it's unrestricted
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_INTERNET);
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.removeCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertTrue(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // just a restricted cap should be restricted regardless of meteredness
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.removeCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // try 2 restricted caps
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_CBS);
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        netCap = new NetworkCapabilities();
+        netCap.addCapability(NET_CAPABILITY_CBS);
+        netCap.addCapability(NET_CAPABILITY_EIMS);
+        netCap.removeCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.maybeMarkCapabilitiesRestricted();
+        assertFalse(netCap.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+    }
+
+}
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/tests/net/java/android/net/NetworkStatsHistoryTest.java
similarity index 99%
rename from core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
rename to tests/net/java/android/net/NetworkStatsHistoryTest.java
index 9a08f41..e7b91b5 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
+++ b/tests/net/java/android/net/NetworkStatsHistoryTest.java
@@ -38,7 +38,7 @@
 import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
-import com.android.frameworks.coretests.R;
+import com.android.frameworks.tests.net.R;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
similarity index 100%
rename from core/tests/coretests/src/android/net/NetworkStatsTest.java
rename to tests/net/java/android/net/NetworkStatsTest.java
diff --git a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
similarity index 99%
rename from core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
rename to tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index 7f13abc..978e5f5 100644
--- a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -30,7 +30,7 @@
 import android.net.TrafficStats;
 import android.test.AndroidTestCase;
 
-import com.android.frameworks.coretests.R;
+import com.android.frameworks.tests.net.R;
 
 import java.io.File;
 import java.io.FileOutputStream;
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index d819b96..d11565a 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -45,7 +45,9 @@
 import android.net.metrics.RaEvent;
 import android.net.metrics.ValidationProbeEvent;
 import android.test.suitebuilder.annotation.SmallTest;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
 import java.util.Arrays;
+import java.util.List;
 import junit.framework.TestCase;
 
 // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
@@ -57,7 +59,7 @@
                 aType(IpReachabilityEvent.class),
                 anInt(IpReachabilityEvent.NUD_FAILED));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -70,13 +72,13 @@
                 "    if_name: \"\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
         verifySerialization(want, ev);
 
         ev.netId = 123;
         ev.transports = 3; // transports have priority for inferrence of link layer
         ev.ifname = "wlan0";
-        want = joinLines(
+        want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -89,12 +91,12 @@
                 "    if_name: \"\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
         verifySerialization(want, ev);
 
         ev.transports = 1;
         ev.ifname = null;
-        want = joinLines(
+        want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -107,12 +109,12 @@
                 "    if_name: \"\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
         verifySerialization(want, ev);
 
         ev.transports = 0;
         ev.ifname = "not_inferred";
-        want = joinLines(
+        want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"not_inferred\"",
@@ -125,11 +127,11 @@
                 "    if_name: \"\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
         verifySerialization(want, ev);
 
         ev.ifname = "bt-pan";
-        want = joinLines(
+        want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -142,11 +144,11 @@
                 "    if_name: \"\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
         verifySerialization(want, ev);
 
         ev.ifname = "rmnet_ipa0";
-        want = joinLines(
+        want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -159,11 +161,11 @@
                 "    if_name: \"\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
         verifySerialization(want, ev);
 
         ev.ifname = "wlan0";
-        want = joinLines(
+        want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -176,7 +178,7 @@
                 "    if_name: \"\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
         verifySerialization(want, ev);
     }
 
@@ -190,7 +192,7 @@
                 aBool(true),
                 aBool(false));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -211,7 +213,7 @@
                 "    transport_types: 3",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -223,7 +225,7 @@
                 aString("SomeState"),
                 anInt(192));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -237,7 +239,7 @@
                 "    state_transition: \"SomeState\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -248,7 +250,7 @@
                 aType(DhcpErrorEvent.class),
                 anInt(DhcpErrorEvent.L4_NOT_UDP));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -262,59 +264,7 @@
                 "    error_code: 50397184",
                 "  >",
                 ">",
-                "version: 2");
-
-        verifySerialization(want, ev);
-    }
-
-    @SmallTest
-    public void testDnsEventSerialization() {
-        ConnectivityMetricsEvent ev = describeIpEvent(
-                aType(DnsEvent.class),
-                anInt(101),
-                aByteArray(b(1), b(1), b(2), b(1), b(1), b(1), b(2), b(2)),
-                aByteArray(b(0), b(0), b(22), b(3), b(1), b(0), b(200), b(178)),
-                anIntArray(3456, 267, 1230, 45, 2111, 450, 638, 1300));
-
-        String want = joinLines(
-                "dropped_events: 0",
-                "events <",
-                "  if_name: \"\"",
-                "  link_layer: 0",
-                "  network_id: 0",
-                "  time_ms: 1",
-                "  transports: 0",
-                "  dns_lookup_batch <",
-                "    event_types: 1",
-                "    event_types: 1",
-                "    event_types: 2",
-                "    event_types: 1",
-                "    event_types: 1",
-                "    event_types: 1",
-                "    event_types: 2",
-                "    event_types: 2",
-                "    latencies_ms: 3456",
-                "    latencies_ms: 267",
-                "    latencies_ms: 1230",
-                "    latencies_ms: 45",
-                "    latencies_ms: 2111",
-                "    latencies_ms: 450",
-                "    latencies_ms: 638",
-                "    latencies_ms: 1300",
-                "    network_id <",
-                "      network_id: 101",
-                "    >",
-                "    return_codes: 0",
-                "    return_codes: 0",
-                "    return_codes: 22",
-                "    return_codes: 3",
-                "    return_codes: 1",
-                "    return_codes: 0",
-                "    return_codes: 200",
-                "    return_codes: 178",
-                "  >",
-                ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -326,7 +276,7 @@
                 anInt(IpManagerEvent.PROVISIONING_OK),
                 aLong(5678));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -340,7 +290,7 @@
                 "    latency_ms: 5678",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -351,7 +301,7 @@
                 aType(IpReachabilityEvent.class),
                 anInt(IpReachabilityEvent.NUD_FAILED));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -364,7 +314,7 @@
                 "    if_name: \"\"",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -377,7 +327,7 @@
                 anInt(5),
                 aLong(20410));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -393,7 +343,7 @@
                 "    >",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -406,7 +356,7 @@
                 anInt(ValidationProbeEvent.PROBE_HTTP),
                 anInt(204));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -420,7 +370,7 @@
                 "    probe_type: 1",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -436,7 +386,7 @@
                 anInt(2048),
                 anInt(3));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -454,7 +404,7 @@
                 "    program_length: 2048",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -474,7 +424,7 @@
                 anInt(3),
                 anInt(2048));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -495,7 +445,7 @@
                 "    zero_lifetime_ras: 1",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
@@ -511,7 +461,7 @@
                 aLong(1000),
                 aLong(-1));
 
-        String want = joinLines(
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -528,28 +478,20 @@
                 "    router_lifetime: 2000",
                 "  >",
                 ">",
-                "version: 2");
+                "version: 2\n");
 
         verifySerialization(want, ev);
     }
 
     static void verifySerialization(String want, ConnectivityMetricsEvent... input) {
         try {
-            byte[] got = IpConnectivityEventBuilder.serialize(0,
-                    IpConnectivityEventBuilder.toProto(Arrays.asList(input)));
+            List<IpConnectivityEvent> proto =
+                    IpConnectivityEventBuilder.toProto(Arrays.asList(input));
+            byte[] got = IpConnectivityEventBuilder.serialize(0, proto);
             IpConnectivityLog log = IpConnectivityLog.parseFrom(got);
             assertEquals(want, log.toString());
         } catch (Exception e) {
             fail(e.toString());
         }
     }
-
-    static String joinLines(String ... elems) {
-        StringBuilder b = new StringBuilder();
-        for (String s : elems) {
-            b.append(s);
-            b.append("\n");
-        }
-        return b.toString();
-    }
 }
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index 68786d0..e01469b 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -16,12 +16,22 @@
 
 package com.android.server.connectivity;
 
+import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
+import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.content.Context;
+import android.net.ConnectivityManager;
 import android.net.ConnectivityMetricsEvent;
 import android.net.IIpConnectivityMetrics;
+import android.net.Network;
+import android.net.NetworkCapabilities;
 import android.net.metrics.ApfProgramEvent;
 import android.net.metrics.ApfStats;
 import android.net.metrics.DefaultNetworkEvent;
@@ -31,7 +41,9 @@
 import android.net.metrics.IpReachabilityEvent;
 import android.net.metrics.RaEvent;
 import android.net.metrics.ValidationProbeEvent;
+import android.system.OsConstants;
 import android.os.Parcelable;
+import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Base64;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
@@ -41,26 +53,38 @@
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
-import junit.framework.TestCase;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class IpConnectivityMetricsTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpConnectivityMetricsTest {
     static final IpReachabilityEvent FAKE_EV =
             new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED);
 
+    private static final String EXAMPLE_IPV4 = "192.0.2.1";
+    private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
+
     @Mock Context mCtx;
     @Mock IIpConnectivityMetrics mMockService;
+    @Mock ConnectivityManager mCm;
 
     IpConnectivityMetrics mService;
+    NetdEventListenerService mNetdListener;
 
+    @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mService = new IpConnectivityMetrics(mCtx, (ctx) -> 2000);
+        mNetdListener = new NetdEventListenerService(mCm);
+        mService.mNetdListener = mNetdListener;
     }
 
-    @SmallTest
+    @Test
     public void testLoggingEvents() throws Exception {
         IpConnectivityLog logger = new IpConnectivityLog(mMockService);
 
@@ -74,7 +98,7 @@
         assertEventsEqual(expectedEvent(3), got.get(2));
     }
 
-    @SmallTest
+    @Test
     public void testLoggingEventsWithMultipleCallers() throws Exception {
         IpConnectivityLog logger = new IpConnectivityLog(mMockService);
 
@@ -91,7 +115,7 @@
             }.start();
         }
 
-        List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 100);
+        List<ConnectivityMetricsEvent> got = verifyEvents(nCallers * nEvents, 200);
         Collections.sort(got, EVENT_COMPARATOR);
         Iterator<ConnectivityMetricsEvent> iter = got.iterator();
         for (int i = 0; i < nCallers; i++) {
@@ -102,7 +126,7 @@
         }
     }
 
-    @SmallTest
+    @Test
     public void testBufferFlushing() {
         String output1 = getdump("flush");
         assertEquals("", output1);
@@ -115,7 +139,7 @@
         assertEquals("", output3);
     }
 
-    @SmallTest
+    @Test
     public void testRateLimiting() {
         final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
         final ApfProgramEvent ev = new ApfProgramEvent();
@@ -137,11 +161,19 @@
         assertEquals("", output2);
     }
 
-    @SmallTest
-    public void testEndToEndLogging() {
+    @Test
+    public void testEndToEndLogging() throws Exception {
         // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
         IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
 
+        NetworkCapabilities ncWifi = new NetworkCapabilities();
+        NetworkCapabilities ncCell = new NetworkCapabilities();
+        ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+        ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+
+        when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
+        when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
+
         ApfStats apfStats = new ApfStats();
         apfStats.durationMs = 45000;
         apfStats.receivedRas = 10;
@@ -177,7 +209,22 @@
             logger.log(ev);
         }
 
-        String want = joinLines(
+        // netId, errno, latency, destination
+        connectEvent(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4);
+        connectEvent(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6);
+        connectEvent(100, 0, 110, EXAMPLE_IPV4);
+        connectEvent(101, 0, 23, EXAMPLE_IPV4);
+        connectEvent(101, 0, 45, EXAMPLE_IPV6);
+        connectEvent(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4);
+
+        // netId, type, return code, latency
+        dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
+        dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
+        dnsEvent(100, EVENT_GETHOSTBYNAME, 0, 638);
+        dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
+        dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 34);
+
+        String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
@@ -279,7 +326,71 @@
                 "    router_lifetime: 2000",
                 "  >",
                 ">",
-                "version: 2");
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 4",
+                "  network_id: 100",
+                "  time_ms: 0",
+                "  transports: 2",
+                "  connect_statistics <",
+                "    connect_blocking_count: 1",
+                "    connect_count: 3",
+                "    errnos_counters <",
+                "      key: 11",
+                "      value: 1",
+                "    >",
+                "    ipv6_addr_count: 1",
+                "    latencies_ms: 110",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 2",
+                "  network_id: 101",
+                "  time_ms: 0",
+                "  transports: 1",
+                "  connect_statistics <",
+                "    connect_blocking_count: 2",
+                "    connect_count: 2",
+                "    ipv6_addr_count: 1",
+                "    latencies_ms: 23",
+                "    latencies_ms: 45",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 4",
+                "  network_id: 100",
+                "  time_ms: 0",
+                "  transports: 2",
+                "  dns_lookup_batch <",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 2",
+                "    latencies_ms: 3456",
+                "    latencies_ms: 45",
+                "    latencies_ms: 638",
+                "    return_codes: 0",
+                "    return_codes: 3",
+                "    return_codes: 0",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 2",
+                "  network_id: 101",
+                "  time_ms: 0",
+                "  transports: 1",
+                "  dns_lookup_batch <",
+                "    event_types: 1",
+                "    event_types: 2",
+                "    latencies_ms: 56",
+                "    latencies_ms: 34",
+                "    return_codes: 0",
+                "    return_codes: 0",
+                "  >",
+                ">",
+                "version: 2\n");
 
         verifySerialization(want, getdump("flush"));
     }
@@ -291,6 +402,14 @@
         return buffer.toString();
     }
 
+    void connectEvent(int netid, int error, int latencyMs, String ipAddr) throws Exception {
+        mNetdListener.onConnectEvent(netid, error, latencyMs, ipAddr, 80, 1);
+    }
+
+    void dnsEvent(int netId, int type, int result, int latency) throws Exception {
+        mNetdListener.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
+    }
+
     List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
         ArgumentCaptor<ConnectivityMetricsEvent> captor =
                 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
diff --git a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 0ab4406..f98ab3d 100644
--- a/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -16,190 +16,182 @@
 
 package com.android.server.connectivity;
 
-import android.net.ConnectivityManager;
-import android.net.ConnectivityManager.NetworkCallback;
-import android.net.Network;
-import android.net.metrics.ConnectStats;
-import android.net.metrics.DnsEvent;
-import android.net.metrics.INetdEventListener;
-import android.net.metrics.IpConnectivityLog;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.system.OsConstants;
-import android.test.suitebuilder.annotation.SmallTest;
-import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-import java.util.OptionalInt;
-import java.util.stream.IntStream;
-import junit.framework.TestCase;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertTrue;
+import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
+import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
-public class NetdEventListenerServiceTest extends TestCase {
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.support.test.runner.AndroidJUnit4;
+import android.system.OsConstants;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Base64;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.DNSLookupBatch;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-    // TODO: read from NetdEventListenerService after this constant is read from system property
-    static final int BATCH_SIZE = 100;
-    static final int EVENT_TYPE = INetdEventListener.EVENT_GETADDRINFO;
-    // TODO: read from INetdEventListener
-    static final int RETURN_CODE = 1;
-
-    static final byte[] EVENT_TYPES  = new byte[BATCH_SIZE];
-    static final byte[] RETURN_CODES = new byte[BATCH_SIZE];
-    static final int[] LATENCIES     = new int[BATCH_SIZE];
-    static {
-        for (int i = 0; i < BATCH_SIZE; i++) {
-            EVENT_TYPES[i] = EVENT_TYPE;
-            RETURN_CODES[i] = RETURN_CODE;
-            LATENCIES[i] = i;
-        }
-    }
-
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetdEventListenerServiceTest {
     private static final String EXAMPLE_IPV4 = "192.0.2.1";
     private static final String EXAMPLE_IPV6 = "2001:db8:1200::2:1";
 
     NetdEventListenerService mNetdEventListenerService;
+    ConnectivityManager mCm;
 
-    @Mock ConnectivityManager mCm;
-    @Mock IpConnectivityLog mLog;
-    ArgumentCaptor<NetworkCallback> mCallbackCaptor;
-    ArgumentCaptor<DnsEvent> mDnsEvCaptor;
-
+    @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class);
-        mDnsEvCaptor = ArgumentCaptor.forClass(DnsEvent.class);
-        mNetdEventListenerService = new NetdEventListenerService(mCm, mLog);
+        NetworkCapabilities ncWifi = new NetworkCapabilities();
+        NetworkCapabilities ncCell = new NetworkCapabilities();
+        ncWifi.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+        ncCell.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
 
-        verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture());
+        mCm = mock(ConnectivityManager.class);
+        when(mCm.getNetworkCapabilities(new Network(100))).thenReturn(ncWifi);
+        when(mCm.getNetworkCapabilities(new Network(101))).thenReturn(ncCell);
+
+        mNetdEventListenerService = new NetdEventListenerService(mCm);
     }
 
-    @SmallTest
-    public void testOneDnsBatch() throws Exception {
-        log(105, LATENCIES);
-        log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event
+    @Test
+    public void testDnsLogging() throws Exception {
+        asyncDump(100);
 
-        verifyLoggedDnsEvents(new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
+        dnsEvent(100, EVENT_GETADDRINFO, 0, 3456);
+        dnsEvent(100, EVENT_GETADDRINFO, 0, 267);
+        dnsEvent(100, EVENT_GETHOSTBYNAME, 22, 1230);
+        dnsEvent(100, EVENT_GETADDRINFO, 3, 45);
+        dnsEvent(100, EVENT_GETADDRINFO, 1, 2111);
+        dnsEvent(100, EVENT_GETADDRINFO, 0, 450);
+        dnsEvent(100, EVENT_GETHOSTBYNAME, 200, 638);
+        dnsEvent(100, EVENT_GETHOSTBYNAME, 178, 1300);
+        dnsEvent(101, EVENT_GETADDRINFO, 0, 56);
+        dnsEvent(101, EVENT_GETADDRINFO, 0, 78);
+        dnsEvent(101, EVENT_GETADDRINFO, 0, 14);
+        dnsEvent(101, EVENT_GETHOSTBYNAME, 0, 56);
+        dnsEvent(101, EVENT_GETADDRINFO, 0, 78);
+        dnsEvent(101, EVENT_GETADDRINFO, 0, 14);
 
-        log(106, Arrays.copyOfRange(LATENCIES, BATCH_SIZE - 1, BATCH_SIZE));
-
-        mDnsEvCaptor = ArgumentCaptor.forClass(DnsEvent.class); // reset argument captor
-        verifyLoggedDnsEvents(
-            new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
-            new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES));
+        String got = flushStatistics();
+        String want = String.join("\n",
+                "dropped_events: 0",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 4",
+                "  network_id: 100",
+                "  time_ms: 0",
+                "  transports: 2",
+                "  dns_lookup_batch <",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 2",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 2",
+                "    event_types: 2",
+                "    latencies_ms: 3456",
+                "    latencies_ms: 267",
+                "    latencies_ms: 1230",
+                "    latencies_ms: 45",
+                "    latencies_ms: 2111",
+                "    latencies_ms: 450",
+                "    latencies_ms: 638",
+                "    latencies_ms: 1300",
+                "    return_codes: 0",
+                "    return_codes: 0",
+                "    return_codes: 22",
+                "    return_codes: 3",
+                "    return_codes: 1",
+                "    return_codes: 0",
+                "    return_codes: 200",
+                "    return_codes: 178",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 2",
+                "  network_id: 101",
+                "  time_ms: 0",
+                "  transports: 1",
+                "  dns_lookup_batch <",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    event_types: 2",
+                "    event_types: 1",
+                "    event_types: 1",
+                "    latencies_ms: 56",
+                "    latencies_ms: 78",
+                "    latencies_ms: 14",
+                "    latencies_ms: 56",
+                "    latencies_ms: 78",
+                "    latencies_ms: 14",
+                "    return_codes: 0",
+                "    return_codes: 0",
+                "    return_codes: 0",
+                "    return_codes: 0",
+                "    return_codes: 0",
+                "    return_codes: 0",
+                "  >",
+                ">",
+                "version: 2\n");
+        assertEquals(want, got);
     }
 
-    @SmallTest
-    public void testSeveralDmsBatches() throws Exception {
-        log(105, LATENCIES);
-        log(106, LATENCIES);
-        log(105, LATENCIES);
-        log(107, LATENCIES);
-
-        verifyLoggedDnsEvents(
-            new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
-            new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES),
-            new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
-            new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
-    }
-
-    @SmallTest
-    public void testDnsBatchAndNetworkLost() throws Exception {
-        byte[] eventTypes = Arrays.copyOf(EVENT_TYPES, 20);
-        byte[] returnCodes = Arrays.copyOf(RETURN_CODES, 20);
-        int[] latencies = Arrays.copyOf(LATENCIES, 20);
-
-        log(105, LATENCIES);
-        log(105, latencies);
-        mCallbackCaptor.getValue().onLost(new Network(105));
-        log(105, LATENCIES);
-
-        verifyLoggedDnsEvents(
-            new DnsEvent(105, eventTypes, returnCodes, latencies),
-            new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
-            new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
-    }
-
-    @SmallTest
-    public void testConcurrentDnsBatchesAndDumps() throws Exception {
-        final long stop = System.currentTimeMillis() + 100;
-        final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
-        new Thread() {
-            public void run() {
-                while (System.currentTimeMillis() < stop) {
-                    mNetdEventListenerService.dump(pw);
-                }
-            }
-        }.start();
-
-        logDnsAsync(105, LATENCIES);
-        logDnsAsync(106, LATENCIES);
-        logDnsAsync(107, LATENCIES);
-
-        verifyLoggedDnsEvents(500,
-            new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
-            new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES),
-            new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
-    }
-
-    @SmallTest
-    public void testConcurrentDnsBatchesAndNetworkLoss() throws Exception {
-        logDnsAsync(105, LATENCIES);
-        Thread.sleep(10L);
-        // call onLost() asynchronously to logDnsAsync's onDnsEvent() calls.
-        mCallbackCaptor.getValue().onLost(new Network(105));
-
-        // do not verify batch with unpredictable length
-        verify(mLog, timeout(500).times(1)).log(any(Parcelable.class));
-    }
-
-    @SmallTest
+    @Test
     public void testConnectLogging() throws Exception {
+        asyncDump(100);
+
         final int OK = 0;
         Thread[] logActions = {
             // ignored
-            connectEventAction(OsConstants.EALREADY, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.EALREADY, 0, EXAMPLE_IPV6),
-            connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
-            connectEventAction(OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
+            connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV4),
+            connectEventAction(100, OsConstants.EALREADY, 0, EXAMPLE_IPV6),
+            connectEventAction(100, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV4),
+            connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
+            connectEventAction(101, OsConstants.EINPROGRESS, 0, EXAMPLE_IPV6),
             // valid latencies
-            connectEventAction(OK, 110, EXAMPLE_IPV4),
-            connectEventAction(OK, 23, EXAMPLE_IPV4),
-            connectEventAction(OK, 45, EXAMPLE_IPV4),
-            connectEventAction(OK, 56, EXAMPLE_IPV4),
-            connectEventAction(OK, 523, EXAMPLE_IPV6),
-            connectEventAction(OK, 214, EXAMPLE_IPV6),
-            connectEventAction(OK, 67, EXAMPLE_IPV6),
+            connectEventAction(100, OK, 110, EXAMPLE_IPV4),
+            connectEventAction(100, OK, 23, EXAMPLE_IPV4),
+            connectEventAction(100, OK, 45, EXAMPLE_IPV4),
+            connectEventAction(101, OK, 56, EXAMPLE_IPV4),
+            connectEventAction(101, OK, 523, EXAMPLE_IPV6),
+            connectEventAction(101, OK, 214, EXAMPLE_IPV6),
+            connectEventAction(101, OK, 67, EXAMPLE_IPV6),
             // errors
-            connectEventAction(OsConstants.EPERM, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.EPERM, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.EAGAIN, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.EACCES, 0, EXAMPLE_IPV6),
-            connectEventAction(OsConstants.EADDRINUSE, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV4),
-            connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
-            connectEventAction(OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
-            connectEventAction(OsConstants.ECONNREFUSED, 0, EXAMPLE_IPV4),
+            connectEventAction(100, OsConstants.EPERM, 0, EXAMPLE_IPV4),
+            connectEventAction(101, OsConstants.EPERM, 0, EXAMPLE_IPV4),
+            connectEventAction(100, OsConstants.EAGAIN, 0, EXAMPLE_IPV4),
+            connectEventAction(100, OsConstants.EACCES, 0, EXAMPLE_IPV4),
+            connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV4),
+            connectEventAction(101, OsConstants.EACCES, 0, EXAMPLE_IPV6),
+            connectEventAction(100, OsConstants.EADDRINUSE, 0, EXAMPLE_IPV4),
+            connectEventAction(101, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV4),
+            connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
+            connectEventAction(100, OsConstants.ETIMEDOUT, 0, EXAMPLE_IPV6),
+            connectEventAction(101, OsConstants.ECONNREFUSED, 0, EXAMPLE_IPV4),
         };
 
         for (Thread t : logActions) {
@@ -209,113 +201,124 @@
             t.join();
         }
 
-        List<IpConnectivityEvent> events = new ArrayList<>();
-        mNetdEventListenerService.flushStatistics(events);
-
-        IpConnectivityEvent got = events.get(0);
+        String got = flushStatistics();
         String want = String.join("\n",
-                "if_name: \"\"",
-                "link_layer: 0",
-                "network_id: 0",
-                "time_ms: 0",
-                "transports: 0",
-                "connect_statistics <",
-                "  connect_blocking_count: 7",
-                "  connect_count: 12",
-                "  errnos_counters <",
-                "    key: 1",
-                "    value: 2",
+                "dropped_events: 0",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 4",
+                "  network_id: 100",
+                "  time_ms: 0",
+                "  transports: 2",
+                "  connect_statistics <",
+                "    connect_blocking_count: 3",
+                "    connect_count: 6",
+                "    errnos_counters <",
+                "      key: 1",
+                "      value: 1",
+                "    >",
+                "    errnos_counters <",
+                "      key: 11",
+                "      value: 1",
+                "    >",
+                "    errnos_counters <",
+                "      key: 13",
+                "      value: 1",
+                "    >",
+                "    errnos_counters <",
+                "      key: 98",
+                "      value: 1",
+                "    >",
+                "    errnos_counters <",
+                "      key: 110",
+                "      value: 2",
+                "    >",
+                "    ipv6_addr_count: 1",
+                "    latencies_ms: 23",
+                "    latencies_ms: 45",
+                "    latencies_ms: 110",
                 "  >",
-                "  errnos_counters <",
-                "    key: 11",
-                "    value: 1",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 2",
+                "  network_id: 101",
+                "  time_ms: 0",
+                "  transports: 1",
+                "  connect_statistics <",
+                "    connect_blocking_count: 4",
+                "    connect_count: 6",
+                "    errnos_counters <",
+                "      key: 1",
+                "      value: 1",
+                "    >",
+                "    errnos_counters <",
+                "      key: 13",
+                "      value: 2",
+                "    >",
+                "    errnos_counters <",
+                "      key: 110",
+                "      value: 1",
+                "    >",
+                "    errnos_counters <",
+                "      key: 111",
+                "      value: 1",
+                "    >",
+                "    ipv6_addr_count: 5",
+                "    latencies_ms: 56",
+                "    latencies_ms: 67",
+                "    latencies_ms: 214",
+                "    latencies_ms: 523",
                 "  >",
-                "  errnos_counters <",
-                "    key: 13",
-                "    value: 3",
-                "  >",
-                "  errnos_counters <",
-                "    key: 98",
-                "    value: 1",
-                "  >",
-                "  errnos_counters <",
-                "    key: 110",
-                "    value: 3",
-                "  >",
-                "  errnos_counters <",
-                "    key: 111",
-                "    value: 1",
-                "  >",
-                "  ipv6_addr_count: 6",
-                "  latencies_ms: 23",
-                "  latencies_ms: 45",
-                "  latencies_ms: 56",
-                "  latencies_ms: 67",
-                "  latencies_ms: 110",
-                "  latencies_ms: 214",
-                "  latencies_ms: 523",
-                ">\n");
-        verifyConnectEvent(want, got);
+                ">",
+                "version: 2\n");
+        assertEquals(want, got);
     }
 
-    Thread connectEventAction(int error, int latencyMs, String ipAddr) {
+    Thread connectEventAction(int netId, int error, int latencyMs, String ipAddr) {
         return new Thread(() -> {
             try {
-                mNetdEventListenerService.onConnectEvent(100, error, latencyMs, ipAddr, 80, 1);
+                mNetdEventListenerService.onConnectEvent(netId, error, latencyMs, ipAddr, 80, 1);
             } catch (Exception e) {
                 fail(e.toString());
             }
         });
     }
 
-    void log(int netId, int[] latencies) {
-        try {
-            for (int l : latencies) {
-                mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l, null, null,
-                        0, 0);
+    void dnsEvent(int netId, int type, int result, int latency) throws Exception {
+        mNetdEventListenerService.onDnsEvent(netId, type, result, latency, "", null, 0, 0);
+    }
+
+    void asyncDump(long durationMs) throws Exception {
+        final long stop = System.currentTimeMillis() + durationMs;
+        final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
+        new Thread(() -> {
+            while (System.currentTimeMillis() < stop) {
+                mNetdEventListenerService.dump(pw);
             }
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
+        }).start();
     }
 
-    void logDnsAsync(int netId, int[] latencies) {
-        new Thread(() -> log(netId, latencies)).start();
-    }
+    // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
+    String flushStatistics() throws Exception {
+        IpConnectivityMetrics metricsService =
+                new IpConnectivityMetrics(mock(Context.class), (ctx) -> 2000);
+        metricsService.mNetdListener = mNetdEventListenerService;
 
-    void verifyLoggedDnsEvents(DnsEvent... expected) {
-        verifyLoggedDnsEvents(0, expected);
-    }
-
-    void verifyLoggedDnsEvents(int wait, DnsEvent... expectedEvents) {
-        verify(mLog, timeout(wait).times(expectedEvents.length)).log(mDnsEvCaptor.capture());
-        for (DnsEvent got : mDnsEvCaptor.getAllValues()) {
-            OptionalInt index = IntStream.range(0, expectedEvents.length)
-                    .filter(i -> dnsEventsEqual(expectedEvents[i], got))
-                    .findFirst();
-            // Don't match same expected event more than once.
-            index.ifPresent(i -> expectedEvents[i] = null);
-            assertTrue(index.isPresent());
-        }
-    }
-
-    /** equality function for DnsEvent to avoid overriding equals() and hashCode(). */
-    static boolean dnsEventsEqual(DnsEvent expected, DnsEvent got) {
-        return (expected == got) || ((expected != null) && (got != null)
-                && (expected.netId == got.netId)
-                && Arrays.equals(expected.eventTypes, got.eventTypes)
-                && Arrays.equals(expected.returnCodes, got.returnCodes)
-                && Arrays.equals(expected.latenciesMs, got.latenciesMs));
-    }
-
-    static void verifyConnectEvent(String expected, IpConnectivityEvent got) {
-        try {
-            Arrays.sort(got.getConnectStatistics().latenciesMs);
-            Arrays.sort(got.getConnectStatistics().errnosCounters,
+        StringWriter buffer = new StringWriter();
+        PrintWriter writer = new PrintWriter(buffer);
+        metricsService.impl.dump(null, writer, new String[]{"flush"});
+        byte[] bytes = Base64.decode(buffer.toString(), Base64.DEFAULT);
+        IpConnectivityLog log = IpConnectivityLog.parseFrom(bytes);
+        for (IpConnectivityEvent ev : log.events) {
+            if (ev.getConnectStatistics() == null) {
+                continue;
+            }
+            // Sort repeated fields of connect() events arriving in non-deterministic order.
+            Arrays.sort(ev.getConnectStatistics().latenciesMs);
+            Arrays.sort(ev.getConnectStatistics().errnosCounters,
                     Comparator.comparingInt((p) -> p.key));
-            assertEquals(expected, got.toString());
-        } catch (Exception e) {
-            fail(e.toString());
         }
+        return log.toString();
     }
 }
diff --git a/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java b/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java
new file mode 100644
index 0000000..b5d333b
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/tethering/SimChangeListenerTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.tethering;
+
+import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_ABSENT;
+import static com.android.internal.telephony.IccCardConstants.INTENT_VALUE_ICC_LOADED;
+import static com.android.internal.telephony.IccCardConstants.INTENT_KEY_ICC_STATE;
+import static com.android.internal.telephony.TelephonyIntents.ACTION_SIM_STATE_CHANGED;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.reset;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.test.BroadcastInterceptingContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SimChangeListenerTest {
+    private static final int EVENT_UNM_UPDATE = 1;
+
+    @Mock private Context mContext;
+    private BroadcastInterceptingContext mServiceContext;
+    private Handler mHandler;
+    private SimChangeListener mSCL;
+    private int mCallbackCount;
+
+    private void doCallback() { mCallbackCount++; }
+
+    private class MockContext extends BroadcastInterceptingContext {
+        MockContext(Context base) {
+            super(base);
+        }
+    }
+
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+    }
+
+    @Before public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        reset(mContext);
+        mServiceContext = new MockContext(mContext);
+        mHandler = new Handler(Looper.myLooper());
+        mCallbackCount = 0;
+        mSCL = new SimChangeListener(mServiceContext, mHandler, () -> doCallback());
+    }
+
+    @After public void tearDown() throws Exception {
+        if (mSCL != null) {
+            mSCL.stopListening();
+            mSCL = null;
+        }
+    }
+
+    private void sendSimStateChangeIntent(String state) {
+        final Intent intent = new Intent(ACTION_SIM_STATE_CHANGED);
+        intent.putExtra(INTENT_KEY_ICC_STATE, state);
+        mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    @Test
+    public void testNotSeenFollowedBySeenCallsCallback() {
+        mSCL.startListening();
+
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
+        assertEquals(1, mCallbackCount);
+
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
+        assertEquals(2, mCallbackCount);
+
+        mSCL.stopListening();
+    }
+
+    @Test
+    public void testNotListeningDoesNotCallback() {
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
+        assertEquals(0, mCallbackCount);
+
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_ABSENT);
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
+        assertEquals(0, mCallbackCount);
+    }
+
+    @Test
+    public void testSeenOnlyDoesNotCallback() {
+        mSCL.startListening();
+
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
+        assertEquals(0, mCallbackCount);
+
+        sendSimStateChangeIntent(INTENT_VALUE_ICC_LOADED);
+        assertEquals(0, mCallbackCount);
+
+        mSCL.stopListening();
+    }
+}
diff --git a/core/tests/coretests/res/raw/history_v1 b/tests/net/res/raw/history_v1
similarity index 100%
rename from core/tests/coretests/res/raw/history_v1
rename to tests/net/res/raw/history_v1
Binary files differ
diff --git a/core/tests/coretests/res/raw/xt_qtaguid_iface_fmt_typical b/tests/net/res/raw/xt_qtaguid_iface_fmt_typical
similarity index 100%
rename from core/tests/coretests/res/raw/xt_qtaguid_iface_fmt_typical
rename to tests/net/res/raw/xt_qtaguid_iface_fmt_typical
diff --git a/core/tests/coretests/res/raw/xt_qtaguid_iface_typical b/tests/net/res/raw/xt_qtaguid_iface_typical
similarity index 100%
rename from core/tests/coretests/res/raw/xt_qtaguid_iface_typical
rename to tests/net/res/raw/xt_qtaguid_iface_typical
diff --git a/core/tests/coretests/res/raw/xt_qtaguid_typical b/tests/net/res/raw/xt_qtaguid_typical
similarity index 100%
rename from core/tests/coretests/res/raw/xt_qtaguid_typical
rename to tests/net/res/raw/xt_qtaguid_typical
diff --git a/tests/radio/src/android/hardware/radio/tests/RadioTest.java b/tests/radio/src/android/hardware/radio/tests/RadioTest.java
index 47fbe74..384ddbc 100644
--- a/tests/radio/src/android/hardware/radio/tests/RadioTest.java
+++ b/tests/radio/src/android/hardware/radio/tests/RadioTest.java
@@ -94,4 +94,12 @@
     public void testOpenTuner() {
         openTuner(new RadioTuner.Callback() {});
     }
+
+    @Test
+    public void testReopenTuner() {
+        openTuner(new RadioTuner.Callback() {});
+        mRadioTuner.close();
+        mRadioTuner = null;
+        openTuner(new RadioTuner.Callback() {});
+    }
 }
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 2bf5206..bd2b2a36 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -782,7 +782,79 @@
     }
 }
 
-status_t massageManifest(Bundle* bundle, sp<XMLNode> root)
+static sp<ResourceTable::ConfigList> findEntry(const String16& packageStr, const String16& typeStr,
+                                               const String16& nameStr, ResourceTable* table) {
+  sp<ResourceTable::Package> pkg = table->getPackage(packageStr);
+  if (pkg != NULL) {
+      sp<ResourceTable::Type> type = pkg->getTypes().valueFor(typeStr);
+      if (type != NULL) {
+          return type->getConfigs().valueFor(nameStr);
+      }
+  }
+  return NULL;
+}
+
+static uint16_t getMaxSdkVersion(const sp<ResourceTable::ConfigList>& configList) {
+  const DefaultKeyedVector<ConfigDescription, sp<ResourceTable::Entry>>& entries =
+          configList->getEntries();
+  uint16_t maxSdkVersion = 0u;
+  for (size_t i = 0; i < entries.size(); i++) {
+    maxSdkVersion = std::max(maxSdkVersion, entries.keyAt(i).sdkVersion);
+  }
+  return maxSdkVersion;
+}
+
+static void massageRoundIconSupport(const String16& iconRef, const String16& roundIconRef,
+                                    ResourceTable* table) {
+  bool publicOnly = false;
+  const char* err;
+
+  String16 iconPackage, iconType, iconName;
+  if (!ResTable::expandResourceRef(iconRef.string(), iconRef.size(), &iconPackage, &iconType,
+                                   &iconName, NULL, &table->getAssetsPackage(), &err,
+                                   &publicOnly)) {
+      // Errors will be raised in later XML compilation.
+      return;
+  }
+
+  sp<ResourceTable::ConfigList> iconEntry = findEntry(iconPackage, iconType, iconName, table);
+  if (iconEntry == NULL || getMaxSdkVersion(iconEntry) < SDK_O) {
+      // The icon is not adaptive, so nothing to massage.
+      return;
+  }
+
+  String16 roundIconPackage, roundIconType, roundIconName;
+  if (!ResTable::expandResourceRef(roundIconRef.string(), roundIconRef.size(), &roundIconPackage,
+                                   &roundIconType, &roundIconName, NULL, &table->getAssetsPackage(),
+                                   &err, &publicOnly)) {
+      // Errors will be raised in later XML compilation.
+      return;
+  }
+
+  sp<ResourceTable::ConfigList> roundIconEntry = findEntry(roundIconPackage, roundIconType,
+                                                           roundIconName, table);
+  if (roundIconEntry == NULL || getMaxSdkVersion(roundIconEntry) >= SDK_O) {
+      // The developer explicitly used a v26 compatible drawable as the roundIcon, meaning we should
+      // not generate an alias to the icon drawable.
+      return;
+  }
+
+  String16 aliasValue = String16(String8::format("@%s:%s/%s", String8(iconPackage).string(),
+                                                 String8(iconType).string(),
+                                                 String8(iconName).string()));
+
+  // Add an equivalent v26 entry to the roundIcon for each v26 variant of the regular icon.
+  const DefaultKeyedVector<ConfigDescription, sp<ResourceTable::Entry>>& configList =
+          iconEntry->getEntries();
+  for (size_t i = 0; i < configList.size(); i++) {
+      if (configList.keyAt(i).sdkVersion >= SDK_O) {
+          table->addEntry(SourcePos(), roundIconPackage, roundIconType, roundIconName, aliasValue,
+                          NULL, &configList.keyAt(i));
+      }
+  }
+}
+
+status_t massageManifest(Bundle* bundle, ResourceTable* table, sp<XMLNode> root)
 {
     root = root->searchElement(String16(), String16("manifest"));
     if (root == NULL) {
@@ -916,7 +988,7 @@
             String8 tag(child->getElementName());
             if (tag == "instrumentation") {
                 XMLNode::attribute_entry* attr = child->editAttribute(
-                        String16("http://schemas.android.com/apk/res/android"), String16("targetPackage"));
+                        String16(RESOURCES_ANDROID_NAMESPACE), String16("targetPackage"));
                 if (attr != NULL) {
                     attr->string.setTo(String16(instrumentationPackageNameOverride));
                 }
@@ -924,6 +996,19 @@
         }
     }
     
+    sp<XMLNode> application = root->getChildElement(String16(), String16("application"));
+    if (application != NULL) {
+        XMLNode::attribute_entry* icon_attr = application->editAttribute(
+                String16(RESOURCES_ANDROID_NAMESPACE), String16("icon"));
+        if (icon_attr != NULL) {
+            XMLNode::attribute_entry* round_icon_attr = application->editAttribute(
+                    String16(RESOURCES_ANDROID_NAMESPACE), String16("roundIcon"));
+            if (round_icon_attr != NULL) {
+                massageRoundIconSupport(icon_attr->string, round_icon_attr->string, table);
+            }
+        }
+    }
+
     // Generate split name if feature is present.
     const XMLNode::attribute_entry* attr = root->getAttribute(String16(), String16("featureName"));
     if (attr != NULL) {
@@ -1638,7 +1723,7 @@
     if (manifestTree == NULL) {
         return UNKNOWN_ERROR;
     }
-    err = massageManifest(bundle, manifestTree);
+    err = massageManifest(bundle, &table, manifestTree);
     if (err < NO_ERROR) {
         return err;
     }
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index aff22d4..b340fc5 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -590,9 +590,10 @@
                        const String16& comment,
                        bool appendComment);
 
+    sp<Package> getPackage(const String16& package);
+
 private:
     void writePublicDefinitions(const String16& package, FILE* fp, bool pub);
-    sp<Package> getPackage(const String16& package);
     sp<Type> getType(const String16& package,
                      const String16& type,
                      const SourcePos& pos,
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 6e0809e..b86188f 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -87,6 +87,7 @@
   Maybe<std::string> generate_java_class_path;
   Maybe<std::string> custom_java_package;
   std::set<std::string> extra_java_packages;
+  Maybe<std::string> generate_text_symbols_path;
   Maybe<std::string> generate_proguard_rules_path;
   Maybe<std::string> generate_main_dex_proguard_rules_path;
   bool generate_non_final_ids = false;
@@ -376,8 +377,8 @@
         versioned_file_desc.config.sdkVersion = (uint16_t)sdk_level;
 
         FileOperation new_file_op;
-        new_file_op.xml_to_flatten =
-            util::make_unique<xml::XmlResource>(versioned_file_desc, doc->root->Clone());
+        new_file_op.xml_to_flatten = util::make_unique<xml::XmlResource>(
+            versioned_file_desc, StringPool{}, doc->root->Clone());
         new_file_op.config = versioned_file_desc.config;
         new_file_op.entry = file_op->entry;
         new_file_op.dst_path =
@@ -837,8 +838,8 @@
   }
 
   bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate,
-                     const StringPiece& out_package,
-                     const JavaClassGeneratorOptions& java_options) {
+                     const StringPiece& out_package, const JavaClassGeneratorOptions& java_options,
+                     const Maybe<std::string> out_text_symbols_path = {}) {
     if (!options_.generate_java_class_path) {
       return true;
     }
@@ -861,8 +862,20 @@
       return false;
     }
 
+    std::unique_ptr<std::ofstream> fout_text;
+    if (out_text_symbols_path) {
+      fout_text =
+          util::make_unique<std::ofstream>(out_text_symbols_path.value(), std::ofstream::binary);
+      if (!*fout_text) {
+        context_->GetDiagnostics()->Error(
+            DiagMessage() << "failed writing to '" << out_text_symbols_path.value()
+                          << "': " << android::base::SystemErrorCodeToString(errno));
+        return false;
+      }
+    }
+
     JavaClassGenerator generator(context_, table, java_options);
-    if (!generator.Generate(package_name_to_generate, out_package, &fout)) {
+    if (!generator.Generate(package_name_to_generate, out_package, &fout, fout_text.get())) {
       context_->GetDiagnostics()->Error(DiagMessage(out_path) << generator.getError());
       return false;
     }
@@ -1683,7 +1696,8 @@
             std::move(packages_to_callback);
       }
 
-      if (!WriteJavaFile(&final_table_, actual_package, output_package, options)) {
+      if (!WriteJavaFile(&final_table_, actual_package, output_package, options,
+                         options_.generate_text_symbols_path)) {
         return 1;
       }
     }
@@ -1785,9 +1799,9 @@
           .OptionalSwitch("-z", "Require localization of strings marked 'suggested'.",
                           &require_localization)
           .OptionalFlagList("-c",
-                        "Comma separated list of configurations to include. The default\n"
-                        "is all configurations.",
-                        &configs)
+                            "Comma separated list of configurations to include. The default\n"
+                            "is all configurations.",
+                            &configs)
           .OptionalFlag("--preferred-density",
                         "Selects the closest matching density and strips out all others.",
                         &preferred_density)
@@ -1841,6 +1855,10 @@
           .OptionalFlagList("--add-javadoc-annotation",
                             "Adds a JavaDoc annotation to all generated Java classes.",
                             &options.javadoc_annotations)
+          .OptionalFlag("--output-text-symbols",
+                        "Generates a text file containing the resource symbols of the R class in\n"
+                        "the specified folder.",
+                        &options.generate_text_symbols_path)
           .OptionalSwitch("--auto-add-overlay",
                           "Allows the addition of new resources in overlays without\n"
                           "<add-resource> tags.",
@@ -1855,7 +1873,8 @@
                             &options.extensions_to_not_compress)
           .OptionalFlagList("--split",
                             "Split resources matching a set of configs out to a Split APK.\n"
-                            "Syntax: path/to/output.apk:<config>[,<config>[...]].",
+                            "Syntax: path/to/output.apk:<config>[,<config>[...]].\n"
+                            "On Windows, use a semicolon ';' separator instead.",
                             &split_args)
           .OptionalSwitch("-v", "Enables verbose logging.", &verbose);
 
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
index 8f8e0c8..e99ee8a 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -302,7 +302,8 @@
                             &configs)
           .OptionalFlagList("--split",
                             "Split resources matching a set of configs out to a "
-                            "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]].",
+                            "Split APK.\nSyntax: path/to/output.apk;<config>[,<config>[...]].\n"
+                            "On Windows, use a semicolon ';' separator instead.",
                             &split_args)
           .OptionalSwitch("--enable-sparse-encoding",
                           "Enables encoding sparse entries using a binary search tree.\n"
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
index fd94bbc..14d4260 100644
--- a/tools/aapt2/cmd/Util.cpp
+++ b/tools/aapt2/cmd/Util.cpp
@@ -57,10 +57,17 @@
   CHECK(out_path != nullptr);
   CHECK(out_split != nullptr);
 
-  std::vector<std::string> parts = util::Split(arg, ':');
+#ifdef _WIN32
+  const char sSeparator = ';';
+#else
+  const char sSeparator = ':';
+#endif
+
+  std::vector<std::string> parts = util::Split(arg, sSeparator);
   if (parts.size() != 2) {
     diag->Error(DiagMessage() << "invalid split parameter '" << arg << "'");
-    diag->Note(DiagMessage() << "should be --split path/to/output.apk:<config>[,<config>...]");
+    diag->Note(DiagMessage() << "should be --split path/to/output.apk" << sSeparator
+                             << "<config>[,<config>...].");
     return false;
   }
 
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 68bdb95..a8226c0 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -22,6 +22,7 @@
 #include <sstream>
 #include <tuple>
 
+#include "android-base/errors.h"
 #include "android-base/logging.h"
 #include "android-base/stringprintf.h"
 #include "androidfw/StringPiece.h"
@@ -227,7 +228,8 @@
                                           const Styleable& styleable,
                                           const StringPiece& package_name_to_generate,
                                           ClassDefinition* out_class_def,
-                                          MethodDefinition* out_rewrite_method) {
+                                          MethodDefinition* out_rewrite_method,
+                                          std::ostream* out_r_txt) {
   const std::string array_field_name = TransformToFieldName(name.entry);
   std::unique_ptr<ResourceArrayMember> array_def =
       util::make_unique<ResourceArrayMember>(array_field_name);
@@ -328,10 +330,25 @@
     array_def->GetCommentBuilder()->AppendComment(styleable_comment.str());
   }
 
+  if (out_r_txt != nullptr) {
+    *out_r_txt << "int[] styleable " << array_field_name << " {";
+  }
+
   // Add the ResourceIds to the array member.
-  for (const StyleableAttr& styleable_attr : sorted_attributes) {
-    const ResourceId id = styleable_attr.attr_ref->id.value_or_default(ResourceId(0));
+  for (size_t i = 0; i < attr_count; i++) {
+    const ResourceId id = sorted_attributes[i].attr_ref->id.value_or_default(ResourceId(0));
     array_def->AddElement(id);
+
+    if (out_r_txt != nullptr) {
+      if (i != 0) {
+        *out_r_txt << ",";
+      }
+      *out_r_txt << " " << id;
+    }
+  }
+
+  if (out_r_txt != nullptr) {
+    *out_r_txt << " }\n";
   }
 
   // Add the Styleable array to the Styleable class.
@@ -386,6 +403,11 @@
     attr_processor->AppendComment(
         StringPrintf("@attr name %s:%s", package_name.data(), attr_name.entry.data()));
 
+    if (out_r_txt != nullptr) {
+      *out_r_txt << StringPrintf("int styleable %s %d\n", sorted_attributes[i].field_name.data(),
+                                 (int)i);
+    }
+
     out_class_def->AddMember(std::move(index_member));
   }
 
@@ -406,7 +428,8 @@
 
 void JavaClassGenerator::ProcessResource(const ResourceNameRef& name, const ResourceId& id,
                                          const ResourceEntry& entry, ClassDefinition* out_class_def,
-                                         MethodDefinition* out_rewrite_method) {
+                                         MethodDefinition* out_rewrite_method,
+                                         std::ostream* out_r_txt) {
   const std::string field_name = TransformToFieldName(name.entry);
   std::unique_ptr<ResourceMember> resource_member =
       util::make_unique<ResourceMember>(field_name, id);
@@ -434,6 +457,10 @@
 
   out_class_def->AddMember(std::move(resource_member));
 
+  if (out_r_txt != nullptr) {
+    *out_r_txt << "int " << name.type << " " << field_name << " " << id << "\n";
+  }
+
   if (out_rewrite_method != nullptr) {
     const StringPiece& type_str = ToString(name.type);
     out_rewrite_method->AppendStatement(StringPrintf("%s.%s = (%s.%s & 0x00ffffff) | (p << 24);",
@@ -470,7 +497,8 @@
                                      const ResourceTablePackage& package,
                                      const ResourceTableType& type,
                                      ClassDefinition* out_type_class_def,
-                                     MethodDefinition* out_rewrite_method_def) {
+                                     MethodDefinition* out_rewrite_method_def,
+                                     std::ostream* out_r_txt) {
   for (const auto& entry : type.entries) {
     const Maybe<std::string> unmangled_name =
         UnmangleResource(package.name, package_name_to_generate, *entry);
@@ -505,15 +533,17 @@
           static_cast<const Styleable*>(entry->values.front()->value.get());
 
       ProcessStyleable(resource_name, id, *styleable, package_name_to_generate, out_type_class_def,
-                       out_rewrite_method_def);
+                       out_rewrite_method_def, out_r_txt);
     } else {
-      ProcessResource(resource_name, id, *entry, out_type_class_def, out_rewrite_method_def);
+      ProcessResource(resource_name, id, *entry, out_type_class_def, out_rewrite_method_def,
+                      out_r_txt);
     }
   }
   return true;
 }
 
-bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, std::ostream* out) {
+bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate, std::ostream* out,
+                                  std::ostream* out_r_txt) {
   return Generate(package_name_to_generate, package_name_to_generate, out);
 }
 
@@ -527,8 +557,8 @@
 }
 
 bool JavaClassGenerator::Generate(const StringPiece& package_name_to_generate,
-                                  const StringPiece& out_package_name,
-                                  std::ostream* out) {
+                                  const StringPiece& out_package_name, std::ostream* out,
+                                  std::ostream* out_r_txt) {
   ClassDefinition r_class("R", ClassQualifier::kNone, true);
   std::unique_ptr<MethodDefinition> rewrite_method;
 
@@ -558,7 +588,7 @@
       std::unique_ptr<ClassDefinition> class_def = util::make_unique<ClassDefinition>(
           ToString(type->type), ClassQualifier::kStatic, force_creation_if_empty);
       if (!ProcessType(package_name_to_generate, *package, *type, class_def.get(),
-                       rewrite_method.get())) {
+                       rewrite_method.get(), out_r_txt)) {
         return false;
       }
 
@@ -567,7 +597,7 @@
         const ResourceTableType* priv_type = package->FindType(ResourceType::kAttrPrivate);
         if (priv_type) {
           if (!ProcessType(package_name_to_generate, *package, *priv_type, class_def.get(),
-                           rewrite_method.get())) {
+                           rewrite_method.get(), out_r_txt)) {
             return false;
           }
         }
@@ -597,6 +627,16 @@
   }
 
   out->flush();
+
+  if (out_r_txt != nullptr) {
+    out_r_txt->flush();
+
+    if (!*out_r_txt) {
+      error_ = android::base::SystemErrorCodeToString(errno);
+      return false;
+    }
+  }
+
   return true;
 }
 
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 4510430..18746ff 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -59,7 +59,7 @@
   std::vector<std::string> javadoc_annotations;
 };
 
-// Generates the R.java file for a resource table.
+// Generates the R.java file for a resource table and optionally an R.txt file.
 class JavaClassGenerator {
  public:
   JavaClassGenerator(IAaptContext* context, ResourceTable* table,
@@ -69,10 +69,12 @@
   // All symbols technically belong to a single package, but linked libraries will
   // have their names mangled, denoting that they came from a different package.
   // We need to generate these symbols in a separate file. Returns true on success.
-  bool Generate(const android::StringPiece& package_name_to_generate, std::ostream* out);
+  bool Generate(const android::StringPiece& package_name_to_generate, std::ostream* out,
+                std::ostream* out_r_txt = nullptr);
 
   bool Generate(const android::StringPiece& package_name_to_generate,
-                const android::StringPiece& output_package_name, std::ostream* out);
+                const android::StringPiece& output_package_name, std::ostream* out,
+                std::ostream* out_r_txt = nullptr);
 
   const std::string& getError() const;
 
@@ -88,13 +90,14 @@
 
   bool ProcessType(const android::StringPiece& package_name_to_generate,
                    const ResourceTablePackage& package, const ResourceTableType& type,
-                   ClassDefinition* out_type_class_def, MethodDefinition* out_rewrite_method_def);
+                   ClassDefinition* out_type_class_def, MethodDefinition* out_rewrite_method_def,
+                   std::ostream* out_r_txt);
 
   // Writes a resource to the R.java file, optionally writing out a rewrite rule for its package
   // ID if `out_rewrite_method` is not nullptr.
   void ProcessResource(const ResourceNameRef& name, const ResourceId& id,
                        const ResourceEntry& entry, ClassDefinition* out_class_def,
-                       MethodDefinition* out_rewrite_method);
+                       MethodDefinition* out_rewrite_method, std::ostream* out_r_txt);
 
   // Writes a styleable resource to the R.java file, optionally writing out a rewrite rule for
   // its package ID if `out_rewrite_method` is not nullptr.
@@ -102,7 +105,8 @@
   void ProcessStyleable(const ResourceNameRef& name, const ResourceId& id,
                         const Styleable& styleable,
                         const android::StringPiece& package_name_to_generate,
-                        ClassDefinition* out_class_def, MethodDefinition* out_rewrite_method);
+                        ClassDefinition* out_class_def, MethodDefinition* out_rewrite_method,
+                        std::ostream* out_r_txt);
 
   IAaptContext* context_;
   ResourceTable* table_;
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 4a278f63..6055190 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -224,7 +224,8 @@
 
   XML_ParserFree(parser);
   if (stack.root) {
-    return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, std::move(stack.root));
+    return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{},
+                                          std::move(stack.root));
   }
   return {};
 }
@@ -357,7 +358,7 @@
       }
     }
   }
-  return util::make_unique<XmlResource>(ResourceFile{}, std::move(root), std::move(string_pool));
+  return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root));
 }
 
 std::unique_ptr<Node> Namespace::Clone() {
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index f1d0953..6950c30 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -128,8 +128,13 @@
 class XmlResource {
  public:
   ResourceFile file;
-  std::unique_ptr<xml::Node> root;
+
+  // StringPool must come before the xml::Node. Destructors are called in reverse order, and
+  // the xml::Node may have StringPool references that need to be destroyed before the StringPool
+  // is destroyed.
   StringPool string_pool;
+
+  std::unique_ptr<xml::Node> root;
 };
 
 /**
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index 78b6f71..d8e049a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -411,6 +411,14 @@
         sManager.removeJavaReferenceFor(builderPtr);
     }
 
+    /**
+     * @see FontFamily#allowUnsupportedFont
+     */
+    @LayoutlibDelegate
+    /*package*/ static void nAllowUnsupportedFont(long builderPtr) {
+        // Do nothing here as this is used for Minikin fonts
+    }
+
     // ---- private helper methods ----
 
     private void init() {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index c7818a3..fa311d0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -90,9 +90,12 @@
         assert variant != FontVariant.NONE;
 
         // Calculate the required weight based on style and weight of this typeface.
-        int weight = mWeight + ((mStyle & Font.BOLD) == 0 ? 0 : FontFamily_Delegate.BOLD_FONT_WEIGHT_DELTA);
-        if (weight > 900) {
-            weight = 900;
+        int weight = mWeight + 50 +
+                ((mStyle & Font.BOLD) == 0 ? 0 : FontFamily_Delegate.BOLD_FONT_WEIGHT_DELTA);
+        if (weight > 1000) {
+            weight = 1000;
+        } else if (weight < 100) {
+            weight = 100;
         }
         final boolean isItalic = (mStyle & Font.ITALIC) != 0;
         List<Font> fonts = new ArrayList<Font>(mFontFamilies.length);
@@ -163,6 +166,22 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static long nativeCreateFromTypefaceWithExactStyle(long native_instance,
+            int weight, boolean italic) {
+        Typeface_Delegate delegate = sManager.getDelegate(native_instance);
+        if (delegate == null) {
+            delegate = sManager.getDelegate(sDefaultTypeface);
+        }
+        if (delegate == null) {
+            return 0;
+        }
+
+        int style = weight >= 600 ? (italic ? Typeface.BOLD_ITALIC : Typeface.BOLD) :
+                (italic ? Typeface.ITALIC : Typeface.NORMAL);
+        return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style, weight));
+    }
+
+    @LayoutlibDelegate
     /*package*/ static synchronized long nativeCreateFromTypefaceWithVariation(long native_instance,
             List<FontVariationAxis> axes) {
         long newInstance = nativeCreateFromTypeface(native_instance, 0);
@@ -195,12 +214,21 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static synchronized long nativeCreateFromArray(long[] familyArray) {
+    /*package*/ static synchronized long nativeCreateFromArray(long[] familyArray, int weight,
+            int italic) {
         FontFamily_Delegate[] fontFamilies = new FontFamily_Delegate[familyArray.length];
         for (int i = 0; i < familyArray.length; i++) {
             fontFamilies[i] = FontFamily_Delegate.getDelegate(familyArray[i]);
         }
-        Typeface_Delegate delegate = new Typeface_Delegate(fontFamilies, Typeface.NORMAL);
+        if (weight == Typeface.RESOLVE_BY_FONT_TABLE) {
+            weight = 400;
+        }
+        if (italic == Typeface.RESOLVE_BY_FONT_TABLE) {
+            italic = 0;
+        }
+        int style = weight >= 600 ? (italic == 1 ? Typeface.BOLD_ITALIC : Typeface.BOLD) :
+                (italic == 1 ? Typeface.ITALIC : Typeface.NORMAL);
+        Typeface_Delegate delegate = new Typeface_Delegate(fontFamilies, style, weight);
         return sManager.addNewDelegate(delegate);
     }
 
@@ -225,6 +253,15 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static int nativeGetBaseWeight(long native_instance) {
+        Typeface_Delegate delegate = sManager.getDelegate(native_instance);
+        if (delegate == null) {
+            return 0;
+        }
+        return delegate.mWeight;
+    }
+
+    @LayoutlibDelegate
     /*package*/ static File getSystemFontConfigLocation() {
         return new File(getFontLocation());
     }
@@ -244,10 +281,6 @@
 
     // ---- Private delegate/helper methods ----
 
-    private Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style) {
-        this(fontFamilies, style, FontFamily_Delegate.DEFAULT_FONT_WEIGHT);
-    }
-
     public Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style, int weight) {
         mFontFamilies = fontFamilies;
         mStyle = style;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 328fc0a..1e77ac1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1865,13 +1865,6 @@
     }
 
     @Override
-    public ComponentName startServiceInForeground(Intent service,
-            int id, Notification notification) {
-        // pass
-        return null;
-    }
-
-    @Override
     public boolean stopService(Intent arg0) {
         // pass
         return false;
@@ -1884,13 +1877,6 @@
     }
 
     @Override
-    public ComponentName startServiceInForegroundAsUser(Intent service,
-            int id, Notification notification, UserHandle user) {
-        // pass
-        return null;
-    }
-
-    @Override
     public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
         // pass
         return false;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 5a239e1..ad26bc8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -923,4 +923,9 @@
     public ComponentName getInstantAppResolverSettingsComponent() {
         return null;
     }
+
+    @Override
+    public ComponentName getInstantAppInstallerComponent() {
+        return null;
+    }
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 1852feb..229aa97 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -125,6 +125,10 @@
 
     void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
 
+    boolean startSoftAp(in WifiConfiguration wifiConfig);
+
+    boolean stopSoftAp();
+
     int getWifiApEnabledState();
 
     WifiConfiguration getWifiApConfiguration();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7268ee5..ed54c3b 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
@@ -1731,6 +1732,39 @@
     }
 
     /**
+     * Start SoftAp mode with the specified configuration.
+     * Note that starting in access point mode disables station
+     * mode operation
+     * @param wifiConfig SSID, security and channel details as
+     *        part of WifiConfiguration
+     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     *
+     * @hide
+     */
+    public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {
+        try {
+            return mService.startSoftAp(wifiConfig);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Stop SoftAp mode.
+     * Note that stopping softap mode will restore the previous wifi mode.
+     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     *
+     * @hide
+     */
+    public boolean stopSoftAp() {
+        try {
+            return mService.stopSoftAp();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Gets the Wi-Fi enabled state.
      * @return One of {@link #WIFI_AP_STATE_DISABLED},
      *         {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index 31f01bd..d35bc0d 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.net.NetworkSpecifier;
 import android.net.wifi.RttManager;
 import android.util.Log;
 
@@ -253,8 +254,8 @@
     }
 
     /**
-     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
-     * unencrypted WiFi Aware connection (link) to the specified peer. The
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+     * an unencrypted WiFi Aware connection (link) to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
@@ -279,13 +280,13 @@
      *                   request from only that peer. A RESPONDER may specify a {@code null} -
      *                   indicating that it will accept connection requests from any device.
      *
-     * @return A string to be used to construct
-     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * @return A {@link NetworkSpecifier} to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
      * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
      */
-    public String createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
+    public NetworkSpecifier createNetworkSpecifierOpen(@Nullable PeerHandle peerHandle) {
         if (mTerminated) {
             Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session");
             return null;
@@ -305,8 +306,8 @@
     }
 
     /**
-     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
-     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+     * an encrypted WiFi Aware connection (link) to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
@@ -332,14 +333,14 @@
      *                   {@link #createNetworkSpecifierOpen(PeerHandle)} API to
      *                   specify an open (unencrypted) link.
      *
-     * @return A string to be used to construct
-     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * @return A {@link NetworkSpecifier} to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
      * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
      */
-    public String createNetworkSpecifierPassphrase(@Nullable PeerHandle peerHandle,
-            @NonNull String passphrase) {
+    public NetworkSpecifier createNetworkSpecifierPassphrase(
+            @Nullable PeerHandle peerHandle, @NonNull String passphrase) {
         if (passphrase == null || passphrase.length() == 0) {
             throw new IllegalArgumentException("Passphrase must not be null or empty");
         }
@@ -364,8 +365,8 @@
     }
 
     /**
-     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
-     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+     * an encrypted WiFi Aware connection (link) to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
@@ -392,8 +393,8 @@
      *            Passphrase or {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an
      *            open (unencrypted) link.
      *
-     * @return A string to be used to construct
-     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * @return A {@link NetworkSpecifier} to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
      * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
@@ -401,7 +402,7 @@
      * @hide
      */
     @SystemApi
-    public String createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
+    public NetworkSpecifier createNetworkSpecifierPmk(@Nullable PeerHandle peerHandle,
             @NonNull byte[] pmk) {
         if (pmk == null || pmk.length == 0) {
             throw new IllegalArgumentException("PMK must not be null or empty");
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 4d3957a..3fcbd4b 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
 import android.net.wifi.RttManager;
 import android.os.Binder;
 import android.os.Bundle;
@@ -31,7 +32,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
-import android.util.Base64;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -39,9 +39,6 @@
 
 import libcore.util.HexEncoding;
 
-import org.json.JSONException;
-import org.json.JSONObject;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
@@ -129,65 +126,6 @@
     private static final boolean VDBG = false; // STOPSHIP if true
 
     /**
-     * Keys used to generate a Network Specifier for the Aware network request. The network
-     * specifier is formatted as a JSON string.
-     */
-
-    /**
-     * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
-     * @hide
-     */
-    public static final int NETWORK_SPECIFIER_TYPE_IB = 0;
-
-    /**
-     * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
-     * [only permitted for RESPONDER]
-     * @hide
-     */
-    public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;
-
-    /**
-     * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
-     * @hide
-     */
-    public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;
-
-    /**
-     * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
-     * [only permitted for RESPONDER]
-     * @hide
-     */
-    public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3;
-
-
-    /** @hide */
-    public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;
-
-    /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_TYPE = "type";
-
-    /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_ROLE = "role";
-
-    /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_CLIENT_ID = "client_id";
-
-    /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_SESSION_ID = "session_id";
-
-    /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_PEER_ID = "peer_id";
-
-    /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_PEER_MAC = "peer_mac";
-
-    /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_PMK = "pmk";
-
-    /** @hide */
-    public static final String NETWORK_SPECIFIER_KEY_PASSPHRASE = "passphrase";
-
-    /**
      * Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed.
      * Use the {@link #isAvailable()} to query the current status.
      * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
@@ -483,7 +421,7 @@
     }
 
     /** @hide */
-    public String createNetworkSpecifier(int clientId, int role, int sessionId,
+    public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
             PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
         if (VDBG) {
             Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
@@ -492,9 +430,6 @@
                     + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
         }
 
-        int type = (peerHandle == null) ? NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
-                : NETWORK_SPECIFIER_TYPE_IB;
-
         if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
                 && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
             throw new IllegalArgumentException(
@@ -509,35 +444,20 @@
             }
         }
 
-        JSONObject json;
-        try {
-            json = new JSONObject();
-            json.put(NETWORK_SPECIFIER_KEY_TYPE, type);
-            json.put(NETWORK_SPECIFIER_KEY_ROLE, role);
-            json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
-            json.put(NETWORK_SPECIFIER_KEY_SESSION_ID, sessionId);
-            if (peerHandle != null) {
-                json.put(NETWORK_SPECIFIER_KEY_PEER_ID, peerHandle.peerId);
-            }
-            if (pmk == null) {
-                pmk = new byte[0];
-            }
-            json.put(NETWORK_SPECIFIER_KEY_PMK,
-                    Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
-            if (passphrase == null) {
-                passphrase = new String();
-            }
-            json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
-
-        } catch (JSONException e) {
-            return "";
-        }
-
-        return json.toString();
+        return new WifiAwareNetworkSpecifier(
+                (peerHandle == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
+                        : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB,
+                role,
+                clientId,
+                sessionId,
+                peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID
+                null, // peerMac (not used in this method)
+                pmk,
+                passphrase);
     }
 
     /** @hide */
-    public String createNetworkSpecifier(int clientId, @DataPathRole int role,
+    public NetworkSpecifier createNetworkSpecifier(int clientId, @DataPathRole int role,
             @Nullable byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
         if (VDBG) {
             Log.v(TAG, "createNetworkSpecifier: role=" + role
@@ -545,9 +465,6 @@
                     + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
         }
 
-        int type = (peer == null) ?
-                NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER : NETWORK_SPECIFIER_TYPE_OOB;
-
         if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
                 && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
             throw new IllegalArgumentException(
@@ -564,29 +481,16 @@
             throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
         }
 
-        JSONObject json;
-        try {
-            json = new JSONObject();
-            json.put(NETWORK_SPECIFIER_KEY_TYPE, type);
-            json.put(NETWORK_SPECIFIER_KEY_ROLE, role);
-            json.put(NETWORK_SPECIFIER_KEY_CLIENT_ID, clientId);
-            if (peer != null) {
-                json.put(NETWORK_SPECIFIER_KEY_PEER_MAC, new String(HexEncoding.encode(peer)));
-            }
-            if (pmk == null) {
-                pmk = new byte[0];
-            }
-            json.put(NETWORK_SPECIFIER_KEY_PMK,
-                    Base64.encodeToString(pmk, 0, pmk.length, Base64.DEFAULT));
-            if (passphrase == null) {
-                passphrase = new String();
-            }
-            json.put(NETWORK_SPECIFIER_KEY_PASSPHRASE, passphrase);
-        } catch (JSONException e) {
-            return "";
-        }
-
-        return json.toString();
+        return new WifiAwareNetworkSpecifier(
+                (peer == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER
+                        : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB,
+                role,
+                clientId,
+                0, // 0 is an invalid session ID
+                0, // 0 is an invalid peer ID
+                peer,
+                pmk,
+                passphrase);
     }
 
     private static class WifiAwareEventCallbackProxy extends IWifiAwareEventCallback.Stub {
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
new file mode 100644
index 0000000..5993480
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.aware;
+
+import android.net.NetworkSpecifier;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Network specifier object used to request a Wi-Fi Aware network. Apps do not create these objects
+ * directly but obtain them using
+ * {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} or
+ * {@link DiscoverySession#createNetworkSpecifierOpen(PeerHandle)} or their secure (Passphrase)
+ * versions.
+ *
+ * @hide
+ */
+public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+    /**
+     * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional
+     * @hide
+     */
+    public static final int NETWORK_SPECIFIER_TYPE_IB = 0;
+
+    /**
+     * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional
+     * [only permitted for RESPONDER]
+     * @hide
+     */
+    public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1;
+
+    /**
+     * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional
+     * @hide
+     */
+    public static final int NETWORK_SPECIFIER_TYPE_OOB = 2;
+
+    /**
+     * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional
+     * [only permitted for RESPONDER]
+     * @hide
+     */
+    public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3;
+
+    /** @hide */
+    public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER;
+
+    /**
+     * One of the NETWORK_SPECIFIER_TYPE_* constants. The type of the network specifier object.
+     * @hide
+     */
+    public final int type;
+
+    /**
+     * The role of the device: WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR or
+     * WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER.
+     * @hide
+     */
+    public final int role;
+
+    /**
+     * The client ID of the device.
+     * @hide
+     */
+    public final int clientId;
+
+    /**
+     * The session ID in which context to request a data-path. Only relevant for IB requests.
+     * @hide
+     */
+    public final int sessionId;
+
+    /**
+     * The peer ID of the device which the data-path should be connected to. Only relevant for
+     * IB requests (i.e. not IB_ANY_PEER or OOB*).
+     * @hide
+     */
+    public final int peerId;
+
+    /**
+     * The peer MAC address of the device which the data-path should be connected to. Only relevant
+     * for OB requests (i.e. not OOB_ANY_PEER or IB*).
+     * @hide
+     */
+    public final byte[] peerMac;
+
+    /**
+     * The PMK of the requested data-path. Can be null. Only one or none of pmk or passphrase should
+     * be specified.
+     * @hide
+     */
+    public final byte[] pmk;
+
+    /**
+     * The Passphrase of the requested data-path. Can be null. Only one or none of the pmk or
+     * passphrase should be specified.
+     * @hide
+     */
+    public final String passphrase;
+
+    /** @hide */
+    public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId,
+            byte[] peerMac, byte[] pmk, String passphrase) {
+        this.type = type;
+        this.role = role;
+        this.clientId = clientId;
+        this.sessionId = sessionId;
+        this.peerId = peerId;
+        this.peerMac = peerMac;
+        this.pmk = pmk;
+        this.passphrase = passphrase;
+    }
+
+    public static final Creator<WifiAwareNetworkSpecifier> CREATOR =
+            new Creator<WifiAwareNetworkSpecifier>() {
+                @Override
+                public WifiAwareNetworkSpecifier createFromParcel(Parcel in) {
+                    return new WifiAwareNetworkSpecifier(
+                        in.readInt(), // type
+                        in.readInt(), // role
+                        in.readInt(), // clientId
+                        in.readInt(), // sessionId
+                        in.readInt(), // peerId
+                        in.createByteArray(), // peerMac
+                        in.createByteArray(), // pmk
+                        in.readString()); // passphrase
+                }
+
+                @Override
+                public WifiAwareNetworkSpecifier[] newArray(int size) {
+                    return new WifiAwareNetworkSpecifier[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(type);
+        dest.writeInt(role);
+        dest.writeInt(clientId);
+        dest.writeInt(sessionId);
+        dest.writeInt(peerId);
+        dest.writeByteArray(peerMac);
+        dest.writeByteArray(pmk);
+        dest.writeString(passphrase);
+    }
+
+    /** @hide */
+    @Override
+    public boolean satisfiedBy(NetworkSpecifier other) {
+        // MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier.
+        return equals(other);
+    }
+
+    /** @hide */
+    @Override
+    public int hashCode() {
+        int result = 17;
+
+        result = 31 * result + type;
+        result = 31 * result + role;
+        result = 31 * result + clientId;
+        result = 31 * result + sessionId;
+        result = 31 * result + peerId;
+        result = 31 * result + Arrays.hashCode(peerMac);
+        result = 31 * result + Arrays.hashCode(pmk);
+        result = 31 * result + Objects.hashCode(passphrase);
+
+        return result;
+    }
+
+    /** @hide */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (!(obj instanceof WifiAwareNetworkSpecifier)) {
+            return false;
+        }
+
+        WifiAwareNetworkSpecifier lhs = (WifiAwareNetworkSpecifier) obj;
+
+        return type == lhs.type
+                && role == lhs.role
+                && clientId == lhs.clientId
+                && sessionId == lhs.sessionId
+                && peerId == lhs.peerId
+                && Arrays.equals(peerMac, lhs.peerMac)
+                && Arrays.equals(pmk, lhs.pmk)
+                && Objects.equals(passphrase, lhs.passphrase);
+    }
+
+    /** @hide */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("WifiAwareNetworkSpecifier [");
+        sb.append("type=").append(type)
+                .append(", role=").append(role)
+                .append(", clientId=").append(clientId)
+                .append(", sessionId=").append(sessionId)
+                .append(", peerId=").append(peerId)
+                // masking potential PII (although low impact information)
+                .append(", peerMac=").append((peerMac == null) ? "<null>" : "<non-null>")
+                // masking PII
+                .append(", pmk=").append((pmk == null) ? "<null>" : "<non-null>")
+                // masking PII
+                .append(", passphrase=").append((passphrase == null) ? "<null>" : "<non-null>")
+                .append("]");
+        return sb.toString();
+    }
+}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareSession.java b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
index 443db0c..8e25805 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareSession.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareSession.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.net.NetworkSpecifier;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.Looper;
@@ -187,8 +188,8 @@
     }
 
     /**
-     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
-     * unencrypted WiFi Aware connection (link) to the specified peer. The
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+     * an unencrypted WiFi Aware connection (link) to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
@@ -208,29 +209,29 @@
      *              peer. A RESPONDER may specify a {@code null} - indicating that it will accept
      *              connection requests from any device.
      *
-     * @return A string to be used to construct
-     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * @return A {@link NetworkSpecifier} to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
      * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
      */
-    public String createNetworkSpecifierOpen(@WifiAwareManager.DataPathRole int role,
-            @Nullable byte[] peer) {
+    public NetworkSpecifier createNetworkSpecifierOpen(
+            @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer) {
         WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
             Log.e(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
-            return "";
+            return null;
         }
         if (mTerminated) {
             Log.e(TAG, "createNetworkSpecifierOpen: called after termination");
-            return "";
+            return null;
         }
         return mgr.createNetworkSpecifier(mClientId, role, peer, null, null);
     }
 
     /**
-     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
-     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+     * an encrypted WiFi Aware connection (link) to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
@@ -250,22 +251,23 @@
      *                   the passphrase. Use {@link #createNetworkSpecifierOpen(int, byte[])} to
      *                   specify an open (unencrypted) link.
      *
-     * @return A string to be used to construct
-     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * @return A {@link NetworkSpecifier} to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
      * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
      */
-    public String createNetworkSpecifierPassphrase(@WifiAwareManager.DataPathRole int role,
-            @Nullable byte[] peer, @NonNull String passphrase) {
+    public NetworkSpecifier createNetworkSpecifierPassphrase(
+            @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer,
+            @NonNull String passphrase) {
         WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
             Log.e(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager");
-            return "";
+            return null;
         }
         if (mTerminated) {
             Log.e(TAG, "createNetworkSpecifierPassphrase: called after termination");
-            return "";
+            return null;
         }
         if (passphrase == null || passphrase.length() == 0) {
             throw new IllegalArgumentException("Passphrase must not be null or empty");
@@ -274,8 +276,8 @@
     }
 
     /**
-     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} for an
-     * encrypted WiFi Aware connection (link) to the specified peer. The
+     * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
+     * an encrypted WiFi Aware connection (link) to the specified peer. The
      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
      * <p>
@@ -297,8 +299,8 @@
      *            Passphrase or {@link #createNetworkSpecifierOpen(int, byte[])} to specify an
      *            open (unencrypted) link.
      *
-     * @return A string to be used to construct
-     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(String)} to pass to
+     * @return A {@link NetworkSpecifier} to be used to construct
+     * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
      * android.net.ConnectivityManager.NetworkCallback)}
      * [or other varieties of that API].
@@ -306,16 +308,16 @@
      * @hide
      */
     @SystemApi
-    public String createNetworkSpecifierPmk(@WifiAwareManager.DataPathRole int role,
-            @Nullable byte[] peer, @NonNull byte[] pmk) {
+    public NetworkSpecifier createNetworkSpecifierPmk(
+            @WifiAwareManager.DataPathRole int role, @Nullable byte[] peer, @NonNull byte[] pmk) {
         WifiAwareManager mgr = mMgr.get();
         if (mgr == null) {
             Log.e(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
-            return "";
+            return null;
         }
         if (mTerminated) {
             Log.e(TAG, "createNetworkSpecifierPmk: called after termination");
-            return "";
+            return null;
         }
         if (pmk == null || pmk.length == 0) {
             throw new IllegalArgumentException("PMK must not be null or empty");
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index 830db22..72a6a7a 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -34,11 +34,9 @@
 import android.os.Parcel;
 import android.os.test.TestLooper;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Base64;
 
 import libcore.util.HexEncoding;
 
-import org.json.JSONObject;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -959,8 +957,6 @@
         final ConfigRequest configRequest = new ConfigRequest.Builder().build();
         final PublishConfig publishConfig = new PublishConfig.Builder().build();
 
-        String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
-
         ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
                 WifiAwareSession.class);
         ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
@@ -991,51 +987,37 @@
         inOrder.verify(mockSessionCallback).onPublishStarted(publishSession.capture());
 
         // (3) request an open (unencrypted) network specifier from the session
-        String networkSpecifier = publishSession.getValue().createNetworkSpecifierOpen(peerHandle);
+        WifiAwareNetworkSpecifier ns =
+                (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierOpen(
+                        peerHandle);
 
         // validate format
-        JSONObject jsonObject = new JSONObject(networkSpecifier);
-        collector.checkThat("role", role,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
-        collector.checkThat("client_id", clientId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
-        collector.checkThat("session_id", sessionId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
-        collector.checkThat("peer_id", peerHandle.peerId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
+        collector.checkThat("role", role, equalTo(ns.role));
+        collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+        collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+        collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
 
         // (4) request an encrypted (PMK) network specifier from the session
-        networkSpecifier = publishSession.getValue().createNetworkSpecifierPmk(peerHandle, pmk);
+        ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPmk(
+                peerHandle, pmk);
 
         // validate format
-        jsonObject = new JSONObject(networkSpecifier);
-        collector.checkThat("role", role,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
-        collector.checkThat("client_id", clientId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
-        collector.checkThat("session_id", sessionId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
-        collector.checkThat("peer_id", peerHandle.peerId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
-        collector.checkThat("pmk", pmkB64 ,
-                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
+        collector.checkThat("role", role, equalTo(ns.role));
+        collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+        collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+        collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
+        collector.checkThat("pmk", pmk , equalTo(ns.pmk));
 
         // (5) request an encrypted (Passphrase) network specifier from the session
-        networkSpecifier = publishSession.getValue().createNetworkSpecifierPassphrase(peerHandle,
-                passphrase);
+        ns = (WifiAwareNetworkSpecifier) publishSession.getValue().createNetworkSpecifierPassphrase(
+                peerHandle, passphrase);
 
         // validate format
-        jsonObject = new JSONObject(networkSpecifier);
-        collector.checkThat("role", role,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
-        collector.checkThat("client_id", clientId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
-        collector.checkThat("session_id", sessionId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID)));
-        collector.checkThat("peer_id", peerHandle.peerId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID)));
-        collector.checkThat("passphrase", passphrase,
-                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
+        collector.checkThat("role", role, equalTo(ns.role));
+        collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+        collector.checkThat("session_id", sessionId, equalTo(ns.sessionId));
+        collector.checkThat("peer_id", peerHandle.peerId, equalTo(ns.peerId));
+        collector.checkThat("passphrase", passphrase, equalTo(ns.passphrase));
 
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
                 mockPublishSession, mockRttListener);
@@ -1054,8 +1036,6 @@
         final byte[] pmk = "Some arbitrary pmk data".getBytes();
         final String passphrase = "A really bad password";
 
-        String pmkB64 = Base64.encodeToString(pmk, Base64.DEFAULT);
-
         ArgumentCaptor<WifiAwareSession> sessionCaptor = ArgumentCaptor.forClass(
                 WifiAwareSession.class);
         ArgumentCaptor<IWifiAwareEventCallback> clientProxyCallback = ArgumentCaptor
@@ -1074,47 +1054,32 @@
         WifiAwareSession session = sessionCaptor.getValue();
 
         // (2) request an open (unencrypted) direct network specifier
-        String networkSpecifier = session.createNetworkSpecifierOpen(role, someMac);
+        WifiAwareNetworkSpecifier ns =
+                (WifiAwareNetworkSpecifier) session.createNetworkSpecifierOpen(role, someMac);
 
         // validate format
-        JSONObject jsonObject = new JSONObject(networkSpecifier);
-        collector.checkThat("role", role,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
-        collector.checkThat("client_id", clientId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
-        collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
-                jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
-                false)));
+        collector.checkThat("role", role, equalTo(ns.role));
+        collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+        collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
 
         // (3) request an encrypted (PMK) direct network specifier
-        networkSpecifier = session.createNetworkSpecifierPmk(role, someMac, pmk);
+        ns = (WifiAwareNetworkSpecifier) session.createNetworkSpecifierPmk(role, someMac, pmk);
 
         // validate format
-        jsonObject = new JSONObject(networkSpecifier);
-        collector.checkThat("role", role,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
-        collector.checkThat("client_id", clientId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
-        collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
-                jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
-                false)));
-        collector.checkThat("pmk", pmkB64,
-                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PMK)));
+        collector.checkThat("role", role, equalTo(ns.role));
+        collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+        collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
+        collector.checkThat("pmk", pmk, equalTo(ns.pmk));
 
         // (4) request an encrypted (Passphrase) direct network specifier
-        networkSpecifier = session.createNetworkSpecifierPassphrase(role, someMac, passphrase);
+        ns = (WifiAwareNetworkSpecifier) session.createNetworkSpecifierPassphrase(role, someMac,
+                passphrase);
 
         // validate format
-        jsonObject = new JSONObject(networkSpecifier);
-        collector.checkThat("role", role,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE)));
-        collector.checkThat("client_id", clientId,
-                equalTo(jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID)));
-        collector.checkThat("peer_mac", someMac, equalTo(HexEncoding.decode(
-                jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(),
-                false)));
-        collector.checkThat("passphrase", passphrase,
-                equalTo(jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_PASSPHRASE)));
+        collector.checkThat("role", role, equalTo(ns.role));
+        collector.checkThat("client_id", clientId, equalTo(ns.clientId));
+        collector.checkThat("peer_mac", someMac, equalTo(ns.peerMac));
+        collector.checkThat("passphrase", passphrase, equalTo(ns.passphrase));
 
         verifyNoMoreInteractions(mockCallback, mockSessionCallback, mockAwareService,
                 mockPublishSession, mockRttListener);