Merge "Merge commit '12562abcd47de4aee3b0469cb04bf771c2072113' into manual_merge_12562abcd47d"
diff --git a/api/current.txt b/api/current.txt
index bca65ee..cd66ed6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -203,6 +203,8 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int __removed0 = 16844097; // 0x1010541
+    field public static final int __removed1 = 16844099; // 0x1010543
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -758,7 +760,6 @@
     field public static final int keyboardLayout = 16843691; // 0x10103ab
     field public static final int keyboardMode = 16843341; // 0x101024d
     field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
-    field public static final int keyboardNavigationSection = 16844097; // 0x1010541
     field public static final int keycode = 16842949; // 0x10100c5
     field public static final int killAfterRestore = 16843420; // 0x101029c
     field public static final int label = 16842753; // 0x1010001
@@ -908,7 +909,6 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
-    field public static final int nextSectionForward = 16844099; // 0x1010543
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -5583,6 +5583,18 @@
     field public static final int STYLE_SPINNER = 0; // 0x0
   }
 
+  public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
+    ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
+    method public int describeContents();
+    method public android.app.PendingIntent getUserAction();
+    method public java.lang.CharSequence getUserActionTitle();
+    method public java.lang.CharSequence getUserMessage();
+    method public void showAsDialog(android.app.Activity);
+    method public void showAsNotification(android.content.Context);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
+  }
+
   public final class RemoteAction implements android.os.Parcelable {
     ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
     method public android.app.RemoteAction clone();
@@ -30454,14 +30466,22 @@
   }
 
   public class StorageManager {
+    method public long getCacheQuotaBytes();
+    method public long getCacheSizeBytes();
+    method public long getExternalCacheQuotaBytes();
+    method public long getExternalCacheSizeBytes();
     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 boolean isCacheBehaviorAtomic(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);
     method public boolean isObbMounted(java.lang.String);
     method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
     method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException;
+    method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException;
+    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";
   }
@@ -37830,7 +37850,8 @@
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
-    field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
+    field public static final deprecated java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
+    field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY = "carrier_vvm_package_name_string_array";
     field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
     field public static final java.lang.String KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL = "carrier_wfc_supports_wifi_only_bool";
     field public static final java.lang.String KEY_CDMA_3WAYCALL_FLASH_DELAY_INT = "cdma_3waycall_flash_delay_int";
@@ -37922,9 +37943,13 @@
     field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
     field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
     field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL = "vvm_cellular_data_required_bool";
+    field public static final java.lang.String KEY_VVM_CLIENT_PREFIX_STRING = "vvm_client_prefix_string";
     field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
+    field public static final java.lang.String KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY = "vvm_disabled_capabilities_string_array";
+    field public static final java.lang.String KEY_VVM_LEGACY_MODE_ENABLED_BOOL = "vvm_legacy_mode_enabled_bool";
     field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
     field public static final java.lang.String KEY_VVM_PREFETCH_BOOL = "vvm_prefetch_bool";
+    field public static final java.lang.String KEY_VVM_SSL_ENABLED_BOOL = "vvm_ssl_enabled_bool";
     field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
@@ -42210,7 +42235,9 @@
     method public android.view.Display.Mode[] getSupportedModes();
     method public deprecated float[] getSupportedRefreshRates();
     method public deprecated int getWidth();
+    method public boolean isHdr();
     method public boolean isValid();
+    method public boolean isWideColorGamut();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
     field public static final int FLAG_PRESENTATION = 8; // 0x8
     field public static final int FLAG_PRIVATE = 4; // 0x4
@@ -42279,7 +42306,7 @@
     method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
     method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
     method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
-    method public android.view.View findNextKeyboardNavigationGroup(int, android.view.View, android.view.View, int);
+    method public android.view.View findNextKeyboardNavigationCluster(android.view.View, android.view.View, int);
     method public static android.view.FocusFinder getInstance();
   }
 
@@ -43577,7 +43604,7 @@
     method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
-    method public void addKeyboardNavigationGroups(int, java.util.Collection<android.view.View>, int);
+    method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
     method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
     method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
     method public void addTouchables(java.util.ArrayList<android.view.View>);
@@ -43741,7 +43768,6 @@
     method public int getNextFocusLeftId();
     method public int getNextFocusRightId();
     method public int getNextFocusUpId();
-    method public int getNextSectionForwardId();
     method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
     method public android.view.ViewOutlineProvider getOutlineProvider();
     method public int getOverScrollMode();
@@ -43847,7 +43873,6 @@
     method public boolean isInLayout();
     method public boolean isInTouchMode();
     method public final boolean isKeyboardNavigationCluster();
-    method public final boolean isKeyboardNavigationSection();
     method public boolean isLaidOut();
     method public boolean isLayoutDirectionResolved();
     method public boolean isLayoutRequested();
@@ -43870,7 +43895,7 @@
     method public boolean isVerticalFadingEdgeEnabled();
     method public boolean isVerticalScrollBarEnabled();
     method public void jumpDrawablesToCurrentState();
-    method public android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
+    method public android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public void layout(int, int, int, int);
     method public final void measure(int, int);
     method protected static int[] mergeDrawableStates(int[], int[]);
@@ -44020,7 +44045,6 @@
     method public void setImportantForAccessibility(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
-    method public void setKeyboardNavigationSection(boolean);
     method public void setLabelFor(int);
     method public void setLayerPaint(android.graphics.Paint);
     method public void setLayerType(int, android.graphics.Paint);
@@ -44038,7 +44062,6 @@
     method public void setNextFocusLeftId(int);
     method public void setNextFocusRightId(int);
     method public void setNextFocusUpId(int);
-    method public void setNextSectionForwardId(int);
     method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
     method public void setOnClickListener(android.view.View.OnClickListener);
     method public void setOnContextClickListener(android.view.View.OnContextClickListener);
@@ -44165,8 +44188,6 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
-    field public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1; // 0x1
-    field public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2; // 0x2
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
     field public static final int LAYER_TYPE_NONE = 0; // 0x0
     field public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
@@ -44685,7 +44706,7 @@
     method public abstract boolean isLayoutRequested();
     method public abstract boolean isTextAlignmentResolved();
     method public abstract boolean isTextDirectionResolved();
-    method public abstract android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
+    method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
     method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
     method public abstract boolean onNestedPreFling(android.view.View, float, float);
diff --git a/api/system-current.txt b/api/system-current.txt
index 53552fc..a3deab0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -312,6 +312,8 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int __removed0 = 16844097; // 0x1010541
+    field public static final int __removed1 = 16844099; // 0x1010543
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -867,7 +869,6 @@
     field public static final int keyboardLayout = 16843691; // 0x10103ab
     field public static final int keyboardMode = 16843341; // 0x101024d
     field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
-    field public static final int keyboardNavigationSection = 16844097; // 0x1010541
     field public static final int keycode = 16842949; // 0x10100c5
     field public static final int killAfterRestore = 16843420; // 0x101029c
     field public static final int label = 16842753; // 0x1010001
@@ -1017,7 +1018,6 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
-    field public static final int nextSectionForward = 16844099; // 0x1010543
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -5504,9 +5504,11 @@
     ctor public Notification.TvExtender();
     ctor public Notification.TvExtender(android.app.Notification);
     method public android.app.Notification.Builder extend(android.app.Notification.Builder);
+    method public java.lang.String getChannel();
     method public android.app.PendingIntent getContentIntent();
     method public android.app.PendingIntent getDeleteIntent();
     method public boolean isAvailableOnTv();
+    method public android.app.Notification.TvExtender setChannel(java.lang.String);
     method public android.app.Notification.TvExtender setContentIntent(android.app.PendingIntent);
     method public android.app.Notification.TvExtender setDeleteIntent(android.app.PendingIntent);
   }
@@ -5770,6 +5772,18 @@
     field public static final int STYLE_SPINNER = 0; // 0x0
   }
 
+  public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
+    ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
+    method public int describeContents();
+    method public android.app.PendingIntent getUserAction();
+    method public java.lang.CharSequence getUserActionTitle();
+    method public java.lang.CharSequence getUserMessage();
+    method public void showAsDialog(android.app.Activity);
+    method public void showAsNotification(android.content.Context);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
+  }
+
   public final class RemoteAction implements android.os.Parcelable {
     ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
     method public android.app.RemoteAction clone();
@@ -33206,14 +33220,22 @@
   }
 
   public class StorageManager {
+    method public long getCacheQuotaBytes();
+    method public long getCacheSizeBytes();
+    method public long getExternalCacheQuotaBytes();
+    method public long getExternalCacheSizeBytes();
     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 boolean isCacheBehaviorAtomic(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);
     method public boolean isObbMounted(java.lang.String);
     method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
     method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException;
+    method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException;
+    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";
   }
@@ -41040,7 +41062,8 @@
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
-    field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
+    field public static final deprecated java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
+    field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY = "carrier_vvm_package_name_string_array";
     field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
     field public static final java.lang.String KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL = "carrier_wfc_supports_wifi_only_bool";
     field public static final java.lang.String KEY_CDMA_3WAYCALL_FLASH_DELAY_INT = "cdma_3waycall_flash_delay_int";
@@ -41132,9 +41155,13 @@
     field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
     field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
     field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL = "vvm_cellular_data_required_bool";
+    field public static final java.lang.String KEY_VVM_CLIENT_PREFIX_STRING = "vvm_client_prefix_string";
     field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
+    field public static final java.lang.String KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY = "vvm_disabled_capabilities_string_array";
+    field public static final java.lang.String KEY_VVM_LEGACY_MODE_ENABLED_BOOL = "vvm_legacy_mode_enabled_bool";
     field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
     field public static final java.lang.String KEY_VVM_PREFETCH_BOOL = "vvm_prefetch_bool";
+    field public static final java.lang.String KEY_VVM_SSL_ENABLED_BOOL = "vvm_ssl_enabled_bool";
     field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
@@ -45512,7 +45539,9 @@
     method public android.view.Display.Mode[] getSupportedModes();
     method public deprecated float[] getSupportedRefreshRates();
     method public deprecated int getWidth();
+    method public boolean isHdr();
     method public boolean isValid();
+    method public boolean isWideColorGamut();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
     field public static final int FLAG_PRESENTATION = 8; // 0x8
     field public static final int FLAG_PRIVATE = 4; // 0x4
@@ -45581,7 +45610,7 @@
     method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
     method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
     method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
-    method public android.view.View findNextKeyboardNavigationGroup(int, android.view.View, android.view.View, int);
+    method public android.view.View findNextKeyboardNavigationCluster(android.view.View, android.view.View, int);
     method public static android.view.FocusFinder getInstance();
   }
 
@@ -46879,7 +46908,7 @@
     method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
-    method public void addKeyboardNavigationGroups(int, java.util.Collection<android.view.View>, int);
+    method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
     method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
     method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
     method public void addTouchables(java.util.ArrayList<android.view.View>);
@@ -47043,7 +47072,6 @@
     method public int getNextFocusLeftId();
     method public int getNextFocusRightId();
     method public int getNextFocusUpId();
-    method public int getNextSectionForwardId();
     method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
     method public android.view.ViewOutlineProvider getOutlineProvider();
     method public int getOverScrollMode();
@@ -47149,7 +47177,6 @@
     method public boolean isInLayout();
     method public boolean isInTouchMode();
     method public final boolean isKeyboardNavigationCluster();
-    method public final boolean isKeyboardNavigationSection();
     method public boolean isLaidOut();
     method public boolean isLayoutDirectionResolved();
     method public boolean isLayoutRequested();
@@ -47172,7 +47199,7 @@
     method public boolean isVerticalFadingEdgeEnabled();
     method public boolean isVerticalScrollBarEnabled();
     method public void jumpDrawablesToCurrentState();
-    method public android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
+    method public android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public void layout(int, int, int, int);
     method public final void measure(int, int);
     method protected static int[] mergeDrawableStates(int[], int[]);
@@ -47322,7 +47349,6 @@
     method public void setImportantForAccessibility(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
-    method public void setKeyboardNavigationSection(boolean);
     method public void setLabelFor(int);
     method public void setLayerPaint(android.graphics.Paint);
     method public void setLayerType(int, android.graphics.Paint);
@@ -47340,7 +47366,6 @@
     method public void setNextFocusLeftId(int);
     method public void setNextFocusRightId(int);
     method public void setNextFocusUpId(int);
-    method public void setNextSectionForwardId(int);
     method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
     method public void setOnClickListener(android.view.View.OnClickListener);
     method public void setOnContextClickListener(android.view.View.OnContextClickListener);
@@ -47467,8 +47492,6 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
-    field public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1; // 0x1
-    field public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2; // 0x2
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
     field public static final int LAYER_TYPE_NONE = 0; // 0x0
     field public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
@@ -47987,7 +48010,7 @@
     method public abstract boolean isLayoutRequested();
     method public abstract boolean isTextAlignmentResolved();
     method public abstract boolean isTextDirectionResolved();
-    method public abstract android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
+    method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
     method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
     method public abstract boolean onNestedPreFling(android.view.View, float, float);
diff --git a/api/test-current.txt b/api/test-current.txt
index d18af4c..f07f3b4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -203,6 +203,8 @@
 
   public static final class R.attr {
     ctor public R.attr();
+    field public static final int __removed0 = 16844097; // 0x1010541
+    field public static final int __removed1 = 16844099; // 0x1010543
     field public static final int absListViewStyle = 16842858; // 0x101006a
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -758,7 +760,6 @@
     field public static final int keyboardLayout = 16843691; // 0x10103ab
     field public static final int keyboardMode = 16843341; // 0x101024d
     field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
-    field public static final int keyboardNavigationSection = 16844097; // 0x1010541
     field public static final int keycode = 16842949; // 0x10100c5
     field public static final int killAfterRestore = 16843420; // 0x101029c
     field public static final int label = 16842753; // 0x1010001
@@ -908,7 +909,6 @@
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
-    field public static final int nextSectionForward = 16844099; // 0x1010543
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
@@ -5594,6 +5594,18 @@
     field public static final int STYLE_SPINNER = 0; // 0x0
   }
 
+  public final class RecoverableSecurityException extends java.lang.SecurityException implements android.os.Parcelable {
+    ctor public RecoverableSecurityException(java.lang.Throwable, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
+    method public int describeContents();
+    method public android.app.PendingIntent getUserAction();
+    method public java.lang.CharSequence getUserActionTitle();
+    method public java.lang.CharSequence getUserMessage();
+    method public void showAsDialog(android.app.Activity);
+    method public void showAsNotification(android.content.Context);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.RecoverableSecurityException> CREATOR;
+  }
+
   public final class RemoteAction implements android.os.Parcelable {
     ctor public RemoteAction(android.graphics.drawable.Icon, java.lang.CharSequence, java.lang.CharSequence, android.app.RemoteAction.OnActionListener);
     method public android.app.RemoteAction clone();
@@ -30567,14 +30579,22 @@
   }
 
   public class StorageManager {
+    method public long getCacheQuotaBytes();
+    method public long getCacheSizeBytes();
+    method public long getExternalCacheQuotaBytes();
+    method public long getExternalCacheSizeBytes();
     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 boolean isCacheBehaviorAtomic(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);
     method public boolean isObbMounted(java.lang.String);
     method public boolean mountObb(java.lang.String, java.lang.String, android.os.storage.OnObbStateChangeListener);
     method public android.os.ParcelFileDescriptor openProxyFileDescriptor(int, android.os.ProxyFileDescriptorCallback) throws java.io.IOException;
+    method public void setCacheBehaviorAtomic(java.io.File, boolean) throws java.io.IOException;
+    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";
   }
@@ -37951,7 +37971,8 @@
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
     field public static final java.lang.String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
-    field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
+    field public static final deprecated java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
+    field public static final java.lang.String KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY = "carrier_vvm_package_name_string_array";
     field public static final java.lang.String KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL = "carrier_wfc_ims_available_bool";
     field public static final java.lang.String KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL = "carrier_wfc_supports_wifi_only_bool";
     field public static final java.lang.String KEY_CDMA_3WAYCALL_FLASH_DELAY_INT = "cdma_3waycall_flash_delay_int";
@@ -38043,9 +38064,13 @@
     field public static final java.lang.String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
     field public static final java.lang.String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
     field public static final java.lang.String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL = "vvm_cellular_data_required_bool";
+    field public static final java.lang.String KEY_VVM_CLIENT_PREFIX_STRING = "vvm_client_prefix_string";
     field public static final java.lang.String KEY_VVM_DESTINATION_NUMBER_STRING = "vvm_destination_number_string";
+    field public static final java.lang.String KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY = "vvm_disabled_capabilities_string_array";
+    field public static final java.lang.String KEY_VVM_LEGACY_MODE_ENABLED_BOOL = "vvm_legacy_mode_enabled_bool";
     field public static final java.lang.String KEY_VVM_PORT_NUMBER_INT = "vvm_port_number_int";
     field public static final java.lang.String KEY_VVM_PREFETCH_BOOL = "vvm_prefetch_bool";
+    field public static final java.lang.String KEY_VVM_SSL_ENABLED_BOOL = "vvm_ssl_enabled_bool";
     field public static final java.lang.String KEY_VVM_TYPE_STRING = "vvm_type_string";
     field public static final java.lang.String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
   }
@@ -42499,7 +42524,9 @@
     method public android.view.Display.Mode[] getSupportedModes();
     method public deprecated float[] getSupportedRefreshRates();
     method public deprecated int getWidth();
+    method public boolean isHdr();
     method public boolean isValid();
+    method public boolean isWideColorGamut();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
     field public static final int FLAG_PRESENTATION = 8; // 0x8
     field public static final int FLAG_PRIVATE = 4; // 0x4
@@ -42568,7 +42595,7 @@
     method public android.view.View findNearestTouchable(android.view.ViewGroup, int, int, int, int[]);
     method public final android.view.View findNextFocus(android.view.ViewGroup, android.view.View, int);
     method public android.view.View findNextFocusFromRect(android.view.ViewGroup, android.graphics.Rect, int);
-    method public android.view.View findNextKeyboardNavigationGroup(int, android.view.View, android.view.View, int);
+    method public android.view.View findNextKeyboardNavigationCluster(android.view.View, android.view.View, int);
     method public static android.view.FocusFinder getInstance();
   }
 
@@ -43868,7 +43895,7 @@
     method public void addChildrenForAccessibility(java.util.ArrayList<android.view.View>);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int);
     method public void addFocusables(java.util.ArrayList<android.view.View>, int, int);
-    method public void addKeyboardNavigationGroups(int, java.util.Collection<android.view.View>, int);
+    method public void addKeyboardNavigationClusters(java.util.Collection<android.view.View>, int);
     method public void addOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
     method public void addOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
     method public void addTouchables(java.util.ArrayList<android.view.View>);
@@ -44032,7 +44059,6 @@
     method public int getNextFocusLeftId();
     method public int getNextFocusRightId();
     method public int getNextFocusUpId();
-    method public int getNextSectionForwardId();
     method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
     method public android.view.ViewOutlineProvider getOutlineProvider();
     method public int getOverScrollMode();
@@ -44139,7 +44165,6 @@
     method public boolean isInLayout();
     method public boolean isInTouchMode();
     method public final boolean isKeyboardNavigationCluster();
-    method public final boolean isKeyboardNavigationSection();
     method public boolean isLaidOut();
     method public boolean isLayoutDirectionResolved();
     method public boolean isLayoutRequested();
@@ -44162,7 +44187,7 @@
     method public boolean isVerticalFadingEdgeEnabled();
     method public boolean isVerticalScrollBarEnabled();
     method public void jumpDrawablesToCurrentState();
-    method public android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
+    method public android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public void layout(int, int, int, int);
     method public final void measure(int, int);
     method protected static int[] mergeDrawableStates(int[], int[]);
@@ -44312,7 +44337,6 @@
     method public void setImportantForAccessibility(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
-    method public void setKeyboardNavigationSection(boolean);
     method public void setLabelFor(int);
     method public void setLayerPaint(android.graphics.Paint);
     method public void setLayerType(int, android.graphics.Paint);
@@ -44330,7 +44354,6 @@
     method public void setNextFocusLeftId(int);
     method public void setNextFocusRightId(int);
     method public void setNextFocusUpId(int);
-    method public void setNextSectionForwardId(int);
     method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
     method public void setOnClickListener(android.view.View.OnClickListener);
     method public void setOnContextClickListener(android.view.View.OnContextClickListener);
@@ -44457,8 +44480,6 @@
     field public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 1; // 0x1
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
-    field public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1; // 0x1
-    field public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2; // 0x2
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
     field public static final int LAYER_TYPE_NONE = 0; // 0x0
     field public static final int LAYER_TYPE_SOFTWARE = 1; // 0x1
@@ -44981,7 +45002,7 @@
     method public abstract boolean isLayoutRequested();
     method public abstract boolean isTextAlignmentResolved();
     method public abstract boolean isTextDirectionResolved();
-    method public abstract android.view.View keyboardNavigationGroupSearch(int, android.view.View, int);
+    method public abstract android.view.View keyboardNavigationClusterSearch(android.view.View, int);
     method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
     method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
     method public abstract boolean onNestedPreFling(android.view.View, float, float);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 1d4b038..c1a888d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -520,17 +520,17 @@
     /** @hide Flag for registerUidObserver: report uid has become active. */
     public static final int UID_OBSERVER_ACTIVE = 1<<3;
 
-    /** @hide Mode for {@link IActivityManager#getAppStartMode}: normal free-to-run operation. */
+    /** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: normal free-to-run operation. */
     public static final int APP_START_MODE_NORMAL = 0;
 
-    /** @hide Mode for {@link IActivityManager#getAppStartMode}: delay running until later. */
+    /** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: delay running until later. */
     public static final int APP_START_MODE_DELAYED = 1;
 
-    /** @hide Mode for {@link IActivityManager#getAppStartMode}: delay running until later, with
+    /** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: delay running until later, with
      * rigid errors (throwing exception). */
     public static final int APP_START_MODE_DELAYED_RIGID = 2;
 
-    /** @hide Mode for {@link IActivityManager#getAppStartMode}: disable/cancel pending
+    /** @hide Mode for {@link IActivityManager#isAppStartModeDisabled}: disable/cancel pending
      * launches; this is the mode for ephemeral apps. */
     public static final int APP_START_MODE_DISABLED = 3;
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b2c97f6..d37888d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1341,8 +1341,8 @@
         }
         try {
             final Intent intent = ActivityManager.getService().registerReceiver(
-                    mMainThread.getApplicationThread(), mBasePackageName,
-                    rd, filter, broadcastPermission, userId);
+                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
+                    broadcastPermission, userId);
             if (intent != null) {
                 intent.setExtrasClassLoader(getClassLoader());
                 intent.prepareToEnterProcess();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 135c2a4..5a48793 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -264,7 +264,7 @@
     boolean isImmersive(in IBinder token);
     void setImmersive(in IBinder token, boolean immersive);
     boolean isTopActivityImmersive();
-    void crashApplication(int uid, int initialPid, in String packageName, in String message);
+    void crashApplication(int uid, int initialPid, in String packageName, int userId, in String message);
     String getProviderMimeType(in Uri uri, int userId);
     IBinder newUriPermissionOwner(in String name);
     void grantUriPermissionFromOwner(in IBinder owner, int fromUid, in String targetPkg,
@@ -475,7 +475,7 @@
     void suppressResizeConfigChanges(boolean suppress);
     void moveTasksToFullscreenStack(int fromStackId, boolean onTop);
     boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
-    int getAppStartMode(int uid, in String packageName);
+    boolean isAppStartModeDisabled(int uid, in String packageName);
     boolean unlockUser(int userid, in byte[] token, in byte[] secret,
             in IProgressListener listener);
     boolean isInMultiWindowMode(in IBinder token);
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 3e87254..c0bf0c4 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -327,7 +327,7 @@
      * password.
      */
     public boolean isDeviceLocked() {
-        return isDeviceLocked(UserHandle.getCallingUserId());
+        return isDeviceLocked(UserHandle.myUserId());
     }
 
     /**
@@ -352,7 +352,7 @@
      * @return true if a PIN, pattern or password was set.
      */
     public boolean isDeviceSecure() {
-        return isDeviceSecure(UserHandle.getCallingUserId());
+        return isDeviceSecure(UserHandle.myUserId());
     }
 
     /**
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5b74e23..601dfce 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -7088,11 +7088,13 @@
         private static final String EXTRA_FLAGS = "flags";
         private static final String EXTRA_CONTENT_INTENT = "content_intent";
         private static final String EXTRA_DELETE_INTENT = "delete_intent";
+        private static final String EXTRA_CHANNEL_ID = "channel_id";
 
         // Flags bitwise-ored to mFlags
         private static final int FLAG_AVAILABLE_ON_TV = 0x1;
 
         private int mFlags;
+        private String mChannelId;
         private PendingIntent mContentIntent;
         private PendingIntent mDeleteIntent;
 
@@ -7113,6 +7115,7 @@
                 null : notif.extras.getBundle(EXTRA_TV_EXTENDER);
             if (bundle != null) {
                 mFlags = bundle.getInt(EXTRA_FLAGS);
+                mChannelId = bundle.getString(EXTRA_CHANNEL_ID);
                 mContentIntent = bundle.getParcelable(EXTRA_CONTENT_INTENT);
                 mDeleteIntent = bundle.getParcelable(EXTRA_DELETE_INTENT);
             }
@@ -7128,6 +7131,7 @@
             Bundle bundle = new Bundle();
 
             bundle.putInt(EXTRA_FLAGS, mFlags);
+            bundle.putString(EXTRA_CHANNEL_ID, mChannelId);
             if (mContentIntent != null) {
                 bundle.putParcelable(EXTRA_CONTENT_INTENT, mContentIntent);
             }
@@ -7149,6 +7153,23 @@
         }
 
         /**
+         * Specifies the channel the notification should be delivered on when shown on TV.
+         * It can be different from the channel that the notification is delivered to when
+         * posting on a non-TV device.
+         */
+        public TvExtender setChannel(String channelId) {
+            mChannelId = channelId;
+            return this;
+        }
+
+        /**
+         * Returns the id of the channel this notification posts to on TV.
+         */
+        public String getChannel() {
+            return mChannelId;
+        }
+
+        /**
          * Supplies a {@link PendingIntent} to be sent when the notification is selected on TV.
          * If provided, it is used instead of the content intent specified
          * at the level of Notification.
diff --git a/core/java/android/app/RecoverableSecurityException.java b/core/java/android/app/RecoverableSecurityException.java
new file mode 100644
index 0000000..1f015a6
--- /dev/null
+++ b/core/java/android/app/RecoverableSecurityException.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Specialization of {@link SecurityException} that contains additional
+ * information about how to involve the end user to recover from the exception.
+ * <p>
+ * This exception is only appropriate where there is a concrete action the user
+ * can take to recover and make forward progress, such as confirming or entering
+ * authentication credentials.
+ * <p class="note">
+ * Note: legacy code that receives this exception may treat it as a general
+ * {@link SecurityException}, and thus there is no guarantee that the messages
+ * contained will be shown to the end user.
+ * </p>
+ */
+public final class RecoverableSecurityException extends SecurityException implements Parcelable {
+    private static final String TAG = "RecoverableSecurityException";
+
+    private final CharSequence mUserMessage;
+    private final CharSequence mUserActionTitle;
+    private final PendingIntent mUserAction;
+
+    /** {@hide} */
+    public RecoverableSecurityException(Parcel in) {
+        this(new SecurityException(in.readString()), in.readCharSequence(), in.readCharSequence(),
+                PendingIntent.CREATOR.createFromParcel(in));
+    }
+
+    /**
+     * Create an instance ready to be thrown.
+     *
+     * @param cause original cause with details designed for engineering
+     *            audiences.
+     * @param userMessage short message describing the issue for end user
+     *            audiences, which may be shown in a notification or dialog.
+     *            This should be less than 64 characters. For example: <em>PIN
+     *            required to access Document.pdf</em>
+     * @param userActionTitle short title describing the primary action. This
+     *            should be less than 24 characters. For example: <em>Enter
+     *            PIN</em>
+     * @param userAction primary action that will initiate the recovery. This
+     *            must launch an activity that is expected to set
+     *            {@link Activity#setResult(int)} before finishing to
+     *            communicate the final status of the recovery. For example,
+     *            apps that observe {@link Activity#RESULT_OK} may choose to
+     *            immediately retry their operation.
+     */
+    public RecoverableSecurityException(Throwable cause, CharSequence userMessage,
+            CharSequence userActionTitle, PendingIntent userAction) {
+        super(cause.getMessage());
+        mUserMessage = Preconditions.checkNotNull(userMessage);
+        mUserActionTitle = Preconditions.checkNotNull(userActionTitle);
+        mUserAction = Preconditions.checkNotNull(userAction);
+    }
+
+    /**
+     * Return short message describing the issue for end user audiences, which
+     * may be shown in a notification or dialog.
+     */
+    public CharSequence getUserMessage() {
+        return mUserMessage;
+    }
+
+    /**
+     * Return short title describing the primary action.
+     */
+    public CharSequence getUserActionTitle() {
+        return mUserActionTitle;
+    }
+
+    /**
+     * Return primary action that will initiate the recovery.
+     */
+    public PendingIntent getUserAction() {
+        return mUserAction;
+    }
+
+    /**
+     * Convenience method that will show a very simple notification populated
+     * with the details from this exception.
+     * <p>
+     * If you want more flexibility over retrying your original operation once
+     * the user action has finished, consider presenting your own UI that uses
+     * {@link Activity#startIntentSenderForResult} to launch the
+     * {@link PendingIntent#getIntentSender()} from {@link #getUserAction()}
+     * when requested. If the result of that activity is
+     * {@link Activity#RESULT_OK}, you should consider retrying.
+     * <p>
+     * This method will only display the most recent exception from any single
+     * remote UID; notifications from older exceptions will always be replaced.
+     */
+    public void showAsNotification(Context context) {
+        final Notification.Builder builder = new Notification.Builder(context)
+                .setSmallIcon(com.android.internal.R.drawable.ic_print_error)
+                .setContentTitle(mUserActionTitle)
+                .setContentText(mUserMessage)
+                .setContentIntent(mUserAction)
+                .setCategory(Notification.CATEGORY_ERROR);
+
+        final NotificationManager nm = context.getSystemService(NotificationManager.class);
+        nm.notify(TAG, mUserAction.getCreatorUid(), builder.build());
+    }
+
+    /**
+     * Convenience method that will show a very simple dialog populated with the
+     * details from this exception.
+     * <p>
+     * If you want more flexibility over retrying your original operation once
+     * the user action has finished, consider presenting your own UI that uses
+     * {@link Activity#startIntentSenderForResult} to launch the
+     * {@link PendingIntent#getIntentSender()} from {@link #getUserAction()}
+     * when requested. If the result of that activity is
+     * {@link Activity#RESULT_OK}, you should consider retrying.
+     * <p>
+     * This method will only display the most recent exception from any single
+     * remote UID; dialogs from older exceptions will always be replaced.
+     */
+    public void showAsDialog(Activity activity) {
+        final LocalDialog dialog = new LocalDialog();
+        final Bundle args = new Bundle();
+        args.putParcelable(TAG, this);
+        dialog.setArguments(args);
+
+        final String tag = TAG + "_" + mUserAction.getCreatorUid();
+        final FragmentManager fm = activity.getFragmentManager();
+        final FragmentTransaction ft = fm.beginTransaction();
+        final Fragment old = fm.findFragmentByTag(tag);
+        if (old != null) {
+            ft.remove(old);
+        }
+        ft.add(dialog, tag);
+        ft.commitAllowingStateLoss();
+    }
+
+    /** {@hide} */
+    public static class LocalDialog extends DialogFragment {
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            final RecoverableSecurityException e = getArguments().getParcelable(TAG);
+            return new AlertDialog.Builder(getActivity())
+                    .setMessage(e.mUserMessage)
+                    .setPositiveButton(e.mUserActionTitle, (dialog, which) -> {
+                        try {
+                            e.mUserAction.send();
+                        } catch (PendingIntent.CanceledException ignored) {
+                        }
+                    })
+                    .setNegativeButton(android.R.string.cancel, null)
+                    .create();
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(getMessage());
+        dest.writeCharSequence(mUserMessage);
+        dest.writeCharSequence(mUserActionTitle);
+        mUserAction.writeToParcel(dest, flags);
+    }
+
+    public static final Creator<RecoverableSecurityException> CREATOR =
+            new Creator<RecoverableSecurityException>() {
+        @Override
+        public RecoverableSecurityException createFromParcel(Parcel source) {
+            return new RecoverableSecurityException(source);
+        }
+
+        @Override
+        public RecoverableSecurityException[] newArray(int size) {
+            return new RecoverableSecurityException[size];
+        }
+    };
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0da89eb..aa56be6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3735,13 +3735,13 @@
     }
 
     /**
-     * Called by a device owner to set whether auto time is required. If auto time is required the
-     * user cannot set the date and time, but has to use network date and time.
+     * Called by a device or profile owner to set whether auto time is required. If auto time is
+     * required, no user will be able set the date and time and network date and time will be used.
      * <p>
      * Note: if auto time is required the user can still manually set the time zone.
      * <p>
-     * The calling device admin must be a device owner. If it is not, a security exception will be
-     * thrown.
+     * The calling device admin must be a device or profile owner. If it is not, a security
+     * exception will be thrown.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param required Whether auto time is set required or not.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 8cc9a3a..c550094 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4842,6 +4842,10 @@
      * or not running) apps, regardless of whether that would be done by default.  By
      * default they will only receive broadcasts if the broadcast has specified an
      * explicit component or package name.
+     *
+     * NOTE: dumpstate uses this flag numerically, so when its value is changed
+     * the broadcast code there must also be changed to match.
+     *
      * @hide
      */
     public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000;
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index b03c907..35a266b 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -291,4 +291,6 @@
     void fstrim(int flags) = 72;
     AppFuseMount mountProxyFileDescriptorBridge() = 73;
     ParcelFileDescriptor openProxyFileDescriptor(int mountPointId, int fileId, int mode) = 74;
+    long getCacheQuotaBytes(String volumeUuid, int uid) = 75;
+    long getCacheSizeBytes(String volumeUuid, int uid) = 76;
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index c6ff476..626d6f4 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -24,27 +24,32 @@
 import android.app.ActivityThread;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.PackageManager;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
-import android.os.ProxyFileDescriptorCallback;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
+import android.os.ProxyFileDescriptorCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.AppFuseMount;
@@ -60,6 +65,7 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.lang.ref.WeakReference;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -1396,6 +1402,222 @@
         }
     }
 
+    /**
+     * Return quota size in bytes for cached data belonging to the calling app.
+     * <p>
+     * If your app goes above this quota, your cached files will be some of the
+     * first to be deleted when additional disk space is needed. Conversely, if
+     * your app stays under this quota, your cached files will be some of the
+     * last to be deleted when additional disk space is needed.
+     * <p>
+     * This quota may change over time depending on how frequently the user
+     * interacts with your app, and depending on how much disk space is used.
+     * <p>
+     * Cached data tracked by this method always includes
+     * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and
+     * it also includes {@link Context#getExternalCacheDir()} if the primary
+     * shared/external storage is hosted on the same storage device as your
+     * private data.
+     * <p class="note">
+     * Note: if your app uses the {@code android:sharedUserId} manifest feature,
+     * then cached data for all packages in your shared UID is tracked together
+     * as a single unit.
+     * </p>
+     *
+     * @see #getCacheQuotaBytes()
+     * @see #getCacheSizeBytes()
+     * @see #getExternalCacheQuotaBytes()
+     * @see #getExternalCacheSizeBytes()
+     */
+    public long getCacheQuotaBytes() {
+        try {
+            final ApplicationInfo app = mContext.getApplicationInfo();
+            return mStorageManager.getCacheQuotaBytes(app.volumeUuid, app.uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return total size in bytes of cached data belonging to the calling app.
+     * <p>
+     * Cached data tracked by this method always includes
+     * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}, and
+     * it also includes {@link Context#getExternalCacheDir()} if the primary
+     * shared/external storage is hosted on the same storage device as your
+     * private data.
+     * <p class="note">
+     * Note: if your app uses the {@code android:sharedUserId} manifest feature,
+     * then cached data for all packages in your shared UID is tracked together
+     * as a single unit.
+     * </p>
+     *
+     * @see #getCacheQuotaBytes()
+     * @see #getCacheSizeBytes()
+     * @see #getExternalCacheQuotaBytes()
+     * @see #getExternalCacheSizeBytes()
+     */
+    public long getCacheSizeBytes() {
+        try {
+            final ApplicationInfo app = mContext.getApplicationInfo();
+            return mStorageManager.getCacheSizeBytes(app.volumeUuid, app.uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return quota size in bytes for cached data on primary shared/external
+     * storage belonging to the calling app.
+     * <p>
+     * If primary shared/external storage is hosted on the same storage device
+     * as your private data, this method will return -1, since all data stored
+     * under {@link Context#getExternalCacheDir()} will be counted under
+     * {@link #getCacheQuotaBytes()}.
+     * <p class="note">
+     * Note: if your app uses the {@code android:sharedUserId} manifest feature,
+     * then cached data for all packages in your shared UID is tracked together
+     * as a single unit.
+     * </p>
+     */
+    public long getExternalCacheQuotaBytes() {
+        final ApplicationInfo app = mContext.getApplicationInfo();
+        final String primaryUuid = getPrimaryStorageUuid();
+        if (Objects.equals(app.volumeUuid, primaryUuid)) {
+            return -1;
+        }
+        try {
+            return mStorageManager.getCacheQuotaBytes(primaryUuid, app.uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return total size in bytes of cached data on primary shared/external
+     * storage belonging to the calling app.
+     * <p>
+     * If primary shared/external storage is hosted on the same storage device
+     * as your private data, this method will return -1, since all data stored
+     * under {@link Context#getExternalCacheDir()} will be counted under
+     * {@link #getCacheQuotaBytes()}.
+     * <p class="note">
+     * Note: if your app uses the {@code android:sharedUserId} manifest feature,
+     * then cached data for all packages in your shared UID is tracked together
+     * as a single unit.
+     * </p>
+     */
+    public long getExternalCacheSizeBytes() {
+        final ApplicationInfo app = mContext.getApplicationInfo();
+        final String primaryUuid = getPrimaryStorageUuid();
+        if (Objects.equals(app.volumeUuid, primaryUuid)) {
+            return -1;
+        }
+        try {
+            return mStorageManager.getCacheSizeBytes(primaryUuid, app.uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private static final String XATTR_ATOMIC = "user.atomic";
+    private static final String XATTR_TOMBSTONE = "user.tombstone";
+
+    /** {@hide} */
+    private static void setCacheBehavior(File path, String name, boolean enabled)
+            throws IOException {
+        if (!path.isDirectory()) {
+            throw new IOException("Cache behavior can only be set on directories");
+        }
+        if (enabled) {
+            try {
+                Os.setxattr(path.getAbsolutePath(), name,
+                        "1".getBytes(StandardCharsets.UTF_8), 0);
+            } catch (ErrnoException e) {
+                throw e.rethrowAsIOException();
+            }
+        } else {
+            try {
+                Os.removexattr(path.getAbsolutePath(), name);
+            } catch (ErrnoException e) {
+                if (e.errno != OsConstants.ENODATA) {
+                    throw e.rethrowAsIOException();
+                }
+            }
+        }
+    }
+
+    /** {@hide} */
+    private static boolean isCacheBehavior(File path, String name) throws IOException {
+        try {
+            Os.getxattr(path.getAbsolutePath(), name);
+            return true;
+        } catch (ErrnoException e) {
+            if (e.errno != OsConstants.ENODATA) {
+                throw e.rethrowAsIOException();
+            } else {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Enable or disable special cache behavior that treats this directory and
+     * its contents as an atomic unit.
+     * <p>
+     * When enabled and this directory is considered for automatic deletion by
+     * the OS, all contained files will either be deleted together, or not at
+     * all. This is useful when you have a directory that contains several
+     * related metadata files that depend on each other, such as movie file and
+     * a subtitle file.
+     * <p>
+     * When enabled, the <em>newest</em> {@link File#lastModified()} value of
+     * any contained files is considered the modified time of the entire
+     * directory.
+     * <p>
+     * This behavior can only be set on a directory, and it applies recursively
+     * to all contained files and directories.
+     */
+    public void setCacheBehaviorAtomic(File path, boolean atomic) throws IOException {
+        setCacheBehavior(path, XATTR_ATOMIC, atomic);
+    }
+
+    /**
+     * Read the current value set by
+     * {@link #setCacheBehaviorAtomic(File, boolean)}.
+     */
+    public boolean isCacheBehaviorAtomic(File path) throws IOException {
+        return isCacheBehavior(path, XATTR_ATOMIC);
+    }
+
+    /**
+     * Enable or disable special cache behavior that leaves deleted cache files
+     * intact as tombstones.
+     * <p>
+     * When enabled and a file contained in this directory is automatically
+     * deleted by the OS, the file will be truncated to have a length of 0 bytes
+     * instead of being fully deleted. This is useful if you need to distinguish
+     * between a file that was deleted versus one that never existed.
+     * <p>
+     * This behavior can only be set on a directory, and it applies recursively
+     * to all contained files and directories.
+     * <p class="note">
+     * Note: this behavior is ignored completely if the user explicitly requests
+     * that all cached data be cleared.
+     * </p>
+     */
+    public void setCacheBehaviorTombstone(File path, boolean tombstone) throws IOException {
+        setCacheBehavior(path, XATTR_TOMBSTONE, tombstone);
+    }
+
+    /**
+     * Read the current value set by
+     * {@link #setCacheBehaviorTombstone(File, boolean)}.
+     */
+    public boolean isCacheBehaviorTombstone(File path) throws IOException {
+        return isCacheBehavior(path, XATTR_TOMBSTONE);
+    }
+
     private final Object mFuseAppLoopLock = new Object();
 
     @GuardedBy("mFuseAppLoopLock")
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index b37ea8e..105cc47 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -292,7 +292,7 @@
     public static final int STATE_VR = 5;
 
     /* The color mode constants defined below must be kept in sync with the ones in
-     * system/graphics.h */
+     * system/core/include/system/graphics-base.h */
 
     /**
      * Display color mode: The current color mode is unknown or invalid.
@@ -306,11 +306,24 @@
      */
     public static final int COLOR_MODE_DEFAULT = 0;
 
-    /**
-     * Display color mode: SRGB
-     * @hide
-     */
+    /** @hide */
+    public static final int COLOR_MODE_BT601_625 = 1;
+    /** @hide */
+    public static final int COLOR_MODE_BT601_625_UNADJUSTED = 2;
+    /** @hide */
+    public static final int COLOR_MODE_BT601_525 = 3;
+    /** @hide */
+    public static final int COLOR_MODE_BT601_525_UNADJUSTED = 4;
+    /** @hide */
+    public static final int COLOR_MODE_BT709 = 5;
+    /** @hide */
+    public static final int COLOR_MODE_DCI_P3 = 6;
+    /** @hide */
     public static final int COLOR_MODE_SRGB = 7;
+    /** @hide */
+    public static final int COLOR_MODE_ADOBE_RGB = 8;
+    /** @hide */
+    public static final int COLOR_MODE_DISPLAY_P3 = 9;
 
     /**
      * Internal method to create a display.
@@ -745,6 +758,8 @@
 
     /**
      * Returns the display's HDR capabilities.
+     *
+     * @see #isHdr()
      */
     public HdrCapabilities getHdrCapabilities() {
         synchronized (this) {
@@ -754,6 +769,35 @@
     }
 
     /**
+     * Returns whether this display supports any HDR type.
+     *
+     * @see #getHdrCapabilities()
+     * @see HdrCapabilities#getSupportedHdrTypes()
+     */
+    public boolean isHdr() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            int[] types = mDisplayInfo.hdrCapabilities.getSupportedHdrTypes();
+            return types != null && types.length > 0;
+        }
+    }
+
+    /**
+     * Returns whether this display can be used to display wide color gamut content.
+     */
+    public boolean isWideColorGamut() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            for (int colorMode : mDisplayInfo.supportedColorModes) {
+                if (colorMode == COLOR_MODE_DCI_P3 || colorMode > COLOR_MODE_SRGB) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
      * Gets the supported color modes of this device.
      * @hide
      */
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index a07a7ef..41a13cf 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -16,16 +16,12 @@
 
 package android.view;
 
-import static android.view.View.KEYBOARD_NAVIGATION_GROUP_CLUSTER;
-import static android.view.View.KEYBOARD_NAVIGATION_GROUP_SECTION;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Rect;
 import android.util.ArrayMap;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
-import android.view.View.KeyboardNavigationGroupType;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -110,31 +106,28 @@
     }
 
     /**
-     * Find the root of the next keyboard navigation group after the current one. The group type can
-     * be either a cluster or a section.
-     * @param groupType Type of the keyboard navigation group
+     * Find the root of the next keyboard navigation cluster after the current one.
      * @param root The view tree to look inside. Cannot be null
-     * @param currentGroup The starting point of the search. Null means the default group
+     * @param currentCluster The starting point of the search. Null means the default cluster
      * @param direction Direction to look
-     * @return The next group, or null if none exists
+     * @return The next cluster, or null if none exists
      */
-    public View findNextKeyboardNavigationGroup(
-            @KeyboardNavigationGroupType int groupType,
+    public View findNextKeyboardNavigationCluster(
             @NonNull View root,
-            @Nullable View currentGroup,
+            @Nullable View currentCluster,
             int direction) {
         View next = null;
 
-        final ArrayList<View> groups = mTempList;
+        final ArrayList<View> clusters = mTempList;
         try {
-            groups.clear();
-            root.addKeyboardNavigationGroups(groupType, groups, direction);
-            if (!groups.isEmpty()) {
-                next = findNextKeyboardNavigationGroup(
-                        groupType, root, currentGroup, groups, direction);
+            clusters.clear();
+            root.addKeyboardNavigationClusters(clusters, direction);
+            if (!clusters.isEmpty()) {
+                next = findNextKeyboardNavigationCluster(
+                        root, currentCluster, clusters, direction);
             }
         } finally {
-            groups.clear();
+            clusters.clear();
         }
         return next;
     }
@@ -207,25 +200,22 @@
         }
     }
 
-    private View findNextKeyboardNavigationGroup(
-            @KeyboardNavigationGroupType int groupType,
+    private View findNextKeyboardNavigationCluster(
             View root,
-            View currentGroup,
-            List<View> groups,
+            View currentCluster,
+            List<View> clusters,
             int direction) {
-        final int count = groups.size();
+        final int count = clusters.size();
 
         switch (direction) {
             case View.FOCUS_FORWARD:
             case View.FOCUS_DOWN:
             case View.FOCUS_RIGHT:
-                return getNextKeyboardNavigationGroup(
-                        groupType, root, currentGroup, groups, count);
+                return getNextKeyboardNavigationCluster(root, currentCluster, clusters, count);
             case View.FOCUS_BACKWARD:
             case View.FOCUS_UP:
             case View.FOCUS_LEFT:
-                return getPreviousKeyboardNavigationGroup(
-                        groupType, root, currentGroup, groups, count);
+                return getPreviousKeyboardNavigationCluster(root, currentCluster, clusters, count);
             default:
                 throw new IllegalArgumentException("Unknown direction: " + direction);
         }
@@ -331,70 +321,50 @@
         return null;
     }
 
-    private static View getNextKeyboardNavigationGroup(
-            @KeyboardNavigationGroupType int groupType,
+    private static View getNextKeyboardNavigationCluster(
             View root,
-            View currentGroup,
-            List<View> groups,
+            View currentCluster,
+            List<View> clusters,
             int count) {
-        if (currentGroup == null) {
-            // The current group is the default one.
-            // The next group after the default one is the first one.
-            // Note that the caller guarantees that 'group' is not empty.
-            return groups.get(0);
+        if (currentCluster == null) {
+            // The current cluster is the default one.
+            // The next cluster after the default one is the first one.
+            // Note that the caller guarantees that 'clusters' is not empty.
+            return clusters.get(0);
         }
 
-        final int position = groups.lastIndexOf(currentGroup);
+        final int position = clusters.lastIndexOf(currentCluster);
         if (position >= 0 && position + 1 < count) {
-            // Return the next non-default group if we can find it.
-            return groups.get(position + 1);
+            // Return the next non-default cluster if we can find it.
+            return clusters.get(position + 1);
         }
 
-        switch (groupType) {
-            case KEYBOARD_NAVIGATION_GROUP_CLUSTER:
-                // The current cluster is the last one. The next one is the default one, i.e. the
-                // root.
-                return root;
-            case KEYBOARD_NAVIGATION_GROUP_SECTION:
-                // There is no "default section", hence returning the first one.
-                return groups.get(0);
-            default:
-                throw new IllegalArgumentException(
-                        "Unknown keyboard navigation group type: " + groupType);
-        }
+        // The current cluster is the last one. The next one is the default one, i.e. the
+        // root.
+        return root;
     }
 
-    private static View getPreviousKeyboardNavigationGroup(
-            @KeyboardNavigationGroupType int groupType,
+    private static View getPreviousKeyboardNavigationCluster(
             View root,
-            View currentGroup,
-            List<View> groups,
+            View currentCluster,
+            List<View> clusters,
             int count) {
-        if (currentGroup == null) {
-            // The current group is the default one.
-            // The previous group before the default one is the last one.
-            // Note that the caller guarantees that 'groups' is not empty.
-            return groups.get(count - 1);
+        if (currentCluster == null) {
+            // The current cluster is the default one.
+            // The previous cluster before the default one is the last one.
+            // Note that the caller guarantees that 'clusters' is not empty.
+            return clusters.get(count - 1);
         }
 
-        final int position = groups.indexOf(currentGroup);
+        final int position = clusters.indexOf(currentCluster);
         if (position > 0) {
-            // Return the previous non-default group if we can find it.
-            return groups.get(position - 1);
+            // Return the previous non-default cluster if we can find it.
+            return clusters.get(position - 1);
         }
 
-        switch (groupType) {
-            case KEYBOARD_NAVIGATION_GROUP_CLUSTER:
-                // The current cluster is the first one. The previous one is the default one, i.e.
-                // the root.
-                return root;
-            case KEYBOARD_NAVIGATION_GROUP_SECTION:
-                // There is no "default section", hence returning the last one.
-                return groups.get(count - 1);
-            default:
-                throw new IllegalArgumentException(
-                        "Unknown keyboard navigation group type: " + groupType);
-        }
+        // The current cluster is the first one. The previous one is the default one, i.e.
+        // the root.
+        return root;
     }
 
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 26e311c..13555f4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1252,14 +1252,6 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
 
-    /** @hide */
-    @IntDef({
-            KEYBOARD_NAVIGATION_GROUP_CLUSTER,
-            KEYBOARD_NAVIGATION_GROUP_SECTION
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface KeyboardNavigationGroupType {}
-
     /**
      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
      * item.
@@ -1293,18 +1285,6 @@
     public static final int FOCUS_DOWN = 0x00000082;
 
     /**
-     * Use with {@link #keyboardNavigationGroupSearch(int, View, int)}. Search for a keyboard
-     * navigation cluster.
-     */
-    public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1;
-
-    /**
-     * Use with {@link #keyboardNavigationGroupSearch(int, View, int)}. Search for a keyboard
-     * navigation section.
-     */
-    public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2;
-
-    /**
      * Bits of {@link #getMeasuredWidthAndState()} and
      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
      */
@@ -2500,7 +2480,7 @@
      *                    1              PFLAG3_SCROLL_INDICATOR_END
      *                   1               PFLAG3_ASSIST_BLOCKED
      *                  1                PFLAG3_CLUSTER
-     *                 1                 PFLAG3_SECTION
+     *                 x                 * NO LONGER NEEDED, SHOULD BE REUSED *
      *                1                  PFLAG3_FINGER_DOWN
      *               1                   PFLAG3_FOCUSED_BY_DEFAULT
      *           xxxx                    * NO LONGER NEEDED, SHOULD BE REUSED *
@@ -2710,14 +2690,6 @@
     private static final int PFLAG3_CLUSTER = 0x8000;
 
     /**
-     * Flag indicating that the view is a root of a keyboard navigation section.
-     *
-     * @see #isKeyboardNavigationSection()
-     * @see #setKeyboardNavigationSection(boolean)
-     */
-    private static final int PFLAG3_SECTION = 0x10000;
-
-    /**
      * Indicates that the user is currently touching the screen.
      * Currently used for the tooltip positioning only.
      */
@@ -3807,11 +3779,6 @@
      */
     int mNextClusterForwardId = View.NO_ID;
 
-    /**
-     * User-specified next keyboard navigation section.
-     */
-    int mNextSectionForwardId = View.NO_ID;
-
     private CheckForLongPress mPendingCheckForLongPress;
     private CheckForTap mPendingCheckForTap = null;
     private PerformClick mPerformClick;
@@ -4622,9 +4589,6 @@
                 case R.styleable.View_nextClusterForward:
                     mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
                     break;
-                case R.styleable.View_nextSectionForward:
-                    mNextSectionForwardId = a.getResourceId(attr, View.NO_ID);
-                    break;
                 case R.styleable.View_minWidth:
                     mMinWidth = a.getDimensionPixelSize(attr, 0);
                     break;
@@ -4769,11 +4733,6 @@
                         setKeyboardNavigationCluster(a.getBoolean(attr, true));
                     }
                     break;
-                case R.styleable.View_keyboardNavigationSection:
-                    if (a.peekValue(attr) != null) {
-                        setKeyboardNavigationSection(a.getBoolean(attr, true));
-                    }
-                    break;
                 case R.styleable.View_focusedByDefault:
                     if (a.peekValue(attr) != null) {
                         setFocusedByDefault(a.getBoolean(attr, true));
@@ -8043,28 +8002,6 @@
     }
 
     /**
-     * Gets the id of the root of the next keyboard navigation section.
-     * @return The next keyboard navigation section ID, or {@link #NO_ID} if the framework should
-     * decide automatically.
-     *
-     * @attr ref android.R.styleable#View_nextSectionForward
-     */
-    public int getNextSectionForwardId() {
-        return mNextSectionForwardId;
-    }
-
-    /**
-     * Sets the id of the view to use as the root of the next keyboard navigation section.
-     * @param nextSectionForwardId The next section ID, or {@link #NO_ID} if the framework should
-     * decide automatically.
-     *
-     * @attr ref android.R.styleable#View_nextSectionForward
-     */
-    public void setNextSectionForwardId(int nextSectionForwardId) {
-        mNextSectionForwardId = nextSectionForwardId;
-    }
-
-    /**
      * Returns the visibility of this view and all of its ancestors
      *
      * @return True if this view and all of its ancestors are {@link #VISIBLE}
@@ -9186,49 +9123,11 @@
     }
 
     /**
-     * Returns whether this View is a root of a keyboard navigation section.
-     *
-     * @return True if this view is a root of a section, or false otherwise.
-     * @attr ref android.R.styleable#View_keyboardNavigationSection
-     */
-    @ViewDebug.ExportedProperty(category = "keyboardNavigationSection")
-    public final boolean isKeyboardNavigationSection() {
-        return (mPrivateFlags3 & PFLAG3_SECTION) != 0;
-    }
-
-    /**
-     * Set whether this view is a root of a keyboard navigation section.
-     *
-     * @param isSection If true, this view is a root of a section.
-     *
-     * @attr ref android.R.styleable#View_keyboardNavigationSection
-     */
-    public void setKeyboardNavigationSection(boolean isSection) {
-        if (isSection) {
-            mPrivateFlags3 |= PFLAG3_SECTION;
-        } else {
-            mPrivateFlags3 &= ~PFLAG3_SECTION;
-        }
-    }
-
-    final boolean isKeyboardNavigationGroupOfType(@KeyboardNavigationGroupType int groupType) {
-        switch (groupType) {
-            case KEYBOARD_NAVIGATION_GROUP_CLUSTER:
-                return isKeyboardNavigationCluster();
-            case KEYBOARD_NAVIGATION_GROUP_SECTION:
-                return isKeyboardNavigationSection();
-            default:
-                throw new IllegalArgumentException(
-                        "Unknown keyboard navigation group type: " + groupType);
-        }
-    }
-
-    /**
      * Returns whether this View should receive focus when the focus is restored for the view
      * hierarchy containing this view.
      * <p>
      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
-     * window or serves as a target of cluster or section navigation.
+     * window or serves as a target of cluster navigation.
      *
      * @see #restoreDefaultFocus(int)
      *
@@ -9245,7 +9144,7 @@
      * hierarchy containing this view.
      * <p>
      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
-     * window or serves as a target of cluster or section navigation.
+     * window or serves as a target of cluster navigation.
      *
      * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
      *                           {@code false} otherwise.
@@ -9284,35 +9183,28 @@
     }
 
     /**
-     * Find the nearest keyboard navigation group in the specified direction. The group type can be
-     * either a cluster or a section.
-     * This does not actually give focus to that group.
+     * Find the nearest keyboard navigation cluster in the specified direction.
+     * This does not actually give focus to that cluster.
      *
-     * @param groupType Type of the keyboard navigation group
-     * @param currentGroup The starting point of the search. Null means the current group is not
-     *                     found yet
+     * @param currentCluster The starting point of the search. Null means the current cluster is not
+     *                       found yet
      * @param direction Direction to look
      *
-     * @return The nearest keyboard navigation group in the specified direction, or null if none
+     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
      *         can be found
      */
-    public View keyboardNavigationGroupSearch(
-            @KeyboardNavigationGroupType int groupType, View currentGroup, int direction) {
-        if (isKeyboardNavigationGroupOfType(groupType)) {
-            currentGroup = this;
+    public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+        if (isKeyboardNavigationCluster()) {
+            currentCluster = this;
         }
-        if (isRootNamespace()
-                || (groupType == KEYBOARD_NAVIGATION_GROUP_SECTION
-                && isKeyboardNavigationCluster())) {
+        if (isRootNamespace()) {
             // Root namespace means we should consider ourselves the top of the
             // tree for group searching; otherwise we could be group searching
             // into other tabs.  see LocalActivityManager and TabHost for more info.
-            // In addition, a cluster node works as a root for section searches.
-            return FocusFinder.getInstance().findNextKeyboardNavigationGroup(
-                    groupType, this, currentGroup, direction);
+            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
+                    this, currentCluster, direction);
         } else if (mParent != null) {
-            return mParent.keyboardNavigationGroupSearch(
-                    groupType, currentGroup, direction);
+            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
         }
         return null;
     }
@@ -9440,19 +9332,16 @@
     }
 
     /**
-     * Adds any keyboard navigation group roots that are descendants of this view (possibly
-     * including this view if it is a group root itself) to views. The group type can be either a
-     * cluster or a section.
+     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
+     * including this view if it is a cluster root itself) to views.
      *
-     * @param groupType Type of the keyboard navigation group
-     * @param views Keyboard navigation group roots found so far
+     * @param views Keyboard navigation cluster roots found so far
      * @param direction Direction to look
      */
-    public void addKeyboardNavigationGroups(
-            @KeyboardNavigationGroupType int groupType,
+    public void addKeyboardNavigationClusters(
             @NonNull Collection<View> views,
             int direction) {
-        if (!(isKeyboardNavigationGroupOfType(groupType))) {
+        if (!(isKeyboardNavigationCluster())) {
             return;
         }
         views.add(this);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d252d75..480741e 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -915,13 +915,10 @@
      */
     @Override
     public View focusSearch(View focused, int direction) {
-        if (isRootNamespace()
-                || isKeyboardNavigationCluster()
-                && (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD)) {
+        if (isRootNamespace()) {
             // root namespace means we should consider ourselves the top of the
             // tree for focus searching; otherwise we could be focus searching
             // into other tabs.  see LocalActivityManager and TabHost for more info.
-            // Cluster's root works same way for the forward and backward navigation.
             return FocusFinder.getInstance().findNextFocus(this, focused, direction);
         } else if (mParent != null) {
             return mParent.focusSearch(focused, direction);
@@ -1136,12 +1133,6 @@
 
     @Override
     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
-        if (isKeyboardNavigationCluster()
-                && (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) && !hasFocus()) {
-            // A cluster cannot be focus-entered from outside using forward/backward navigation.
-            return;
-        }
-
         final int focusableCount = views.size();
 
         final int descendantFocusability = getDescendantFocusability();
@@ -1175,11 +1166,10 @@
     }
 
     @Override
-    public void addKeyboardNavigationGroups(
-            @KeyboardNavigationGroupType int groupType, Collection<View> views, int direction) {
+    public void addKeyboardNavigationClusters(Collection<View> views, int direction) {
         final int focusableCount = views.size();
 
-        super.addKeyboardNavigationGroups(groupType, views, direction);
+        super.addKeyboardNavigationClusters(views, direction);
 
         if (focusableCount != views.size()) {
             // No need to look for groups inside a group.
@@ -1195,14 +1185,8 @@
 
         for (int i = 0; i < count; i++) {
             final View child = children[i];
-            if (groupType == KEYBOARD_NAVIGATION_GROUP_SECTION
-                    && child.isKeyboardNavigationCluster()) {
-                // When the current cluster is the default cluster, and we are searching for
-                // sections, ignore sections inside non-default clusters.
-                continue;
-            }
             if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
-                child.addKeyboardNavigationGroups(groupType, views, direction);
+                child.addKeyboardNavigationClusters(views, direction);
             }
         }
     }
@@ -3072,8 +3056,7 @@
         final View[] children = mChildren;
         for (int i = index; i != end; i += increment) {
             View child = children[i];
-            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
-                    && !child.isKeyboardNavigationCluster()) {
+            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
                 if (child.requestFocus(direction, previouslyFocusedRect)) {
                     return true;
                 }
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index c9277ca..79b05cd 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -18,7 +18,6 @@
 
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.view.View.KeyboardNavigationGroupType;
 import android.view.accessibility.AccessibilityEvent;
 
 /**
@@ -148,20 +147,17 @@
     public View focusSearch(View v, int direction);
 
     /**
-     * Find the nearest keyboard navigation group in the specified direction. The group type can be
-     * either a cluster or a section.
-     * This does not actually give focus to that group.
+     * Find the nearest keyboard navigation cluster in the specified direction.
+     * This does not actually give focus to that cluster.
      *
-     * @param groupType Type of the keyboard navigation group
-     * @param currentGroup The starting point of the search. Null means the current group is not
-     *                     found yet
+     * @param currentCluster The starting point of the search. Null means the current cluster is not
+     *                       found yet
      * @param direction Direction to look
      *
-     * @return The nearest keyboard navigation group in the specified direction, or null if none
+     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
      *         can be found
      */
-    View keyboardNavigationGroupSearch(
-            @KeyboardNavigationGroupType int groupType, View currentGroup, int direction);
+    View keyboardNavigationClusterSearch(View currentCluster, int direction);
 
     /**
      * Change the z order of the child so it's on top of all other children.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c0f2c37..3cbe82e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -16,8 +16,6 @@
 
 package android.view;
 
-import static android.view.View.KEYBOARD_NAVIGATION_GROUP_CLUSTER;
-import static android.view.View.KEYBOARD_NAVIGATION_GROUP_SECTION;
 import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
 import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
@@ -73,7 +71,6 @@
 import android.util.TypedValue;
 import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
-import android.view.View.KeyboardNavigationGroupType;
 import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -4397,14 +4394,13 @@
             return false;
         }
 
-        private boolean performKeyboardGroupNavigation(
-                @KeyboardNavigationGroupType int groupType, int direction) {
+        private boolean performKeyboardGroupNavigation(int direction) {
             final View focused = mView.findFocus();
-            final View group = focused != null
-                    ? focused.keyboardNavigationGroupSearch(groupType, null, direction)
-                    : keyboardNavigationGroupSearch(groupType, null, direction);
+            final View cluster = focused != null
+                    ? focused.keyboardNavigationClusterSearch(null, direction)
+                    : keyboardNavigationClusterSearch(null, direction);
 
-            if (group != null && group.restoreDefaultFocus(View.FOCUS_DOWN)) {
+            if (cluster != null && cluster.restoreDefaultFocus(View.FOCUS_DOWN)) {
                 return true;
             }
 
@@ -4424,32 +4420,15 @@
             }
 
             int groupNavigationDirection = 0;
-            @KeyboardNavigationGroupType int groupType = 0;
 
             if (event.getAction() == KeyEvent.ACTION_DOWN && event.isCtrlPressed()) {
                 final int character =
                         event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_CTRL_MASK);
                 if (character == '+') {
-                    groupType = KEYBOARD_NAVIGATION_GROUP_CLUSTER;
                     groupNavigationDirection = View.FOCUS_FORWARD;
                 }
 
                 if (character == '_') {
-                    groupType = KEYBOARD_NAVIGATION_GROUP_CLUSTER;
-                    groupNavigationDirection = View.FOCUS_BACKWARD;
-                }
-            }
-
-            if (event.getAction() == KeyEvent.ACTION_DOWN && event.isAltPressed()) {
-                final int character =
-                        event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_ALT_MASK);
-                if (character == '+') {
-                    groupType = KEYBOARD_NAVIGATION_GROUP_SECTION;
-                    groupNavigationDirection = View.FOCUS_FORWARD;
-                }
-
-                if (character == '_') {
-                    groupType = KEYBOARD_NAVIGATION_GROUP_SECTION;
                     groupNavigationDirection = View.FOCUS_BACKWARD;
                 }
             }
@@ -4479,7 +4458,7 @@
             // Handle automatic focus changes.
             if (event.getAction() == KeyEvent.ACTION_DOWN) {
                 if (groupNavigationDirection != 0) {
-                    if (performKeyboardGroupNavigation(groupType, groupNavigationDirection)) {
+                    if (performKeyboardGroupNavigation(groupNavigationDirection)) {
                         return FINISH_HANDLED;
                     }
                 } else {
@@ -5910,11 +5889,10 @@
      * {@inheritDoc}
      */
     @Override
-    public View keyboardNavigationGroupSearch(
-            @KeyboardNavigationGroupType int groupType, View currentGroup, int direction) {
+    public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
         checkThread();
-        return FocusFinder.getInstance().findNextKeyboardNavigationGroup(groupType,
-                mView, currentGroup, direction);
+        return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
+                mView, currentCluster, direction);
     }
 
     public void debug() {
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 716997f..c08cd72 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -1080,22 +1080,6 @@
             return enabledSubtypes;
         }
 
-        // At the initial boot, the settings for input methods are not set,
-        // so we need to enable IME in that case.
-        public void enableAllIMEsIfThereIsNoEnabledIME() {
-            if (TextUtils.isEmpty(getEnabledInputMethodsStr())) {
-                StringBuilder sb = new StringBuilder();
-                final int N = mMethodList.size();
-                for (int i = 0; i < N; i++) {
-                    InputMethodInfo imi = mMethodList.get(i);
-                    Slog.i(TAG, "Adding: " + imi.getId());
-                    if (i > 0) sb.append(':');
-                    sb.append(imi.getId());
-                }
-                putEnabledInputMethodsStr(sb.toString());
-            }
-        }
-
         public List<Pair<String, ArrayList<String>>> getEnabledInputMethodsAndSubtypeListLocked() {
             return buildInputMethodsAndSubtypeList(getEnabledInputMethodsStr(),
                     mInputMethodSplitter,
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index a29882b4..ece5540 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1314,7 +1314,7 @@
     }
 
     private boolean isDoNotAskCredentialsOnBootSet() {
-        return mDevicePolicyManager.getDoNotAskCredentialsOnBoot();
+        return getDevicePolicyManager().getDoNotAskCredentialsOnBoot();
     }
 
     private boolean shouldEncryptWithCredentials(boolean defaultValue) {
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 9ce5670..c49287c 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -63,97 +63,87 @@
     get_canvas(canvasHandle)->setBitmap(bitmap);
 }
 
-static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
+static jboolean isOpaque(jlong canvasHandle) {
     return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
 }
 
-static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
+static jint getWidth(jlong canvasHandle) {
     return static_cast<jint>(get_canvas(canvasHandle)->width());
 }
 
-static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
+static jint getHeight(jlong canvasHandle) {
     return static_cast<jint>(get_canvas(canvasHandle)->height());
 }
 
-static void setHighContrastText(JNIEnv*, jobject, jlong canvasHandle, jboolean highContrastText) {
+static void setHighContrastText(jlong canvasHandle, jboolean highContrastText) {
     Canvas* canvas = get_canvas(canvasHandle);
     canvas->setHighContrastText(highContrastText);
 }
 
-static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
-    return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
-}
-
-static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
+static jint save(jlong canvasHandle, jint flagsHandle) {
     SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
     return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
 }
 
-static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
+static jint saveLayer(jlong canvasHandle, jfloat l, jfloat t,
                       jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
     Paint* paint  = reinterpret_cast<Paint*>(paintHandle);
     SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
     return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
 }
 
-static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
+static jint saveLayerAlpha(jlong canvasHandle, jfloat l, jfloat t,
                            jfloat r, jfloat b, jint alpha, jint flagsHandle) {
     SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle);
     return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
 }
 
-static void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) {
+static bool restore(jlong canvasHandle) {
     Canvas* canvas = get_canvas(canvasHandle);
-    if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
-        if (throwOnUnderflow) {
-            doThrowISE(env, "Underflow in restore - more restores than saves");
-        }
-        return; // compat behavior - return without throwing
+    if (canvas->getSaveCount() <= 1) {
+        return false; // cannot restore anymore
     }
     canvas->restore();
+    return true; // success
 }
 
-static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount,
-        jboolean throwOnUnderflow) {
+static void restoreToCount(jlong canvasHandle, jint saveCount) {
     Canvas* canvas = get_canvas(canvasHandle);
-    if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
-        if (throwOnUnderflow) {
-            doThrowIAE(env, "Underflow in restoreToCount - more restores than saves");
-            return;
-        }
-        restoreCount = 1; // compat behavior - restore as far as possible
-    }
-    canvas->restoreToCount(restoreCount);
+    canvas->restoreToCount(saveCount);
 }
 
-static void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
+static jint getSaveCount(jlong canvasHandle) {
+    return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
+}
+
+static void getMatrix(jlong canvasHandle, jlong matrixHandle) {
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
     get_canvas(canvasHandle)->getMatrix(matrix);
 }
 
-static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
+static void setMatrix(jlong canvasHandle, jlong matrixHandle) {
     const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
     get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
 }
 
-static void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
+static void concat(jlong canvasHandle, jlong matrixHandle) {
     const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
     get_canvas(canvasHandle)->concat(*matrix);
 }
 
-static void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
+static void rotate(jlong canvasHandle, jfloat degrees) {
     get_canvas(canvasHandle)->rotate(degrees);
 }
 
-static void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
+static void scale(jlong canvasHandle, jfloat sx, jfloat sy) {
     get_canvas(canvasHandle)->scale(sx, sy);
 }
 
-static void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
+static void skew(jlong canvasHandle, jfloat sx, jfloat sy) {
     get_canvas(canvasHandle)->skew(sx, sy);
 }
 
-static void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
+static void translate(jlong canvasHandle, jfloat dx, jfloat dy) {
     get_canvas(canvasHandle)->translate(dx, dy);
 }
 
@@ -171,13 +161,13 @@
     return result ? JNI_TRUE : JNI_FALSE;
 }
 
-static jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
+static jboolean quickRejectRect(jlong canvasHandle,
                                 jfloat left, jfloat top, jfloat right, jfloat bottom) {
     bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
     return result ? JNI_TRUE : JNI_FALSE;
 }
 
-static jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
+static jboolean quickRejectPath(jlong canvasHandle, jlong pathHandle) {
     SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
     bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
     return result ? JNI_TRUE : JNI_FALSE;
@@ -205,14 +195,14 @@
     return static_cast<SkClipOp>(rgnOp);
 }
 
-static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
+static jboolean clipRect(jlong canvasHandle, jfloat l, jfloat t,
                          jfloat r, jfloat b, jint opHandle) {
     bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b,
             opHandleToClipOp(opHandle));
     return nonEmptyClip ? JNI_TRUE : JNI_FALSE;
 }
 
-static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
+static jboolean clipPath(jlong canvasHandle, jlong pathHandle,
                          jint opHandle) {
     SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
     bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, opHandleToClipOp(opHandle));
@@ -565,7 +555,7 @@
     env->ReleaseStringChars(text, jchars);
 }
 
-static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
+static void setDrawFilter(jlong canvasHandle, jlong filterHandle) {
     get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
 }
 
@@ -587,6 +577,9 @@
 
     // ------------ @FastNative ----------------
     {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
+    {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
+
+    // ------------ @CriticalNative ----------------
     {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
     {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},
     {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight},
@@ -595,16 +588,15 @@
     {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
     {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
     {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
-    {"nRestore","(JZ)V", (void*) CanvasJNI::restore},
-    {"nRestoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
-    {"nGetCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
+    {"nRestore","(J)Z", (void*) CanvasJNI::restore},
+    {"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
+    {"nGetMatrix", "(JJ)V", (void*)CanvasJNI::getMatrix},
     {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
     {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
     {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
     {"nScale","(JFF)V", (void*) CanvasJNI::scale},
     {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
     {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
-    {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
     {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
     {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
     {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 87c2b25..df7a5f5 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2896,9 +2896,7 @@
              See {@link android.view.View#setKeyboardNavigationCluster(boolean)}. -->
         <attr name="keyboardNavigationCluster" format="boolean" />
 
-        <!-- Whether this view is a root of a keyboard navigation section.
-             See {@link android.view.View#setKeyboardNavigationSection(boolean)}. -->
-        <attr name="keyboardNavigationSection" format="boolean" />
+        <attr name="__removed0" format="boolean" />
 
         <!-- Defines the next keyboard navigation cluster.
 
@@ -2907,12 +2905,7 @@
              will result when the reference is accessed.-->
         <attr name="nextClusterForward" format="reference"/>
 
-        <!-- Defines the next keyboard navigation section.
-
-             If the reference refers to a view that does not exist or is part
-             of a hierarchy that is invisible, a {@link java.lang.RuntimeException}
-             will result when the reference is accessed.-->
-        <attr name="nextSectionForward" format="reference"/>
+        <attr name="__removed1" format="reference"/>
 
         <!-- Whether this view is a default-focus view.
              Only one view per keyboard navigation cluster can have this attribute set to true.
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 060c59e..40d0e45 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2777,9 +2777,9 @@
         <public name="paddingVertical" />
         <public name="visibleToInstantApps" />
         <public name="keyboardNavigationCluster" />
-        <public name="keyboardNavigationSection" />
+        <public name="__removed0" />
         <public name="nextClusterForward" />
-        <public name="nextSectionForward" />
+        <public name="__removed1" />
         <public name="textColorError" />
         <public name="focusedByDefault" />
         <public name="appCategory" />
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index cc5cc7b..8572345 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -21,11 +21,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
-import android.text.GraphicsOperations;
-import android.text.SpannableString;
-import android.text.SpannedString;
-import android.text.TextUtils;
 
+import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 
 import libcore.util.NativeAllocationRegistry;
@@ -501,8 +498,10 @@
      * an error to call restore() more times than save() was called.
      */
     public void restore() {
-        boolean throwOnUnderflow = !sCompatibilityRestore || !isHardwareAccelerated();
-        nRestore(mNativeCanvasWrapper, throwOnUnderflow);
+        if (!nRestore(mNativeCanvasWrapper)
+                && (!sCompatibilityRestore || !isHardwareAccelerated())) {
+            throw new IllegalStateException("Underflow in restore - more restores than saves");
+        }
     }
 
     /**
@@ -527,8 +526,16 @@
      * @param saveCount The save level to restore to.
      */
     public void restoreToCount(int saveCount) {
-        boolean throwOnUnderflow = !sCompatibilityRestore || !isHardwareAccelerated();
-        nRestoreToCount(mNativeCanvasWrapper, saveCount, throwOnUnderflow);
+        if (saveCount < 1) {
+            if (!sCompatibilityRestore || !isHardwareAccelerated()) {
+                // do nothing and throw without restoring
+                throw new IllegalArgumentException(
+                        "Underflow in restoreToCount - more restores than saves");
+            }
+            // compat behavior - restore as far as possible
+            saveCount = 1;
+        }
+        nRestoreToCount(mNativeCanvasWrapper, saveCount);
     }
 
     /**
@@ -643,7 +650,7 @@
      */
     @Deprecated
     public void getMatrix(@NonNull Matrix ctm) {
-        nGetCTM(mNativeCanvasWrapper, ctm.native_instance);
+        nGetMatrix(mNativeCanvasWrapper, ctm.native_instance);
     }
 
     /**
@@ -1059,79 +1066,66 @@
     // ---------------- @FastNative -------------------
 
     @FastNative
-    private static native void nSetBitmap(long canvasHandle,
-                                                Bitmap bitmap);
+    private static native void nSetBitmap(long canvasHandle, Bitmap bitmap);
+
     @FastNative
+    private static native boolean nGetClipBounds(long nativeCanvas, Rect bounds);
+
+    // ---------------- @CriticalNative -------------------
+
+    @CriticalNative
     private static native boolean nIsOpaque(long canvasHandle);
-    @FastNative
+    @CriticalNative
     private static native void nSetHighContrastText(long renderer, boolean highContrastText);
-    @FastNative
+    @CriticalNative
     private static native int nGetWidth(long canvasHandle);
-    @FastNative
+    @CriticalNative
     private static native int nGetHeight(long canvasHandle);
 
-    @FastNative
+    @CriticalNative
     private static native int nSave(long canvasHandle, int saveFlags);
-    @FastNative
-    private static native int nSaveLayer(long nativeCanvas, float l,
-                                               float t, float r, float b,
-                                               long nativePaint,
-                                               int layerFlags);
-    @FastNative
-    private static native int nSaveLayerAlpha(long nativeCanvas, float l,
-                                                    float t, float r, float b,
-                                                    int alpha, int layerFlags);
-    @FastNative
-    private static native void nRestore(long canvasHandle, boolean tolerateUnderflow);
-    @FastNative
-    private static native void nRestoreToCount(long canvasHandle,
-                                                     int saveCount,
-                                                     boolean tolerateUnderflow);
-    @FastNative
+    @CriticalNative
+    private static native int nSaveLayer(long nativeCanvas, float l, float t, float r, float b,
+            long nativePaint, int layerFlags);
+    @CriticalNative
+    private static native int nSaveLayerAlpha(long nativeCanvas, float l, float t, float r, float b,
+            int alpha, int layerFlags);
+    @CriticalNative
+    private static native boolean nRestore(long canvasHandle);
+    @CriticalNative
+    private static native void nRestoreToCount(long canvasHandle, int saveCount);
+    @CriticalNative
     private static native int nGetSaveCount(long canvasHandle);
 
-    @FastNative
-    private static native void nTranslate(long canvasHandle,
-                                                float dx, float dy);
-    @FastNative
-    private static native void nScale(long canvasHandle,
-                                            float sx, float sy);
-    @FastNative
+    @CriticalNative
+    private static native void nTranslate(long canvasHandle, float dx, float dy);
+    @CriticalNative
+    private static native void nScale(long canvasHandle, float sx, float sy);
+    @CriticalNative
     private static native void nRotate(long canvasHandle, float degrees);
-    @FastNative
-    private static native void nSkew(long canvasHandle,
-                                           float sx, float sy);
-    @FastNative
-    private static native void nConcat(long nativeCanvas,
-                                             long nativeMatrix);
-    @FastNative
-    private static native void nSetMatrix(long nativeCanvas,
-                                                long nativeMatrix);
-    @FastNative
+    @CriticalNative
+    private static native void nSkew(long canvasHandle, float sx, float sy);
+    @CriticalNative
+    private static native void nConcat(long nativeCanvas, long nativeMatrix);
+    @CriticalNative
+    private static native void nSetMatrix(long nativeCanvas, long nativeMatrix);
+    @CriticalNative
     private static native boolean nClipRect(long nativeCanvas,
-                                                  float left, float top,
-                                                  float right, float bottom,
-                                                  int regionOp);
-    @FastNative
-    private static native boolean nClipPath(long nativeCanvas,
-                                                  long nativePath,
-                                                  int regionOp);
-    @FastNative
-    private static native void nSetDrawFilter(long nativeCanvas,
-                                                   long nativeFilter);
-    @FastNative
-    private static native boolean nGetClipBounds(long nativeCanvas,
-                                                       Rect bounds);
-    @FastNative
-    private static native void nGetCTM(long nativeCanvas,
-                                             long nativeMatrix);
-    @FastNative
-    private static native boolean nQuickReject(long nativeCanvas,
-                                                     long nativePath);
-    @FastNative
-    private static native boolean nQuickReject(long nativeCanvas,
-                                                     float left, float top,
-                                                     float right, float bottom);
+            float left, float top, float right, float bottom, int regionOp);
+    @CriticalNative
+    private static native boolean nClipPath(long nativeCanvas, long nativePath, int regionOp);
+    @CriticalNative
+    private static native void nSetDrawFilter(long nativeCanvas, long nativeFilter);
+    @CriticalNative
+    private static native void nGetMatrix(long nativeCanvas, long nativeMatrix);
+    @CriticalNative
+    private static native boolean nQuickReject(long nativeCanvas, long nativePath);
+    @CriticalNative
+    private static native boolean nQuickReject(long nativeCanvas, float left, float top,
+            float right, float bottom);
+
+
+    // ---------------- Draw Methods -------------------
 
     /**
      * <p>
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 6f3ed9c..5a2791c 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -311,13 +311,32 @@
         TestUtils::syncHierarchyPropertiesAndDisplayList(node);
     }
 
-    FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600,
-            sLightGeometry, Caches::getInstance());
-    frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds);
+    {
+        FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600,
+                sLightGeometry, Caches::getInstance());
+        frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds);
 
-    DeferRenderNodeSceneTestRenderer renderer;
-    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
-    EXPECT_EQ(4, renderer.getIndex());
+        DeferRenderNodeSceneTestRenderer renderer;
+        frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+        EXPECT_EQ(4, renderer.getIndex());
+    }
+
+    for (auto& node : nodes) {
+        EXPECT_FALSE(node->nothingToDraw());
+        node->setStagingDisplayList(nullptr, nullptr);
+        node->destroyHardwareResources(nullptr);
+        EXPECT_TRUE(node->nothingToDraw());
+    }
+
+    {
+        // Validate no crashes if any nodes are missing DisplayLists
+        FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600,
+                sLightGeometry, Caches::getInstance());
+        frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds);
+
+        FailRenderer renderer;
+        frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+    }
 }
 
 RENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, empty_noFbo0) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index fede34d..f72d091 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -131,6 +131,9 @@
     <!-- Assist -->
     <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
 
+    <!-- Doze mode temp whitelisting for notification dispatching. -->
+    <uses-permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST" />
+
     <!-- Listen for keyboard attachment / detachment -->
     <uses-permission android:name="android.permission.TABLET_MODE" />
 
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginFragment.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginFragment.java
index a9d1fa9..152dbc5 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginFragment.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginFragment.java
@@ -14,17 +14,13 @@
 
 package com.android.systemui.plugins;
 
-import android.annotation.Nullable;
 import android.app.Fragment;
 import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 
 public abstract class PluginFragment extends Fragment implements Plugin {
 
-    private static final String KEY_PLUGIN_PACKAGE = "plugin_package_name";
     private Context mPluginContext;
 
     @Override
@@ -33,45 +29,17 @@
     }
 
     @Override
-    public void onCreate(@Nullable Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        if (savedInstanceState != null) {
-            Context sysuiContext = getContext();
-            Context pluginContext = recreatePluginContext(sysuiContext, savedInstanceState);
-            onCreate(sysuiContext, pluginContext);
-        }
-        if (mPluginContext == null) {
-            throw new RuntimeException("PluginFragments must call super.onCreate("
-                    + "Context sysuiContext, Context pluginContext)");
-        }
+    public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
+        return super.getLayoutInflater(savedInstanceState).cloneInContext(getContext());
     }
 
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        outState.putString(KEY_PLUGIN_PACKAGE, getContext().getPackageName());
     }
 
-    private Context recreatePluginContext(Context sysuiContext, Bundle savedInstanceState) {
-        final String pkg = savedInstanceState.getString(KEY_PLUGIN_PACKAGE);
-        try {
-            ApplicationInfo appInfo = sysuiContext.getPackageManager().getApplicationInfo(pkg, 0);
-            return PluginManager.getInstance(sysuiContext).getContext(appInfo, pkg);
-        } catch (NameNotFoundException e) {
-            throw new RuntimeException("Plugin with invalid package? " + pkg, e);
-        }
-    }
-
-    @Override
-    public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
-        return super.getLayoutInflater(savedInstanceState).cloneInContext(mPluginContext);
-    }
-
-    /**
-     * Should only be called after {@link Plugin#onCreate(Context, Context)}.
-     */
     @Override
     public Context getContext() {
-        return mPluginContext != null ? mPluginContext : super.getContext();
+        return mPluginContext;
     }
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
index 47b97bd..9f44bd4 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -177,8 +177,12 @@
                     if (DEBUG) Log.d(TAG, "onPluginConnected");
                     PluginPrefs.setHasPlugins(mContext);
                     PluginInfo<T> info = (PluginInfo<T>) msg.obj;
-                    info.mPlugin.onCreate(mContext, info.mPluginContext);
-                    mListener.onPluginConnected(info.mPlugin);
+                    if (!(msg.obj instanceof PluginFragment)) {
+                        // Only call onDestroy for plugins that aren't fragments, as fragments
+                        // will get the onCreate as part of the fragment lifecycle.
+                        info.mPlugin.onCreate(mContext, info.mPluginContext);
+                    }
+                    mListener.onPluginConnected(info.mPlugin, info.mPluginContext);
                     break;
                 case PLUGIN_DISCONNECTED:
                     if (DEBUG) Log.d(TAG, "onPluginDisconnected");
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginListener.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginListener.java
index b2f92d6..b488d2a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginListener.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginListener.java
@@ -14,6 +14,8 @@
 
 package com.android.systemui.plugins;
 
+import android.content.Context;
+
 /**
  * Interface for listening to plugins being connected.
  */
@@ -24,7 +26,7 @@
      * It may also be called in the future if the plugin package changes
      * and needs to be reloaded.
      */
-    void onPluginConnected(T plugin);
+    void onPluginConnected(T plugin, Context pluginContext);
 
     /**
      * Called when a plugin has been uninstalled/updated and should be removed
diff --git a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
index efa7cae..efddf20 100644
--- a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
@@ -98,7 +98,7 @@
     }
 
     @Override
-    public void onPluginConnected(ViewProvider plugin) {
+    public void onPluginConnected(ViewProvider plugin, Context context) {
         mPluginView = plugin.getView();
         inflateLayout();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index f83a5d3..f2aaec1 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -207,7 +207,7 @@
         PluginManager.getInstance(this).addPluginListener(OverlayPlugin.ACTION,
                 new PluginListener<OverlayPlugin>() {
             @Override
-            public void onPluginConnected(OverlayPlugin plugin) {
+            public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
                 PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
                 if (phoneStatusBar != null) {
                     plugin.setup(phoneStatusBar.getStatusBarWindow(),
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 57857cc..50506a9 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -27,11 +27,13 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcelable;
+import android.util.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
 
 import com.android.settingslib.applications.InterestingConfigChanges;
 import com.android.systemui.SystemUIApplication;
+import com.android.systemui.plugins.Plugin;
 import com.android.systemui.plugins.PluginManager;
 
 import java.io.FileDescriptor;
@@ -47,6 +49,7 @@
     private final View mRootView;
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges();
     private final FragmentService mManager;
+    private final PluginFragmentManager mPlugins = new PluginFragmentManager();
 
     private FragmentController mFragments;
     private FragmentLifecycleCallbacks mLifecycleCallbacks;
@@ -163,6 +166,10 @@
         return mFragments.getFragmentManager();
     }
 
+    PluginFragmentManager getPluginManager() {
+        return mPlugins;
+    }
+
     public interface FragmentListener {
         void onFragmentViewCreated(String tag, Fragment fragment);
 
@@ -198,6 +205,11 @@
         }
 
         @Override
+        public Fragment instantiate(Context context, String className, Bundle arguments) {
+            return mPlugins.instantiate(context, className, arguments);
+        }
+
+        @Override
         public boolean onShouldSaveFragmentState(Fragment fragment) {
             return true; // True for now.
         }
@@ -237,4 +249,57 @@
             return true;
         }
     }
+
+    class PluginFragmentManager {
+        private final ArrayMap<String, Context> mPluginLookup = new ArrayMap<>();
+
+        public void removePlugin(String tag, String currentClass, String defaultClass) {
+            Fragment fragment = getFragmentManager().findFragmentByTag(tag);
+            mPluginLookup.remove(currentClass);
+            getFragmentManager().beginTransaction()
+                    .replace(((View) fragment.getView().getParent()).getId(),
+                            instantiate(mContext, defaultClass, null), tag)
+                    .commit();
+            reloadFragments();
+        }
+
+        public void setCurrentPlugin(String tag, String currentClass, Context context) {
+            Fragment fragment = getFragmentManager().findFragmentByTag(tag);
+            mPluginLookup.put(currentClass, context);
+            getFragmentManager().beginTransaction()
+                    .replace(((View) fragment.getView().getParent()).getId(),
+                            instantiate(context, currentClass, null), tag)
+                    .commit();
+            reloadFragments();
+        }
+
+        private void reloadFragments() {
+            // Save the old state.
+            Parcelable p = destroyFragmentHost();
+            // Generate a new fragment host and restore its state.
+            createFragmentHost(p);
+        }
+
+        Fragment instantiate(Context context, String className, Bundle arguments) {
+            Context pluginContext = mPluginLookup.get(className);
+            if (pluginContext != null) {
+                Fragment f = Fragment.instantiate(pluginContext, className, arguments);
+                if (f instanceof Plugin) {
+                    ((Plugin) f).onCreate(mContext, pluginContext);
+                }
+                return f;
+            }
+            return Fragment.instantiate(context, className, arguments);
+        }
+    }
+
+    private static class PluginState {
+        Context mContext;
+        String mCls;
+
+        private PluginState(String cls, Context context) {
+            mCls = cls;
+            mContext = context;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/PluginFragmentListener.java b/packages/SystemUI/src/com/android/systemui/fragments/PluginFragmentListener.java
index e107fcd..2e6de4a 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/PluginFragmentListener.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/PluginFragmentListener.java
@@ -15,6 +15,7 @@
 package com.android.systemui.fragments;
 
 import android.app.Fragment;
+import android.content.Context;
 import android.util.Log;
 import android.view.View;
 
@@ -30,27 +31,19 @@
     private final FragmentHostManager mFragmentHostManager;
     private final PluginManager mPluginManager;
     private final Class<? extends Fragment> mDefaultClass;
-    private final int mId;
-    private final String mTag;
     private final Class<? extends FragmentBase> mExpectedInterface;
+    private final String mTag;
 
-    public PluginFragmentListener(View view, String tag, int id,
-            Class<? extends Fragment> defaultFragment,
+    public PluginFragmentListener(View view, String tag, Class<? extends Fragment> defaultFragment,
             Class<? extends FragmentBase> expectedInterface) {
+        mTag = tag;
         mFragmentHostManager = FragmentHostManager.get(view);
         mPluginManager = PluginManager.getInstance(view.getContext());
         mExpectedInterface = expectedInterface;
-        mTag = tag;
         mDefaultClass = defaultFragment;
-        mId = id;
     }
 
     public void startListening(String action, int version) {
-        try {
-            setFragment(mDefaultClass.newInstance());
-        } catch (InstantiationException | IllegalAccessException e) {
-            Log.e(TAG, "Couldn't instantiate " + mDefaultClass.getName(), e);
-        }
         mPluginManager.addPluginListener(action, this, version, false /* Only allow one */);
     }
 
@@ -58,17 +51,13 @@
         mPluginManager.removePluginListener(this);
     }
 
-    private void setFragment(Fragment fragment) {
-        mFragmentHostManager.getFragmentManager().beginTransaction()
-                .replace(mId, fragment, mTag)
-                .commit();
-    }
-
     @Override
-    public void onPluginConnected(Plugin plugin) {
+    public void onPluginConnected(Plugin plugin, Context pluginContext) {
         try {
             mExpectedInterface.cast(plugin);
-            setFragment((Fragment) plugin);
+            Fragment.class.cast(plugin);
+            mFragmentHostManager.getPluginManager().setCurrentPlugin(mTag,
+                    plugin.getClass().getName(), pluginContext);
         } catch (ClassCastException e) {
             Log.e(TAG, plugin.getClass().getName() + " must be a Fragment and implement "
                     + mExpectedInterface.getName(), e);
@@ -77,10 +66,7 @@
 
     @Override
     public void onPluginDisconnected(Plugin plugin) {
-        try {
-            setFragment(mDefaultClass.newInstance());
-        } catch (InstantiationException | IllegalAccessException e) {
-            Log.e(TAG, "Couldn't instantiate " + mDefaultClass.getName(), e);
-        }
+        mFragmentHostManager.getPluginManager().removePlugin(mTag,
+                plugin.getClass().getName(), mDefaultClass.getName());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 93f72a8..f24e40b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -72,6 +72,7 @@
         SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
         registerPackageChangeReceivers();
 
+        createBatteryController();
         mCarBatteryController.startListening();
         mConnectedDeviceSignalController.startListening();
     }
@@ -113,8 +114,7 @@
         return statusBarView;
     }
 
-    @Override
-    protected BatteryController createBatteryController() {
+    private BatteryController createBatteryController() {
         mCarBatteryController = new CarBatteryController(mContext);
         mCarBatteryController.addBatteryViewHandler(this);
         return mCarBatteryController;
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 d326787..79120d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -779,7 +779,7 @@
     private final PluginListener<IntentButtonProvider> mRightListener =
             new PluginListener<IntentButtonProvider>() {
         @Override
-        public void onPluginConnected(IntentButtonProvider plugin) {
+        public void onPluginConnected(IntentButtonProvider plugin, Context pluginContext) {
             setRightButton(plugin.getIntentButton());
         }
 
@@ -792,7 +792,7 @@
     private final PluginListener<IntentButtonProvider> mLeftListener =
             new PluginListener<IntentButtonProvider>() {
         @Override
-        public void onPluginConnected(IntentButtonProvider plugin) {
+        public void onPluginConnected(IntentButtonProvider plugin, Context pluginContext) {
             setLeftButton(plugin.getIntentButton());
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index b6feb0e..f04a9ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -365,7 +365,7 @@
     }
 
     @Override
-    public void onPluginConnected(NavBarButtonProvider plugin) {
+    public void onPluginConnected(NavBarButtonProvider plugin, Context context) {
         mPlugins.add(plugin);
         clearViews();
         inflateLayout(mCurrentLayout);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 31c78c8..319f124 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -765,7 +765,7 @@
     }
 
     @Override
-    public void onPluginConnected(NavGesture plugin) {
+    public void onPluginConnected(NavGesture plugin, Context context) {
         mGestureHelper = plugin.getGestureHelper();
         updateTaskSwitchHelper();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index cb9fbb9..3291d59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -870,7 +870,10 @@
         View container = mStatusBarWindow.findViewById(R.id.qs_frame);
         if (container != null) {
             FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
-            new PluginFragmentListener(container, QS.TAG, R.id.qs_frame, QSFragment.class, QS.class)
+            fragmentHostManager.getFragmentManager().beginTransaction()
+                    .replace(R.id.qs_frame, new QSFragment(), QS.TAG)
+                    .commit();
+            new PluginFragmentListener(container, QS.TAG, QSFragment.class, QS.class)
                     .startListening(QS.ACTION, QS.VERSION);
             final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
                     mIconController);
@@ -986,10 +989,6 @@
         }
     }
 
-    protected BatteryController createBatteryController() {
-        return new BatteryControllerImpl(mContext);
-    }
-
     private void inflateShelf() {
         mNotificationShelf =
                 (NotificationShelf) LayoutInflater.from(mContext).inflate(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
index d529ee1..3715df2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java
@@ -113,8 +113,7 @@
         waitForIdleSync(mPluginInstanceManager.mPluginHandler);
         waitForIdleSync(mPluginInstanceManager.mMainHandler);
 
-        verify(mMockListener, Mockito.never()).onPluginConnected(
-                ArgumentCaptor.forClass(Plugin.class).capture());
+        verify(mMockListener, Mockito.never()).onPluginConnected(any(), any());
     }
 
     @Test
@@ -124,7 +123,7 @@
         // Verify startup lifecycle
         verify(sMockPlugin).onCreate(ArgumentCaptor.forClass(Context.class).capture(),
                 ArgumentCaptor.forClass(Context.class).capture());
-        verify(mMockListener).onPluginConnected(ArgumentCaptor.forClass(Plugin.class).capture());
+        verify(mMockListener).onPluginConnected(any(), any());
     }
 
     @Test
@@ -154,8 +153,7 @@
         waitForIdleSync(mPluginInstanceManager.mMainHandler);
 
         // Plugin shouldn't be connected because it is the wrong version.
-        verify(mMockListener, Mockito.never()).onPluginConnected(
-                ArgumentCaptor.forClass(Plugin.class).capture());
+        verify(mMockListener, Mockito.never()).onPluginConnected(any(), any());
         verify(nm).notifyAsUser(eq(TestPlugin.class.getName()), eq(SystemMessage.NOTE_PLUGIN),
                 any(), eq(UserHandle.ALL));
     }
@@ -176,8 +174,7 @@
         verify(sMockPlugin, Mockito.times(2)).onCreate(
                 ArgumentCaptor.forClass(Context.class).capture(),
                 ArgumentCaptor.forClass(Context.class).capture());
-        verify(mMockListener, Mockito.times(2)).onPluginConnected(
-                ArgumentCaptor.forClass(Plugin.class).capture());
+        verify(mMockListener, Mockito.times(2)).onPluginConnected(any(), any());
     }
 
     @Test
@@ -193,8 +190,7 @@
         waitForIdleSync(mPluginInstanceManager.mMainHandler);;
 
         // Non-debuggable build should receive no plugins.
-        verify(mMockListener, Mockito.never()).onPluginConnected(
-                ArgumentCaptor.forClass(Plugin.class).capture());
+        verify(mMockListener, Mockito.never()).onPluginConnected(any(), any());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarTest.java
new file mode 100644
index 0000000..d82566f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.BaseStatusBar;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PhoneStatusBarTest extends SysuiTestCase {
+
+    StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    PhoneStatusBar mPhoneStatusBar;
+
+    @Before
+    public void setup() {
+        mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class);
+        mPhoneStatusBar = new TestablePhoneStatusBar(mStatusBarKeyguardViewManager);
+
+        doAnswer(invocation -> {
+            OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
+            onDismissAction.onDismiss();
+            return null;
+        }).when(mStatusBarKeyguardViewManager).dismissWithAction(any(), any(), anyBoolean());
+
+        doAnswer(invocation -> {
+            Runnable runnable = (Runnable) invocation.getArguments()[0];
+            runnable.run();
+            return null;
+        }).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
+    }
+
+    @Test
+    public void executeRunnableDismissingKeyguard_nullRunnable_showingAndOccluded() {
+        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
+        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(true);
+
+        mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
+    }
+
+    @Test
+    public void executeRunnableDismissingKeyguard_nullRunnable_showing() {
+        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
+        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
+
+        mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
+    }
+
+    @Test
+    public void executeRunnableDismissingKeyguard_nullRunnable_notShowing() {
+        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
+        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
+
+        mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
+    }
+
+    static class TestablePhoneStatusBar extends PhoneStatusBar {
+        public TestablePhoneStatusBar(StatusBarKeyguardViewManager man) {
+            mStatusBarKeyguardViewManager = man;
+        }
+
+        @Override
+        protected BaseStatusBar.H createHandler() {
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 581aa05..0e07ec0 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -504,8 +504,8 @@
             for (int i = alarms.size()-1; i >= 0; i--) {
                 Alarm alarm = alarms.get(i);
                 try {
-                    if (alarm.uid == uid && ActivityManager.getService().getAppStartMode(
-                            uid, alarm.packageName) == ActivityManager.APP_START_MODE_DISABLED) {
+                    if (alarm.uid == uid && ActivityManager.getService().isAppStartModeDisabled(
+                            uid, alarm.packageName)) {
                         alarms.remove(i);
                         didRemove = true;
                         if (alarm.alarmClock != null) {
@@ -1089,8 +1089,7 @@
                 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
                 callingUid, callingPackage);
         try {
-            if (ActivityManager.getService().getAppStartMode(callingUid, callingPackage)
-                    == ActivityManager.APP_START_MODE_DISABLED) {
+            if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
                 Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
                         + " -- package not allowed to start");
                 return;
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index f718fa1..bee1f97 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -243,7 +243,6 @@
     private PendingIntent mImeSwitchPendingIntent;
     private boolean mShowOngoingImeSwitcherForPhones;
     private boolean mNotificationShown;
-    private final boolean mImeSelectedOnBoot;
 
     static class SessionState {
         final ClientState client;
@@ -566,7 +565,7 @@
         }
     }
 
-    class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
+    class ImmsBroadcastReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
@@ -587,6 +586,10 @@
                             Intent.EXTRA_SETTING_NEW_VALUE);
                     restoreEnabledInputMethods(mContext, prevValue, newValue);
                 }
+            } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
+                synchronized (mMethodMap) {
+                    resetStateIfCurrentLocaleChangedLocked();
+                }
             } else {
                 Slog.w(TAG, "Unexpected intent " + intent);
             }
@@ -845,9 +848,11 @@
                 return;
             }
             mSettings.switchCurrentUser(currentUserId, !mSystemReady);
-            // We need to rebuild IMEs.
-            buildInputMethodListLocked(false /* resetDefaultEnabledIme */);
-            updateInputMethodsFromSettingsLocked(true /* enabledChanged */);
+            if (mSystemReady) {
+                // We need to rebuild IMEs.
+                buildInputMethodListLocked(false /* resetDefaultEnabledIme */);
+                updateInputMethodsFromSettingsLocked(true /* enabledChanged */);
+            }
         }
     }
 
@@ -897,13 +902,6 @@
 
         mShowOngoingImeSwitcherForPhones = false;
 
-        final IntentFilter broadcastFilter = new IntentFilter();
-        broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
-        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
-        broadcastFilter.addAction(Intent.ACTION_SETTING_RESTORED);
-        mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
-
         mNotificationShown = false;
         int userId = 0;
         try {
@@ -911,7 +909,6 @@
         } catch (RemoteException e) {
             Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
         }
-        mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
 
         // mSettings should be created before buildInputMethodListLocked
         mSettings = new InputMethodSettings(
@@ -919,48 +916,8 @@
 
         updateCurrentProfileIds();
         mFileManager = new InputMethodFileManager(mMethodMap, userId);
-        synchronized (mMethodMap) {
-            mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
-                    mSettings, context);
-        }
-
-        // Just checking if defaultImiId is empty or not
-        final String defaultImiId = mSettings.getSelectedInputMethod();
-        if (DEBUG) {
-            Slog.d(TAG, "Initial default ime = " + defaultImiId);
-        }
-        mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
-
-        synchronized (mMethodMap) {
-            buildInputMethodListLocked(!mImeSelectedOnBoot /* resetDefaultEnabledIme */);
-        }
-        mSettings.enableAllIMEsIfThereIsNoEnabledIME();
-
-        if (!mImeSelectedOnBoot) {
-            Slog.w(TAG, "No IME selected. Choose the most applicable IME.");
-            synchronized (mMethodMap) {
-                resetDefaultImeLocked(context);
-            }
-        }
-
-        synchronized (mMethodMap) {
-            mSettingsObserver.registerContentObserverLocked(userId);
-            updateFromSettingsLocked(true);
-        }
-
-        // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
-        // according to the new system locale.
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
-        mContext.registerReceiver(
-                new BroadcastReceiver() {
-                    @Override
-                    public void onReceive(Context context, Intent intent) {
-                        synchronized(mMethodMap) {
-                            resetStateIfCurrentLocaleChangedLocked();
-                        }
-                    }
-                }, filter);
+        mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
+                mSettings, context);
     }
 
     private void resetDefaultImeLocked(Context context) {
@@ -1089,6 +1046,7 @@
             }
             if (!mSystemReady) {
                 mSystemReady = true;
+                mLastSystemLocales = mRes.getConfiguration().getLocales();
                 final int currentUserId = mSettings.getCurrentUserId();
                 mSettings.switchCurrentUser(currentUserId,
                         !mUserManager.isUserUnlockingOrUnlocked(currentUserId));
@@ -1105,14 +1063,25 @@
                     mWindowManagerInternal.setOnHardKeyboardStatusChangeListener(
                             mHardKeyboardListener);
                 }
-                if (!mImeSelectedOnBoot) {
-                    Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
-                    resetStateIfCurrentLocaleChangedLocked();
-                    InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
-                            mSettings.getEnabledInputMethodListLocked(),
-                            mSettings.getCurrentUserId(), mContext.getBasePackageName());
-                }
-                mLastSystemLocales = mRes.getConfiguration().getLocales();
+
+                mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
+                mSettingsObserver.registerContentObserverLocked(currentUserId);
+
+                final IntentFilter broadcastFilter = new IntentFilter();
+                broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+                broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
+                broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
+                broadcastFilter.addAction(Intent.ACTION_SETTING_RESTORED);
+                broadcastFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
+                mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
+
+                buildInputMethodListLocked(true /* resetDefaultEnabledIme */);
+                resetDefaultImeLocked(mContext);
+                updateFromSettingsLocked(true);
+                InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
+                        mSettings.getEnabledInputMethodListLocked(), currentUserId,
+                        mContext.getBasePackageName());
+
                 try {
                     startInputInnerLocked();
                 } catch (RuntimeException e) {
@@ -2624,6 +2593,9 @@
         // additional input method subtypes to the IME.
         if (TextUtils.isEmpty(imiId) || subtypes == null) return;
         synchronized (mMethodMap) {
+            if (!mSystemReady) {
+                return;
+            }
             final InputMethodInfo imi = mMethodMap.get(imiId);
             if (imi == null) return;
             final String[] packageInfos;
@@ -3048,6 +3020,10 @@
             Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
                     + " \n ------ caller=" + Debug.getCallers(10));
         }
+        if (!mSystemReady) {
+            Slog.e(TAG, "buildInputMethodListLocked is not allowed until system is ready");
+            return;
+        }
         mMethodList.clear();
         mMethodMap.clear();
 
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 94acd75..e11dd1a 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -33,6 +33,7 @@
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
+import android.app.usage.StorageStatsManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -3270,6 +3271,29 @@
         }
     }
 
+    @Override
+    public long getCacheQuotaBytes(String volumeUuid, int uid) {
+        if (uid != Binder.getCallingUid()) {
+            mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
+        }
+        // TODO: wire up to cache quota once merged
+        return 64 * TrafficStats.MB_IN_BYTES;
+    }
+
+    @Override
+    public long getCacheSizeBytes(String volumeUuid, int uid) {
+        if (uid != Binder.getCallingUid()) {
+            mContext.enforceCallingPermission(android.Manifest.permission.STORAGE_INTERNAL, TAG);
+        }
+        final long token = Binder.clearCallingIdentity();
+        try {
+            return mContext.getSystemService(StorageStatsManager.class)
+                    .queryStatsForUid(volumeUuid, uid).getCacheBytes();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     private void addObbStateLocked(ObbState obbState) throws RemoteException {
         final IBinder binder = obbState.getBinder();
         List<ObbState> obbStates = mObbMounts.get(binder);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 1bba7ec..5655dc5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -349,8 +349,8 @@
             try {
                 // Before going further -- if this app is not allowed to start services in the
                 // background, then at this point we aren't going to let it period.
-                final int allowed = mAm.checkAllowBackgroundLocked(
-                        r.appInfo.uid, r.packageName, callingPid, false);
+                final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
+                        r.appInfo.targetSdkVersion, callingPid, false, false);
                 if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                     Slog.w(TAG, "Background start not allowed: service "
                             + service + " to " + r.name.flattenToShortString()
@@ -607,8 +607,9 @@
             for (int i=services.mServicesByName.size()-1; i>=0; i--) {
                 ServiceRecord service = services.mServicesByName.valueAt(i);
                 if (service.appInfo.uid == uid && service.startRequested) {
-                    if (mAm.checkAllowBackgroundLocked(service.appInfo.uid, service.packageName,
-                            -1, false) != ActivityManager.APP_START_MODE_NORMAL) {
+                    if (mAm.getAppStartModeLocked(service.appInfo.uid, service.packageName,
+                            service.appInfo.targetSdkVersion, -1, false, false)
+                            != ActivityManager.APP_START_MODE_NORMAL) {
                         if (stopping == null) {
                             stopping = new ArrayList<>();
                             stopping.add(service);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8a0baad..a72950b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -22,6 +22,7 @@
 import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST;
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -4936,7 +4937,7 @@
     }
 
     @Override
-    public void crashApplication(int uid, int initialPid, String packageName,
+    public void crashApplication(int uid, int initialPid, String packageName, int userId,
             String message) {
         if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -4949,7 +4950,7 @@
         }
 
         synchronized(this) {
-            mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, message);
+            mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, message);
         }
     }
 
@@ -7284,18 +7285,23 @@
             Slog.d(TAG, "tempWhitelistAppForPowerSave(" + callerPid + ", " + callerUid + ", "
                     + targetUid + ", " + duration + ")");
         }
-        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");
+
+        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;
                 }
-                return;
+                if (!pr.whitelistManager) {
+                    if (DEBUG_WHITELISTS) {
+                        Slog.d(TAG, "tempWhitelistAppForPowerSave() for target " + targetUid
+                                + ": pid " + callerPid + " is not allowed");
+                    }
+                    return;
+                }
             }
         }
 
@@ -8020,65 +8026,42 @@
         return readMet && writeMet;
     }
 
-    public int getAppStartMode(int uid, String packageName) {
+    public boolean isAppStartModeDisabled(int uid, String packageName) {
         synchronized (this) {
-            return checkAllowBackgroundLocked(uid, packageName, -1, false);
+            return getAppStartModeLocked(uid, packageName, 0, -1, false, true)
+                    == ActivityManager.APP_START_MODE_DISABLED;
         }
     }
 
     // Unified app-op and target sdk check
-    int appRestrictedInBackgroundLocked(int uid, String packageName) {
-        if (packageName == null) {
-            packageName = mPackageManagerInt.getNameForUid(uid);
-            if (packageName == null) {
-                Slog.w(TAG, "No package known for uid " + uid);
-                return ActivityManager.APP_START_MODE_NORMAL;
-            }
-        }
-
-        // !!! TODO: cache the package/versionCode lookups to fast path this
-        ApplicationInfo app = getPackageManagerInternalLocked().getApplicationInfo(packageName,
-                UserHandle.getUserId(uid));
-        if (app != null) {
-            // Apps that target O+ are always subject to background check
-            if (mEnforceBackgroundCheck && app.targetSdkVersion >= Build.VERSION_CODES.O) {
-                if (DEBUG_BACKGROUND_CHECK) {
-                    Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
-                }
-                return ActivityManager.APP_START_MODE_DELAYED_RIGID;
-            }
-            // ...and legacy apps get an AppOp check
-            int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
-                    uid, packageName);
+    int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
+        // Apps that target O+ are always subject to background check
+        if (mEnforceBackgroundCheck && packageTargetSdk >= Build.VERSION_CODES.O) {
             if (DEBUG_BACKGROUND_CHECK) {
-                Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
+                Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
             }
-            switch (appop) {
-                case AppOpsManager.MODE_ALLOWED:
-                    return ActivityManager.APP_START_MODE_NORMAL;
-                case AppOpsManager.MODE_IGNORED:
-                    return ActivityManager.APP_START_MODE_DELAYED;
-                default:
-                    return ActivityManager.APP_START_MODE_DELAYED_RIGID;
-            }
-        } else {
-            Slog.w(TAG, "Unknown app " + packageName + " / " + uid);
+            return ActivityManager.APP_START_MODE_DELAYED_RIGID;
         }
-        return ActivityManager.APP_START_MODE_NORMAL;
+        // ...and legacy apps get an AppOp check
+        int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
+                uid, packageName);
+        if (DEBUG_BACKGROUND_CHECK) {
+            Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
+        }
+        switch (appop) {
+            case AppOpsManager.MODE_ALLOWED:
+                return ActivityManager.APP_START_MODE_NORMAL;
+            case AppOpsManager.MODE_IGNORED:
+                return ActivityManager.APP_START_MODE_DELAYED;
+            default:
+                return ActivityManager.APP_START_MODE_DELAYED_RIGID;
+        }
     }
 
     // Service launch is available to apps with run-in-background exemptions but
     // some other background operations are not.  If we're doing a check
     // of service-launch policy, allow those callers to proceed unrestricted.
-    int appServicesRestrictedInBackgroundLocked(int uid, String packageName) {
-        if (packageName == null) {
-            packageName = mPackageManagerInt.getNameForUid(uid);
-            if (packageName == null) {
-                Slog.w(TAG, "No package known for uid " + uid);
-                return ActivityManager.APP_START_MODE_NORMAL;
-            }
-        }
-
+    int appServicesRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
         // Persistent app?  NB: expects that persistent uids are always active.
         final UidRecord uidRec = mActiveUids.get(uid);
         if (uidRec != null && uidRec.persistent) {
@@ -8108,11 +8091,11 @@
         }
 
         // None of the service-policy criteria apply, so we apply the common criteria
-        return appRestrictedInBackgroundLocked(uid, packageName);
+        return appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk);
     }
 
-    int checkAllowBackgroundLocked(int uid, String packageName, int callingPid,
-            boolean alwaysRestrict) {
+    int getAppStartModeLocked(int uid, String packageName, int packageTargetSdk,
+            int callingPid, boolean alwaysRestrict, boolean disabledOnly) {
         UidRecord uidRec = mActiveUids.get(uid);
         if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid + " pkg="
                 + packageName + " rec=" + uidRec + " always=" + alwaysRestrict + " idle="
@@ -8130,27 +8113,37 @@
                 // We are hard-core about ephemeral apps not running in the background.
                 return ActivityManager.APP_START_MODE_DISABLED;
             } else {
-                /** Don't want to allow this exception in the final background check impl?
-                if (callingPid >= 0) {
-                    ProcessRecord proc;
-                    synchronized (mPidsSelfLocked) {
-                        proc = mPidsSelfLocked.get(callingPid);
-                    }
-                    if (proc != null && proc.curProcState
-                            < ActivityManager.PROCESS_STATE_RECEIVER) {
-                        // Whoever is instigating this is in the foreground, so we will allow it
-                        // to go through.
-                        return ActivityManager.APP_START_MODE_NORMAL;
-                    }
+                if (disabledOnly) {
+                    // The caller is only interested in whether app starts are completely
+                    // disabled for the given package (that is, it is an instant app).  So
+                    // we don't need to go further, which is all just seeing if we should
+                    // apply a "delayed" mode for a regular app.
+                    return ActivityManager.APP_START_MODE_NORMAL;
                 }
-                */
-
                 final int startMode = (alwaysRestrict)
-                        ? appRestrictedInBackgroundLocked(uid, packageName)
-                        : appServicesRestrictedInBackgroundLocked(uid, packageName);
+                        ? appRestrictedInBackgroundLocked(uid, packageName, packageTargetSdk)
+                        : appServicesRestrictedInBackgroundLocked(uid, packageName,
+                                packageTargetSdk);
                 if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid
                         + " pkg=" + packageName + " startMode=" + startMode
                         + " onwhitelist=" + isOnDeviceIdleWhitelistLocked(uid));
+                if (startMode == ActivityManager.APP_START_MODE_DELAYED) {
+                    // This is an old app that has been forced into a "compatible as possible"
+                    // mode of background check.  To increase compatibility, we will allow other
+                    // foreground apps to cause its services to start.
+                    if (callingPid >= 0) {
+                        ProcessRecord proc;
+                        synchronized (mPidsSelfLocked) {
+                            proc = mPidsSelfLocked.get(callingPid);
+                        }
+                        if (proc != null && proc.curProcState
+                                < ActivityManager.PROCESS_STATE_RECEIVER) {
+                            // Whoever is instigating this is in the foreground, so we will allow it
+                            // to go through.
+                            return ActivityManager.APP_START_MODE_NORMAL;
+                        }
+                    }
+                }
                 return startMode;
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 202868a..1a2a31b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -167,6 +167,8 @@
                     return runBugReport(pw);
                 case "force-stop":
                     return runForceStop(pw);
+                case "crash":
+                    return runCrash(pw);
                 case "kill":
                     return runKill(pw);
                 case "kill-all":
@@ -851,6 +853,32 @@
         return 0;
     }
 
+    int runCrash(PrintWriter pw) throws RemoteException {
+        int userId = UserHandle.USER_ALL;
+
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+
+        int pid = -1;
+        String packageName = null;
+        final String arg = getNextArgRequired();
+        // The argument is either a pid or a package name
+        try {
+            pid = Integer.parseInt(arg);
+        } catch (NumberFormatException e) {
+            packageName = arg;
+        }
+        mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash");
+        return 0;
+    }
+
     int runKill(PrintWriter pw) throws RemoteException {
         int userId = UserHandle.USER_ALL;
 
@@ -2480,6 +2508,8 @@
             pw.println("     --telephony: will dump only telephony sections.");
             pw.println("  force-stop [--user <USER_ID> | all | current] <PACKAGE>");
             pw.println("      Completely stop the given application package.");
+            pw.println("  crash [--user <USER_ID>] <PACKAGE|PID>");
+            pw.println("      Induce a VM crash in the specified package or process");
             pw.println("  kill [--user <USER_ID> | all | current] <PACKAGE>");
             pw.println("      Kill all processes associated with the given application.");
             pw.println("  kill-all");
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 739a8c4..384f2f8 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -259,7 +259,16 @@
         }
     }
 
-    void scheduleAppCrashLocked(int uid, int initialPid, String packageName,
+    /**
+     * Induce a crash in the given app.
+     *
+     * @param uid if nonnegative, the required matching uid of the target to crash
+     * @param initialPid fast-path match for the target to crash
+     * @param packageName fallback match if the stated pid is not found or doesn't match uid
+     * @param userId If nonnegative, required to identify a match by package name
+     * @param message
+     */
+    void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
             String message) {
         ProcessRecord proc = null;
 
@@ -270,14 +279,15 @@
         synchronized (mService.mPidsSelfLocked) {
             for (int i=0; i<mService.mPidsSelfLocked.size(); i++) {
                 ProcessRecord p = mService.mPidsSelfLocked.valueAt(i);
-                if (p.uid != uid) {
+                if (uid >= 0 && p.uid != uid) {
                     continue;
                 }
                 if (p.pid == initialPid) {
                     proc = p;
                     break;
                 }
-                if (p.pkgList.containsKey(packageName)) {
+                if (p.pkgList.containsKey(packageName)
+                        && (userId < 0 || p.userId == userId)) {
                     proc = p;
                 }
             }
@@ -286,7 +296,8 @@
         if (proc == null) {
             Slog.w(TAG, "crashApplication: nothing for uid=" + uid
                     + " initialPid=" + initialPid
-                    + " packageName=" + packageName);
+                    + " packageName=" + packageName
+                    + " userId=" + userId);
             return;
         }
 
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 61e555b..ee2467a 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -592,22 +592,6 @@
                     + " (uid " + r.callingUid + ")");
             skip = true;
         }
-        if (!skip) {
-            final int allowed = mService.checkAllowBackgroundLocked(filter.receiverList.uid,
-                    filter.packageName, -1, false);
-            if (false && allowed == ActivityManager.APP_START_MODE_DISABLED) {
-                // XXX should we really not allow this?  It means that while we are
-                // keeping an ephemeral app cached, its registered receivers will stop
-                // receiving broadcasts after it goes idle...  so if it comes back to
-                // the foreground, it won't know what the current state of those broadcasts is.
-                Slog.w(TAG, "Background execution not allowed: receiving "
-                        + r.intent
-                        + " to " + filter.receiverList.app
-                        + " (pid=" + filter.receiverList.pid
-                        + ", uid=" + filter.receiverList.uid + ")");
-                skip = true;
-            }
-        }
 
         if (!mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
                 r.callingPid, r.resolvedType, filter.receiverList.uid)) {
@@ -1156,13 +1140,14 @@
                     info.activityInfo.applicationInfo.uid, false);
 
             if (!skip) {
-                final int allowed = mService.checkAllowBackgroundLocked(
-                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1, true);
+                final int allowed = mService.getAppStartModeLocked(
+                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName,
+                        info.activityInfo.applicationInfo.targetSdkVersion, -1, true, false);
                 if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                     // We won't allow this receiver to be launched if the app has been
                     // completely disabled from launches, or it was not explicitly sent
                     // to it and the app is in a state that should not receive it
-                    // (depending on how checkAllowBackgroundLocked has determined that).
+                    // (depending on how getAppStartModeLocked has determined that).
                     if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
                         Slog.w(TAG, "Background execution disabled: receiving "
                                 + r.intent + " to "
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 71c7fd3..82b00da 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -534,7 +534,7 @@
                         // get to be foreground.
                         ams.setServiceForeground(name, ServiceRecord.this,
                                 0, null, 0);
-                        ams.crashApplication(appUid, appPid, localPackageName,
+                        ams.crashApplication(appUid, appPid, localPackageName, -1,
                                 "Bad notification for startForeground: " + e);
                     }
                 }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 11a3f11..5b539ff 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1019,8 +1019,7 @@
         final int owningUid = syncAdapterInfo.uid;
         final String owningPackage = syncAdapterInfo.componentName.getPackageName();
         try {
-            if (ActivityManager.getService().getAppStartMode(owningUid,
-                    owningPackage) == ActivityManager.APP_START_MODE_DISABLED) {
+            if (ActivityManager.getService().isAppStartModeDisabled(owningUid, owningPackage)) {
                 Slog.w(TAG, "Not scheduling job " + syncAdapterInfo.uid + ":"
                         + syncAdapterInfo.componentName
                         + " -- package not allowed to start");
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index f42c5be..a748013 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -566,8 +566,8 @@
             String tag) {
         JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag);
         try {
-            if (ActivityManager.getService().getAppStartMode(uId,
-                    job.getService().getPackageName()) == ActivityManager.APP_START_MODE_DISABLED) {
+            if (ActivityManager.getService().isAppStartModeDisabled(uId,
+                    job.getService().getPackageName())) {
                 Slog.w(TAG, "Not scheduling job " + uId + ":" + job.toString()
                         + " -- package not allowed to start");
                 return JobScheduler.RESULT_FAILURE;
@@ -1201,9 +1201,8 @@
             public void process(JobStatus job) {
                 if (isReadyToBeExecutedLocked(job)) {
                     try {
-                        if (ActivityManager.getService().getAppStartMode(job.getUid(),
-                                job.getJob().getService().getPackageName())
-                                == ActivityManager.APP_START_MODE_DISABLED) {
+                        if (ActivityManager.getService().isAppStartModeDisabled(job.getUid(),
+                                job.getJob().getService().getPackageName())) {
                             Slog.w(TAG, "Aborting job " + job.getUid() + ":"
                                     + job.getJob().toString() + " -- package not allowed to start");
                             mHandler.obtainMessage(MSG_STOP_JOB, job).sendToTarget();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 323b468..168884d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -605,7 +605,7 @@
                     REASON_DELEGATE_ERROR, null);
             long ident = Binder.clearCallingIdentity();
             try {
-                ActivityManager.getService().crashApplication(uid, initialPid, pkg,
+                ActivityManager.getService().crashApplication(uid, initialPid, pkg, -1,
                         "Bad notification posted from package " + pkg
                         + ": " + message);
             } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6044561..63a5d14 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9391,8 +9391,7 @@
             }
 
             // A package name must be unique; don't allow duplicates
-            if (mPackages.containsKey(pkg.packageName)
-                    || mSharedLibraries.containsKey(pkg.packageName)) {
+            if (mPackages.containsKey(pkg.packageName)) {
                 throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
                         "Application package " + pkg.packageName
                         + " already installed.  Skipping duplicate.");
@@ -17704,6 +17703,13 @@
             return false;
         }
 
+        try {
+            // update shared libraries for the newly re-installed system package
+            updateSharedLibrariesLPr(newPkg, null);
+        } catch (PackageManagerException e) {
+            Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
+        }
+
         prepareAppDataAfterInstallLIF(newPkg);
 
         // writer
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ae709fe..56d679e 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1529,10 +1529,11 @@
         if (UserHandle.getUserId(callingUid) != userId) {
             throw new SecurityException("Invalid user-ID");
         }
-        if (injectGetPackageUid(packageName, userId) == callingUid) {
-            return; // Caller is valid.
+        if (injectGetPackageUid(packageName, userId) != callingUid) {
+            throw new SecurityException("Calling package name mismatch");
         }
-        throw new SecurityException("Calling package name mismatch");
+        Preconditions.checkState(!isEphemeralApp(packageName, userId),
+                "Ephemeral apps can't use ShortcutManager");
     }
 
     // Overridden in unit tests to execute r synchronously.
@@ -3073,6 +3074,10 @@
         return (ai != null) && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
     }
 
+    private static boolean isEphemeralApp(@Nullable ApplicationInfo ai) {
+        return (ai != null) && ai.isEphemeralApp();
+    }
+
     private static boolean isInstalled(@Nullable PackageInfo pi) {
         return (pi != null) && isInstalled(pi.applicationInfo);
     }
@@ -3097,6 +3102,10 @@
         return getApplicationInfo(packageName, userId) != null;
     }
 
+    boolean isEphemeralApp(String packageName, int userId) {
+        return isEphemeralApp(getApplicationInfo(packageName, userId));
+    }
+
     @Nullable
     XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
         return activityInfo.loadXmlMetaData(mContext.getPackageManager(), key);
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index 2fd0603..74af639 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -81,7 +81,7 @@
 
     // TODO(b/31632518)
     if (gLight == nullptr) {
-        gLight = ILight::getService("light");
+        gLight = ILight::getService();
     }
 
     if (gLight == nullptr) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 623a0a5..f3b0131 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5574,7 +5574,7 @@
     }
 
     /**
-     * Set whether auto time is required by the specified admin (must be device owner).
+     * Set whether auto time is required by the specified admin (must be device or profile owner).
      */
     @Override
     public void setAutoTimeRequired(ComponentName who, boolean required) {
@@ -5585,7 +5585,7 @@
         final int userHandle = UserHandle.getCallingUserId();
         synchronized (this) {
             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
-                    DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             if (admin.requireAutoTime != required) {
                 admin.requireAutoTime = required;
                 saveSettingsLocked(userHandle);
@@ -5604,7 +5604,7 @@
     }
 
     /**
-     * Returns whether or not auto time is required by the device owner.
+     * Returns whether or not auto time is required by the device owner or any profile owner.
      */
     @Override
     public boolean getAutoTimeRequired() {
@@ -5613,7 +5613,20 @@
         }
         synchronized (this) {
             ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
-            return (deviceOwner != null) ? deviceOwner.requireAutoTime : false;
+            if (deviceOwner != null && deviceOwner.requireAutoTime) {
+                // If the device owner enforces auto time, we don't need to check the PO's
+                return true;
+            }
+
+            // Now check to see if any profile owner on any user enforces auto time
+            for (Integer userId : mOwners.getProfileOwnerKeys()) {
+                ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
+                if (profileOwner != null && profileOwner.requireAutoTime) {
+                    return true;
+                }
+            }
+
+            return false;
         }
     }
 
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 ee49a00..a600e69 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -76,6 +76,7 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.security.GeneralSecurityException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -94,6 +95,7 @@
     @Mock private DevicePolicyManager mMockDevicePolicyManager;
     @Mock private IAccountManagerResponse mMockAccountManagerResponse;
     @Mock private IBinder mMockBinder;
+    @Mock private INotificationManager mMockNotificationManager;
 
     @Captor private ArgumentCaptor<Intent> mIntentCaptor;
     @Captor private ArgumentCaptor<Bundle> mBundleCaptor;
@@ -129,7 +131,7 @@
         Context realTestContext = getContext();
         MyMockContext mockContext = new MyMockContext(realTestContext, mMockContext);
         setContext(mockContext);
-        mTestInjector = new TestInjector(realTestContext, mockContext);
+        mTestInjector = new TestInjector(realTestContext, mockContext, mMockNotificationManager);
         mAms = new AccountManagerService(mTestInjector);
     }
 
@@ -500,7 +502,7 @@
     }
 
     @SmallTest
-    public void testStartAddAccountSessionUserSuccessWithoutPasswordForwarding() throws Exception {
+    public void testStartAddAccountSessionSuccessWithoutPasswordForwarding() throws Exception {
         unlockSystemUser();
         when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn(
                 PackageManager.PERMISSION_DENIED);
@@ -531,7 +533,7 @@
     }
 
     @SmallTest
-    public void testStartAddAccountSessionUserSuccessWithPasswordForwarding() throws Exception {
+    public void testStartAddAccountSessionSuccessWithPasswordForwarding() throws Exception {
         unlockSystemUser();
         when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn(
                 PackageManager.PERMISSION_GRANTED);
@@ -564,7 +566,7 @@
     }
 
     @SmallTest
-    public void testStartAddAccountSessionUserReturnWithInvalidIntent() throws Exception {
+    public void testStartAddAccountSessionReturnWithInvalidIntent() throws Exception {
         unlockSystemUser();
         ResolveInfo resolveInfo = new ResolveInfo();
         resolveInfo.activityInfo = new ActivityInfo();
@@ -593,7 +595,7 @@
     }
 
     @SmallTest
-    public void testStartAddAccountSessionUserReturnWithValidIntent() throws Exception {
+    public void testStartAddAccountSessionReturnWithValidIntent() throws Exception {
         unlockSystemUser();
         ResolveInfo resolveInfo = new ResolveInfo();
         resolveInfo.activityInfo = new ActivityInfo();
@@ -626,7 +628,7 @@
     }
 
     @SmallTest
-    public void testStartAddAccountSessionUserError() throws Exception {
+    public void testStartAddAccountSessionError() throws Exception {
         unlockSystemUser();
         Bundle options = createOptionsWithAccountName(
                 AccountManagerServiceTestFixtures.ACCOUNT_NAME_ERROR);
@@ -650,14 +652,629 @@
         verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
     }
 
+    @SmallTest
+    public void testStartUpdateCredentialsSessionWithNullResponse() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.startUpdateCredentialsSession(
+                null, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                "authTokenType",
+                true, // expectActivityLaunch
+                null); // optionsIn
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+        } catch(Exception e){
+            fail(String.format("Expect IllegalArgumentException, but got %s.", e));
+        }
+    }
+
+    @SmallTest
+    public void testStartUpdateCredentialsSessionWithNullAccount() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.startUpdateCredentialsSession(
+                mMockAccountManagerResponse, // response
+                null,
+                "authTokenType",
+                true, // expectActivityLaunch
+                null); // optionsIn
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+        } catch(Exception e){
+            fail(String.format("Expect IllegalArgumentException, but got %s.", e));
+        }
+    }
+
+    @SmallTest
+    public void testStartUpdateCredentialsSessionSuccessWithoutPasswordForwarding()
+            throws Exception {
+        unlockSystemUser();
+        when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn(
+                PackageManager.PERMISSION_DENIED);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+        Bundle options = createOptionsWithAccountName(
+            AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS);
+        mAms.startUpdateCredentialsSession(
+                response, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                "authTokenType",
+                false, // expectActivityLaunch
+                options); // optionsIn
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
+        assertNotNull(sessionBundle);
+        // Assert that session bundle is encrypted and hence data not visible.
+        assertNull(sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1));
+        // Assert password is not returned
+        assertNull(result.getString(AccountManager.KEY_PASSWORD));
+        assertNull(result.getString(AccountManager.KEY_AUTHTOKEN, null));
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN,
+                result.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
+    }
+
+    @SmallTest
+    public void testStartUpdateCredentialsSessionSuccessWithPasswordForwarding() throws Exception {
+        unlockSystemUser();
+        when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn(
+                PackageManager.PERMISSION_GRANTED);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+        Bundle options = createOptionsWithAccountName(
+            AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS);
+        mAms.startUpdateCredentialsSession(
+                response, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                "authTokenType",
+                false, // expectActivityLaunch
+                options); // optionsIn
+
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
+        assertNotNull(sessionBundle);
+        // Assert that session bundle is encrypted and hence data not visible.
+        assertNull(sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1));
+        // Assert password is returned
+        assertEquals(result.getString(AccountManager.KEY_PASSWORD),
+                AccountManagerServiceTestFixtures.ACCOUNT_PASSWORD);
+        assertNull(result.getString(AccountManager.KEY_AUTHTOKEN));
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN,
+                result.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
+    }
+
+    @SmallTest
+    public void testStartUpdateCredentialsSessionReturnWithInvalidIntent() throws Exception {
+        unlockSystemUser();
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.applicationInfo = new ApplicationInfo();
+        when(mMockPackageManager.resolveActivityAsUser(
+                any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
+        when(mMockPackageManager.checkSignatures(
+                anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+        Bundle options = createOptionsWithAccountName(
+                AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE);
+
+        mAms.startUpdateCredentialsSession(
+                response, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE,
+                "authTokenType",
+                true,  // expectActivityLaunch
+                options); // optionsIn
+
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
+        verify(mMockAccountManagerResponse).onError(
+                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+    }
+
+    @SmallTest
+    public void testStartUpdateCredentialsSessionReturnWithValidIntent() throws Exception {
+        unlockSystemUser();
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.applicationInfo = new ApplicationInfo();
+        when(mMockPackageManager.resolveActivityAsUser(
+                any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
+        when(mMockPackageManager.checkSignatures(
+                anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+        Bundle options = createOptionsWithAccountName(
+                AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE);
+
+        mAms.startUpdateCredentialsSession(
+                response, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE,
+                "authTokenType",
+                true,  // expectActivityLaunch
+                options); // optionsIn
+
+        waitForLatch(latch);
+
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
+        assertNotNull(intent);
+        assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT));
+        assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK));
+    }
+
+    @SmallTest
+    public void testStartUpdateCredentialsSessionError() throws Exception {
+        unlockSystemUser();
+        Bundle options = createOptionsWithAccountName(
+                AccountManagerServiceTestFixtures.ACCOUNT_NAME_ERROR);
+        options.putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE);
+        options.putString(AccountManager.KEY_ERROR_MESSAGE,
+                AccountManagerServiceTestFixtures.ERROR_MESSAGE);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+
+        mAms.startUpdateCredentialsSession(
+                response, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_ERROR,
+                "authTokenType",
+                true,  // expectActivityLaunch
+                options); // optionsIn
+
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
+                AccountManagerServiceTestFixtures.ERROR_MESSAGE);
+        verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserWithNullResponse() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.finishSessionAsUser(
+                null, // response
+                createEncryptedSessionBundle(
+                        AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS),
+                false, // expectActivityLaunch
+                createAppBundle(), // appInfo
+                UserHandle.USER_SYSTEM);
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+        } catch(Exception e){
+            fail(String.format("Expect IllegalArgumentException, but got %s.", e));
+        }
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserWithNullSessionBundle() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.finishSessionAsUser(
+                mMockAccountManagerResponse, // response
+                null, // sessionBundle
+                false, // expectActivityLaunch
+                createAppBundle(), // appInfo
+                UserHandle.USER_SYSTEM);
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+        } catch(Exception e){
+            fail(String.format("Expect IllegalArgumentException, but got %s.", e));
+        }
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserUserCannotModifyAccountNoDPM() throws Exception {
+        unlockSystemUser();
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true);
+        when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle);
+        LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+
+        mAms.finishSessionAsUser(
+            mMockAccountManagerResponse, // response
+            createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS),
+            false, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            2); // fake user id
+
+        verify(mMockAccountManagerResponse).onError(
+                eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString());
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.of(2)));
+
+        // verify the intent for default CantAddAccountActivity is sent.
+        Intent intent = mIntentCaptor.getValue();
+        assertEquals(intent.getComponent().getClassName(), CantAddAccountActivity.class.getName());
+        assertEquals(intent.getIntExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, 0),
+                AccountManager.ERROR_CODE_USER_RESTRICTED);
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserUserCannotModifyAccountWithDPM() throws Exception {
+        unlockSystemUser();
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, true);
+        when(mMockUserManager.getUserRestrictions(any(UserHandle.class))).thenReturn(bundle);
+        LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+        LocalServices.addService(
+                DevicePolicyManagerInternal.class, mMockDevicePolicyManagerInternal);
+        when(mMockDevicePolicyManagerInternal.createUserRestrictionSupportIntent(
+                anyInt(), anyString())).thenReturn(new Intent());
+        when(mMockDevicePolicyManagerInternal.createShowAdminSupportIntent(
+                anyInt(), anyBoolean())).thenReturn(new Intent());
+
+        mAms.finishSessionAsUser(
+            mMockAccountManagerResponse, // response
+            createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS),
+            false, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            2); // fake user id
+
+        verify(mMockAccountManagerResponse).onError(
+                eq(AccountManager.ERROR_CODE_USER_RESTRICTED), anyString());
+        verify(mMockContext).startActivityAsUser(any(Intent.class), eq(UserHandle.of(2)));
+        verify(mMockDevicePolicyManagerInternal).createUserRestrictionSupportIntent(
+                anyInt(), anyString());
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserWithBadSessionBundle() throws Exception {
+        unlockSystemUser();
+
+        Bundle badSessionBundle = new Bundle();
+        badSessionBundle.putString("any", "any");
+        mAms.finishSessionAsUser(
+            mMockAccountManagerResponse, // response
+            badSessionBundle, // sessionBundle
+            false, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            2); // fake user id
+
+        verify(mMockAccountManagerResponse).onError(
+                eq(AccountManager.ERROR_CODE_BAD_REQUEST), anyString());
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserWithBadAccountType() throws Exception {
+        unlockSystemUser();
+
+        mAms.finishSessionAsUser(
+            mMockAccountManagerResponse, // response
+            createEncryptedSessionBundleWithNoAccountType(
+                    AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS),
+            false, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            2); // fake user id
+
+        verify(mMockAccountManagerResponse).onError(
+                eq(AccountManager.ERROR_CODE_BAD_ARGUMENTS), anyString());
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserUserCannotModifyAccountForTypeNoDPM() throws Exception {
+        unlockSystemUser();
+        when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt()))
+                .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"});
+        LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+
+        mAms.finishSessionAsUser(
+            mMockAccountManagerResponse, // response
+            createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS),
+            false, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            2); // fake user id
+
+        verify(mMockAccountManagerResponse).onError(
+                eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString());
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.of(2)));
+
+        // verify the intent for default CantAddAccountActivity is sent.
+        Intent intent = mIntentCaptor.getValue();
+        assertEquals(intent.getComponent().getClassName(), CantAddAccountActivity.class.getName());
+        assertEquals(intent.getIntExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, 0),
+                AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE);
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserUserCannotModifyAccountForTypeWithDPM() throws Exception {
+        unlockSystemUser();
+        when(mMockContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
+                mMockDevicePolicyManager);
+        when(mMockDevicePolicyManager.getAccountTypesWithManagementDisabledAsUser(anyInt()))
+                .thenReturn(new String[]{AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, "BBB"});
+
+        LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
+        LocalServices.addService(
+                DevicePolicyManagerInternal.class, mMockDevicePolicyManagerInternal);
+        when(mMockDevicePolicyManagerInternal.createUserRestrictionSupportIntent(
+                anyInt(), anyString())).thenReturn(new Intent());
+        when(mMockDevicePolicyManagerInternal.createShowAdminSupportIntent(
+                anyInt(), anyBoolean())).thenReturn(new Intent());
+
+        mAms.finishSessionAsUser(
+            mMockAccountManagerResponse, // response
+            createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS),
+            false, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            2); // fake user id
+
+        verify(mMockAccountManagerResponse).onError(
+                eq(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE), anyString());
+        verify(mMockContext).startActivityAsUser(any(Intent.class), eq(UserHandle.of(2)));
+        verify(mMockDevicePolicyManagerInternal).createShowAdminSupportIntent(
+                anyInt(), anyBoolean());
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserSuccess() throws Exception {
+        unlockSystemUser();
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+        mAms.finishSessionAsUser(
+            response, // response
+            createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS),
+            false, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            UserHandle.USER_SYSTEM);
+
+        waitForLatch(latch);
+        // Verify notification is cancelled
+        verify(mMockNotificationManager).cancelNotificationWithTag(
+                anyString(), anyString(), anyInt(), anyInt());
+
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        Bundle sessionBundle = result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE);
+        assertNotNull(sessionBundle);
+        // Assert that session bundle is decrypted and hence data is visible.
+        assertEquals(AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1,
+                sessionBundle.getString(AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1));
+        // Assert finishSessionAsUser added calling uid and pid into the sessionBundle
+        assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_UID));
+        assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_PID));
+        // Assert App bundle data overrides sessionBundle data
+        assertEquals(sessionBundle.getString(
+                AccountManager.KEY_ANDROID_PACKAGE_NAME), "APCT.package");
+
+        // Verify response data
+        assertNull(result.getString(AccountManager.KEY_AUTHTOKEN, null));
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME,
+                result.getString(AccountManager.KEY_ACCOUNT_NAME));
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+                result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserReturnWithInvalidIntent() throws Exception {
+        unlockSystemUser();
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.applicationInfo = new ApplicationInfo();
+        when(mMockPackageManager.resolveActivityAsUser(
+                any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
+        when(mMockPackageManager.checkSignatures(
+                anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_NO_MATCH);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+
+        mAms.finishSessionAsUser(
+            response, // response
+            createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE),
+            true, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            UserHandle.USER_SYSTEM);
+
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
+        verify(mMockAccountManagerResponse).onError(
+                eq(AccountManager.ERROR_CODE_REMOTE_EXCEPTION), anyString());
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserReturnWithValidIntent() throws Exception {
+        unlockSystemUser();
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.applicationInfo = new ApplicationInfo();
+        when(mMockPackageManager.resolveActivityAsUser(
+                any(Intent.class), anyInt(), anyInt())).thenReturn(resolveInfo);
+        when(mMockPackageManager.checkSignatures(
+                anyInt(), anyInt())).thenReturn(PackageManager.SIGNATURE_MATCH);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+
+        mAms.finishSessionAsUser(
+            response, // response
+            createEncryptedSessionBundle(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE),
+            true, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            UserHandle.USER_SYSTEM);
+
+        waitForLatch(latch);
+
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
+        assertNotNull(intent);
+        assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_RESULT));
+        assertNotNull(intent.getParcelableExtra(AccountManagerServiceTestFixtures.KEY_CALLBACK));
+    }
+
+    @SmallTest
+    public void testFinishSessionAsUserError() throws Exception {
+        unlockSystemUser();
+        Bundle sessionBundle = createEncryptedSessionBundleWithError(
+                AccountManagerServiceTestFixtures.ACCOUNT_NAME_ERROR);
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+
+        mAms.finishSessionAsUser(
+            response, // response
+            sessionBundle,
+            false, // expectActivityLaunch
+            createAppBundle(), // appInfo
+            UserHandle.USER_SYSTEM);
+
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
+                AccountManagerServiceTestFixtures.ERROR_MESSAGE);
+        verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
+    }
+
+    @SmallTest
+    public void testIsCredentialsUpdatedSuggestedWithNullResponse() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.isCredentialsUpdateSuggested(
+                null, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+        } catch(Exception e){
+            fail(String.format("Expect IllegalArgumentException, but got %s.", e));
+        }
+    }
+
+    @SmallTest
+    public void testIsCredentialsUpdatedSuggestedWithNullAccount() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.isCredentialsUpdateSuggested(
+                mMockAccountManagerResponse,
+                null, // account
+                AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+        } catch(Exception e){
+            fail(String.format("Expect IllegalArgumentException, but got %s.", e));
+        }
+    }
+
+    @SmallTest
+    public void testIsCredentialsUpdatedSuggestedWithEmptyStatusToken() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.isCredentialsUpdateSuggested(
+                mMockAccountManagerResponse,
+                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+                null);
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+        } catch(Exception e){
+            fail(String.format("Expect IllegalArgumentException, but got %s.", e));
+        }
+    }
+
+    @SmallTest
+    public void testIsCredentialsUpdatedSuggestedError() throws Exception {
+        unlockSystemUser();
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+
+        mAms.isCredentialsUpdateSuggested(
+            response,
+            AccountManagerServiceTestFixtures.ACCOUNT_ERROR,
+            AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
+
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
+                AccountManagerServiceTestFixtures.ERROR_MESSAGE);
+        verify(mMockAccountManagerResponse, never()).onResult(any(Bundle.class));
+    }
+
+    @SmallTest
+    public void testIsCredentialsUpdatedSuggestedSuccess() throws Exception {
+        unlockSystemUser();
+        final CountDownLatch latch = new CountDownLatch(1);
+        Response response = new Response(latch, mMockAccountManagerResponse);
+
+        mAms.isCredentialsUpdateSuggested(
+            response,
+            AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS,
+            AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
+
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        boolean needUpdate = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
+        assertTrue(needUpdate);
+    }
+
     private void waitForLatch(CountDownLatch latch) {
         try {
             latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
         } catch (InterruptedException e) {
-            fail("should not throw an InterruptedException");
+            throw new IllegalStateException("Should not throw an InterruptedException", e);
         }
     }
 
+    private Bundle encryptBundleWithCryptoHelper(Bundle sessionBundle) {
+        Bundle encryptedBundle = null;
+        try {
+            CryptoHelper cryptoHelper = CryptoHelper.getInstance();
+            encryptedBundle = cryptoHelper.encryptBundle(sessionBundle);
+        } catch (GeneralSecurityException e) {
+            throw new IllegalStateException("Failed to encrypt session bundle.", e);
+        }
+        return encryptedBundle;
+    }
+
+    private Bundle createEncryptedSessionBundle(final String accountName) {
+        Bundle sessionBundle = new Bundle();
+        sessionBundle.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME, accountName);
+        sessionBundle.putString(
+                AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1,
+                AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1);
+        sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE,
+                AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
+        sessionBundle.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, "APCT.session.package");
+        return encryptBundleWithCryptoHelper(sessionBundle);
+    }
+
+    private Bundle createEncryptedSessionBundleWithError(final String accountName) {
+        Bundle sessionBundle = new Bundle();
+        sessionBundle.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME, accountName);
+        sessionBundle.putString(
+                AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1,
+                AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1);
+        sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE,
+                AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
+        sessionBundle.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, "APCT.session.package");
+        sessionBundle.putInt(
+                AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_INVALID_RESPONSE);
+        sessionBundle.putString(AccountManager.KEY_ERROR_MESSAGE,
+                AccountManagerServiceTestFixtures.ERROR_MESSAGE);
+        return encryptBundleWithCryptoHelper(sessionBundle);
+    }
+
+    private Bundle createEncryptedSessionBundleWithNoAccountType(final String accountName) {
+        Bundle sessionBundle = new Bundle();
+        sessionBundle.putString(AccountManagerServiceTestFixtures.KEY_ACCOUNT_NAME, accountName);
+        sessionBundle.putString(
+                AccountManagerServiceTestFixtures.SESSION_DATA_NAME_1,
+                AccountManagerServiceTestFixtures.SESSION_DATA_VALUE_1);
+        sessionBundle.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, "APCT.session.package");
+        return encryptBundleWithCryptoHelper(sessionBundle);
+    }
+
+    private Bundle createAppBundle() {
+        Bundle appBundle = new Bundle();
+        appBundle.putString(AccountManager.KEY_ANDROID_PACKAGE_NAME, "APCT.package");
+        return appBundle;
+    }
+
     private Bundle createOptionsWithAccountName(final String accountName) {
         Bundle sessionBundle = new Bundle();
         sessionBundle.putString(
@@ -784,9 +1401,13 @@
 
     static class TestInjector extends AccountManagerService.Injector {
         private Context mRealContext;
-        TestInjector(Context realContext, Context mockContext) {
+        private INotificationManager mMockNotificationManager;
+        TestInjector(Context realContext,
+                Context mockContext,
+                INotificationManager mockNotificationManager) {
             super(mockContext);
             mRealContext = realContext;
+            mMockNotificationManager = mockNotificationManager;
         }
 
         @Override
@@ -820,7 +1441,7 @@
 
         @Override
         INotificationManager getNotificationManager() {
-            return mock(INotificationManager.class);
+            return mMockNotificationManager;
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
index 0db11e0c..8ec6176 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
@@ -197,7 +197,8 @@
             result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
             result.putString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN,
                     AccountManagerServiceTestFixtures.ACCOUNT_STATUS_TOKEN);
-            result.putString(AccountManager.KEY_PASSWORD, "doesn't matter");
+            result.putString(AccountManager.KEY_PASSWORD,
+                    AccountManagerServiceTestFixtures.ACCOUNT_PASSWORD);
             result.putString(AccountManager.KEY_AUTHTOKEN,
                     Integer.toString(mTokenCounter.incrementAndGet()));
         } else if (accountName.equals(
@@ -243,6 +244,8 @@
 
         Bundle result = new Bundle();
         if (accountName.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
+            // add sessionBundle into result for verification purpose
+            result.putBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE, sessionBundle);
             // fill bundle with a success result.
             result.putString(AccountManager.KEY_ACCOUNT_NAME,
                     AccountManagerServiceTestFixtures.ACCOUNT_NAME);
@@ -288,7 +291,9 @@
         } else {
             // fill with error
             fillResultWithError(
-                    result, AccountManager.ERROR_CODE_INVALID_RESPONSE, "Default Error Message");
+                    result,
+                    AccountManager.ERROR_CODE_INVALID_RESPONSE,
+                    AccountManagerServiceTestFixtures.ERROR_MESSAGE);
         }
 
         response.onResult(result);
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 167b33a..9835c88 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -566,6 +566,7 @@
     protected Map<String, PackageInfo> mInjectedPackages;
 
     protected Set<PackageWithUser> mUninstalledPackages;
+    protected Set<PackageWithUser> mEphemeralPackages;
     protected Set<String> mSystemPackages;
 
     protected PackageManager mMockPackageManager;
@@ -731,6 +732,7 @@
 
         mUninstalledPackages = new HashSet<>();
         mSystemPackages = new HashSet<>();
+        mEphemeralPackages = new HashSet<>();
 
         mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files");
 
@@ -1034,6 +1036,9 @@
         if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) {
             ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
         }
+        if (mEphemeralPackages.contains(PackageWithUser.of(userId, packageName))) {
+            ret.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_EPHEMERAL;
+        }
         if (mSystemPackages.contains(packageName)) {
             ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index d25923c..562de414 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -46,6 +46,7 @@
 
 import com.android.frameworks.servicestests.R;
 import com.android.server.pm.ShortcutService.ConfigConstants;
+import com.android.server.pm.ShortcutUser.PackageWithUser;
 
 import java.io.File;
 import java.io.FileWriter;
@@ -2037,4 +2038,32 @@
         assertFalse(mService.isUserUnlockedL(USER_0));
         assertFalse(mService.isUserUnlockedL(USER_10));
     }
+
+    public void testEphemeralApp() {
+        mRunningUsers.put(USER_10, true); // this test needs user 10.
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertWith(mManager.getDynamicShortcuts()).isEmpty();
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertWith(mManager.getDynamicShortcuts()).isEmpty();
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertWith(mManager.getDynamicShortcuts()).isEmpty();
+        });
+        // Make package 1 ephemeral.
+        mEphemeralPackages.add(PackageWithUser.of(USER_0, CALLING_PACKAGE_1));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertExpectException(IllegalStateException.class, "Ephemeral apps", () -> {
+                mManager.getDynamicShortcuts();
+            });
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertWith(mManager.getDynamicShortcuts()).isEmpty();
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertWith(mManager.getDynamicShortcuts()).isEmpty();
+        });
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 68765b6..6826975 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -37,6 +37,7 @@
 import android.util.Slog;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
 import com.android.server.SystemService;
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
@@ -46,8 +47,6 @@
 
     private static final String PROP_VERIFY_STORAGE = "fw.verify_storage";
 
-    // TODO: pivot all methods to manual mode when quota isn't supported
-
     public static class Lifecycle extends SystemService {
         private StorageStatsService mService;
 
@@ -71,11 +70,11 @@
     private final Installer mInstaller;
 
     public StorageStatsService(Context context) {
-        mContext = context;
-        mAppOps = context.getSystemService(AppOpsManager.class);
-        mUser = context.getSystemService(UserManager.class);
-        mPackage = context.getSystemService(PackageManager.class);
-        mStorage = context.getSystemService(StorageManager.class);
+        mContext = Preconditions.checkNotNull(context);
+        mAppOps = Preconditions.checkNotNull(context.getSystemService(AppOpsManager.class));
+        mUser = Preconditions.checkNotNull(context.getSystemService(UserManager.class));
+        mPackage = Preconditions.checkNotNull(context.getPackageManager());
+        mStorage = Preconditions.checkNotNull(context.getSystemService(StorageManager.class));
 
         mInstaller = new Installer(context);
         mInstaller.onStart();
@@ -107,7 +106,7 @@
             case AppOpsManager.MODE_ALLOWED:
                 return;
             case AppOpsManager.MODE_DEFAULT:
-                mContext.enforceCallingPermission(
+                mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.PACKAGE_USAGE_STATS, TAG);
                 return;
             default:
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index db7a31a..fbbe636 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -656,6 +656,7 @@
             // send a sticky broadcast containing current USB state
             Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
                     | Intent.FLAG_RECEIVER_FOREGROUND);
             intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
             intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index c0a86d6..a853d5c 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -598,6 +598,38 @@
         "vvm_cellular_data_required_bool";
 
     /**
+     * The default OMTP visual voicemail client prefix to use. Defaulted to "//VVM"
+     */
+    public static final String KEY_VVM_CLIENT_PREFIX_STRING =
+            "vvm_client_prefix_string";
+
+    /**
+     * Whether to use SSL to connect to the visual voicemail IMAP server. Defaulted to false.
+     */
+    public static final String KEY_VVM_SSL_ENABLED_BOOL = "vvm_ssl_enabled_bool";
+
+    /**
+     * A set of capabilities that should not be used even if it is reported by the visual voicemail
+     * IMAP CAPABILITY command.
+     */
+    public static final String KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY =
+            "vvm_disabled_capabilities_string_array";
+
+    /**
+     * Whether legacy mode should be used when the visual voicemail client is disabled.
+     *
+     * <p>Legacy mode is a mode that on the carrier side visual voicemail is still activated, but on
+     * the client side all network operations are disabled. SMSs are still monitored so a new
+     * message SYNC SMS will be translated to show a message waiting indicator, like traditional
+     * voicemails.
+     *
+     * <p>This is for carriers that does not support VVM deactivation so voicemail can continue to
+     * function without the data cost.
+     */
+    public static final String KEY_VVM_LEGACY_MODE_ENABLED_BOOL =
+            "vvm_legacy_mode_enabled_bool";
+
+    /**
      * Whether to prefetch audio data on new voicemail arrival, defaulted to true.
      */
     public static final String KEY_VVM_PREFETCH_BOOL = "vvm_prefetch_bool";
@@ -605,10 +637,20 @@
     /**
      * The package name of the carrier's visual voicemail app to ensure that dialer visual voicemail
      * and carrier visual voicemail are not active at the same time.
+     *
+     * @deprecated use {@link #KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY}.
      */
+    @Deprecated
     public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
 
     /**
+     * A list of the carrier's visual voicemail app package names to ensure that dialer visual
+     * voicemail and carrier visual voicemail are not active at the same time.
+     */
+    public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY =
+            "carrier_vvm_package_name_string_array";
+
+    /**
      * Flag specifying whether ICCID is showed in SIM Status screen, default to false.
      */
     public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
@@ -1308,8 +1350,13 @@
         sDefaults.putInt(KEY_VVM_PORT_NUMBER_INT, 0);
         sDefaults.putString(KEY_VVM_TYPE_STRING, "");
         sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL, false);
+        sDefaults.putString(KEY_VVM_CLIENT_PREFIX_STRING,"//VVM");
+        sDefaults.putBoolean(KEY_VVM_SSL_ENABLED_BOOL,false);
+        sDefaults.putStringArray(KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY, null);
+        sDefaults.putBoolean(KEY_VVM_LEGACY_MODE_ENABLED_BOOL,false);
         sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOL, true);
         sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, "");
+        sDefaults.putStringArray(KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false);
         sDefaults.putBoolean(KEY_CI_ACTION_ON_SYS_UPDATE_BOOL, false);
         sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING, "");