Merge "Added explicit cast so it compiles on Eclipse." into nyc-mr1-dev
diff --git a/Android.mk b/Android.mk
index 2b248d4..50bed92 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1120,6 +1120,9 @@
 		-showAnnotation android.annotation.SystemApi \
 		-title "Android SDK - Including system APIs." \
 		-toroot / \
+		-hide 101 \
+		-hide 104 \
+		-hide 108 \
 		-hdf android.whichdoc online \
 		$(sample_groups) \
 		-hdf android.hasSamples true \
diff --git a/api/current.txt b/api/current.txt
index 375250c..1414fab 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -420,9 +420,9 @@
     field public static final int contentInsetStart = 16843859; // 0x1010453
     field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522
     field public static final int contextClickable = 16844007; // 0x10104e7
-    field public static final int contextDescription = 16844082; // 0x1010532
+    field public static final int contextDescription = 16844078; // 0x101052e
     field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
-    field public static final int contextUri = 16844081; // 0x1010531
+    field public static final int contextUri = 16844077; // 0x101052d
     field public static final int controlX1 = 16843772; // 0x10103fc
     field public static final int controlX2 = 16843774; // 0x10103fe
     field public static final int controlY1 = 16843773; // 0x10103fd
@@ -1041,7 +1041,7 @@
     field public static final int rotation = 16843558; // 0x1010326
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
-    field public static final int roundIcon = 16844080; // 0x1010530
+    field public static final int roundIcon = 16844076; // 0x101052c
     field public static final int rowCount = 16843637; // 0x1010375
     field public static final int rowDelay = 16843216; // 0x10101d0
     field public static final int rowEdgeFlags = 16843329; // 0x1010241
@@ -1109,20 +1109,16 @@
     field public static final int shareInterpolator = 16843195; // 0x10101bb
     field public static final int sharedUserId = 16842763; // 0x101000b
     field public static final int sharedUserLabel = 16843361; // 0x1010261
-    field public static final int shortcutCategories = 16844077; // 0x101052d
-    field public static final int shortcutDisabledMessage = 16844076; // 0x101052c
-    field public static final int shortcutIcon = 16844073; // 0x1010529
+    field public static final int shortcutDisabledMessage = 16844075; // 0x101052b
     field public static final int shortcutId = 16844072; // 0x1010528
-    field public static final int shortcutIntentAction = 16844078; // 0x101052e
-    field public static final int shortcutIntentData = 16844079; // 0x101052f
-    field public static final int shortcutLongLabel = 16844075; // 0x101052b
-    field public static final int shortcutShortLabel = 16844074; // 0x101052a
+    field public static final int shortcutLongLabel = 16844074; // 0x101052a
+    field public static final int shortcutShortLabel = 16844073; // 0x1010529
     field public static final int shouldDisableView = 16843246; // 0x10101ee
     field public static final int showAsAction = 16843481; // 0x10102d9
     field public static final int showDefault = 16843258; // 0x10101fa
     field public static final int showDividers = 16843561; // 0x1010329
     field public static final int showForAllUsers = 16844015; // 0x10104ef
-    field public static final int showMetadataInPreview = 16844083; // 0x1010533
+    field public static final int showMetadataInPreview = 16844079; // 0x101052f
     field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9
     field public static final int showSilent = 16843259; // 0x10101fb
     field public static final int showText = 16843949; // 0x10104ad
@@ -10099,14 +10095,14 @@
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
-    method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
     method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
     method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
-    method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setRank(int);
-    method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence);
   }
 
   public class ShortcutManager {
@@ -37466,12 +37462,15 @@
     field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6
     field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc
     field public static final int NETWORK_TYPE_GPRS = 1; // 0x1
+    field public static final int NETWORK_TYPE_GSM = 16; // 0x10
     field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8
     field public static final int NETWORK_TYPE_HSPA = 10; // 0xa
     field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf
     field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9
     field public static final int NETWORK_TYPE_IDEN = 11; // 0xb
+    field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12
     field public static final int NETWORK_TYPE_LTE = 13; // 0xd
+    field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11
     field public static final int NETWORK_TYPE_UMTS = 3; // 0x3
     field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
     field public static final int PHONE_TYPE_CDMA = 2; // 0x2
@@ -40272,7 +40271,10 @@
     method public boolean equals(android.util.DisplayMetrics);
     method public void setTo(android.util.DisplayMetrics);
     method public void setToDefaults();
+    field public static final int DENSITY_260 = 260; // 0x104
     field public static final int DENSITY_280 = 280; // 0x118
+    field public static final int DENSITY_300 = 300; // 0x12c
+    field public static final int DENSITY_340 = 340; // 0x154
     field public static final int DENSITY_360 = 360; // 0x168
     field public static final int DENSITY_400 = 400; // 0x190
     field public static final int DENSITY_420 = 420; // 0x1a4
@@ -44693,6 +44695,7 @@
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -44708,7 +44711,6 @@
     method public java.lang.CharSequence getSelectedText(int);
     method public java.lang.CharSequence getTextAfterCursor(int, int);
     method public java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean performContextMenuAction(int);
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44863,6 +44865,7 @@
     method public abstract boolean clearMetaKeyStates(int);
     method public abstract void closeConnection();
     method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public abstract boolean commitText(java.lang.CharSequence, int);
     method public abstract boolean deleteSurroundingText(int, int);
@@ -44875,7 +44878,6 @@
     method public abstract java.lang.CharSequence getSelectedText(int);
     method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
     method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public abstract boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public abstract boolean performContextMenuAction(int);
     method public abstract boolean performEditorAction(int);
     method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44897,6 +44899,7 @@
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -44909,7 +44912,6 @@
     method public java.lang.CharSequence getSelectedText(int);
     method public java.lang.CharSequence getTextAfterCursor(int, int);
     method public java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean performContextMenuAction(int);
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
diff --git a/api/system-current.txt b/api/system-current.txt
index 49dd103..cb6ae79 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -527,9 +527,9 @@
     field public static final int contentInsetStart = 16843859; // 0x1010453
     field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522
     field public static final int contextClickable = 16844007; // 0x10104e7
-    field public static final int contextDescription = 16844082; // 0x1010532
+    field public static final int contextDescription = 16844078; // 0x101052e
     field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
-    field public static final int contextUri = 16844081; // 0x1010531
+    field public static final int contextUri = 16844077; // 0x101052d
     field public static final int controlX1 = 16843772; // 0x10103fc
     field public static final int controlX2 = 16843774; // 0x10103fe
     field public static final int controlY1 = 16843773; // 0x10103fd
@@ -1148,7 +1148,7 @@
     field public static final int rotation = 16843558; // 0x1010326
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
-    field public static final int roundIcon = 16844080; // 0x1010530
+    field public static final int roundIcon = 16844076; // 0x101052c
     field public static final int rowCount = 16843637; // 0x1010375
     field public static final int rowDelay = 16843216; // 0x10101d0
     field public static final int rowEdgeFlags = 16843329; // 0x1010241
@@ -1220,20 +1220,16 @@
     field public static final int shareInterpolator = 16843195; // 0x10101bb
     field public static final int sharedUserId = 16842763; // 0x101000b
     field public static final int sharedUserLabel = 16843361; // 0x1010261
-    field public static final int shortcutCategories = 16844077; // 0x101052d
-    field public static final int shortcutDisabledMessage = 16844076; // 0x101052c
-    field public static final int shortcutIcon = 16844073; // 0x1010529
+    field public static final int shortcutDisabledMessage = 16844075; // 0x101052b
     field public static final int shortcutId = 16844072; // 0x1010528
-    field public static final int shortcutIntentAction = 16844078; // 0x101052e
-    field public static final int shortcutIntentData = 16844079; // 0x101052f
-    field public static final int shortcutLongLabel = 16844075; // 0x101052b
-    field public static final int shortcutShortLabel = 16844074; // 0x101052a
+    field public static final int shortcutLongLabel = 16844074; // 0x101052a
+    field public static final int shortcutShortLabel = 16844073; // 0x1010529
     field public static final int shouldDisableView = 16843246; // 0x10101ee
     field public static final int showAsAction = 16843481; // 0x10102d9
     field public static final int showDefault = 16843258; // 0x10101fa
     field public static final int showDividers = 16843561; // 0x1010329
     field public static final int showForAllUsers = 16844015; // 0x10104ef
-    field public static final int showMetadataInPreview = 16844083; // 0x1010533
+    field public static final int showMetadataInPreview = 16844079; // 0x101052f
     field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9
     field public static final int showSilent = 16843259; // 0x10101fb
     field public static final int showText = 16843949; // 0x10104ad
@@ -10523,14 +10519,14 @@
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
-    method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
     method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
     method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
-    method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setRank(int);
-    method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence);
   }
 
   public class ShortcutManager {
@@ -39334,14 +39330,16 @@
   }
 
   public class ParcelableCallAnalytics implements android.os.Parcelable {
-    ctor public ParcelableCallAnalytics(long, long, int, boolean, boolean, int, int, boolean, java.lang.String, boolean);
+    ctor public ParcelableCallAnalytics(long, long, int, boolean, boolean, int, int, boolean, java.lang.String, boolean, java.util.List<android.telecom.ParcelableCallAnalytics.AnalyticsEvent>, java.util.List<android.telecom.ParcelableCallAnalytics.EventTiming>);
     ctor public ParcelableCallAnalytics(android.os.Parcel);
+    method public java.util.List<android.telecom.ParcelableCallAnalytics.AnalyticsEvent> analyticsEvents();
     method public int describeContents();
     method public long getCallDurationMillis();
     method public int getCallTechnologies();
     method public int getCallTerminationCode();
     method public int getCallType();
     method public java.lang.String getConnectionService();
+    method public java.util.List<android.telecom.ParcelableCallAnalytics.EventTiming> getEventTimings();
     method public long getStartTimeMillis();
     method public boolean isAdditionalCall();
     method public boolean isCreatedFromExistingConnection();
@@ -39362,6 +39360,73 @@
     field public static final int THIRD_PARTY_PHONE = 16; // 0x10
   }
 
+  public static final class ParcelableCallAnalytics.AnalyticsEvent implements android.os.Parcelable {
+    ctor public ParcelableCallAnalytics.AnalyticsEvent(int, long);
+    method public int describeContents();
+    method public int getEventName();
+    method public long getTimeSinceLastEvent();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int AUDIO_ROUTE_BT = 204; // 0xcc
+    field public static final int AUDIO_ROUTE_EARPIECE = 205; // 0xcd
+    field public static final int AUDIO_ROUTE_HEADSET = 206; // 0xce
+    field public static final int AUDIO_ROUTE_SPEAKER = 207; // 0xcf
+    field public static final int BIND_CS = 5; // 0x5
+    field public static final int BLOCK_CHECK_FINISHED = 105; // 0x69
+    field public static final int BLOCK_CHECK_INITIATED = 104; // 0x68
+    field public static final int CONFERENCE_WITH = 300; // 0x12c
+    field public static final android.os.Parcelable.Creator<android.telecom.ParcelableCallAnalytics.AnalyticsEvent> CREATOR;
+    field public static final int CS_BOUND = 6; // 0x6
+    field public static final int DIRECT_TO_VM_FINISHED = 103; // 0x67
+    field public static final int DIRECT_TO_VM_INITIATED = 102; // 0x66
+    field public static final int FILTERING_COMPLETED = 107; // 0x6b
+    field public static final int FILTERING_INITIATED = 106; // 0x6a
+    field public static final int FILTERING_TIMED_OUT = 108; // 0x6c
+    field public static final int MUTE = 202; // 0xca
+    field public static final int REMOTELY_HELD = 402; // 0x192
+    field public static final int REMOTELY_UNHELD = 403; // 0x193
+    field public static final int REQUEST_ACCEPT = 7; // 0x7
+    field public static final int REQUEST_HOLD = 400; // 0x190
+    field public static final int REQUEST_PULL = 500; // 0x1f4
+    field public static final int REQUEST_REJECT = 8; // 0x8
+    field public static final int REQUEST_UNHOLD = 401; // 0x191
+    field public static final int SCREENING_COMPLETED = 101; // 0x65
+    field public static final int SCREENING_SENT = 100; // 0x64
+    field public static final int SET_ACTIVE = 1; // 0x1
+    field public static final int SET_DIALING = 4; // 0x4
+    field public static final int SET_DISCONNECTED = 2; // 0x2
+    field public static final int SET_HOLD = 404; // 0x194
+    field public static final int SET_PARENT = 302; // 0x12e
+    field public static final int SET_SELECT_PHONE_ACCOUNT = 0; // 0x0
+    field public static final int SILENCE = 201; // 0xc9
+    field public static final int SKIP_RINGING = 200; // 0xc8
+    field public static final int SPLIT_CONFERENCE = 301; // 0x12d
+    field public static final int START_CONNECTION = 3; // 0x3
+    field public static final int SWAP = 405; // 0x195
+    field public static final int UNMUTE = 203; // 0xcb
+  }
+
+  public static final class ParcelableCallAnalytics.EventTiming implements android.os.Parcelable {
+    ctor public ParcelableCallAnalytics.EventTiming(int, long);
+    method public int describeContents();
+    method public int getName();
+    method public long getTime();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACCEPT_TIMING = 0; // 0x0
+    field public static final int BIND_CS_TIMING = 6; // 0x6
+    field public static final int BLOCK_CHECK_FINISHED_TIMING = 9; // 0x9
+    field public static final android.os.Parcelable.Creator<android.telecom.ParcelableCallAnalytics.EventTiming> CREATOR;
+    field public static final int DIRECT_TO_VM_FINISHED_TIMING = 8; // 0x8
+    field public static final int DISCONNECT_TIMING = 2; // 0x2
+    field public static final int FILTERING_COMPLETED_TIMING = 10; // 0xa
+    field public static final int FILTERING_TIMED_OUT_TIMING = 11; // 0xb
+    field public static final int HOLD_TIMING = 3; // 0x3
+    field public static final int INVALID = 999999; // 0xf423f
+    field public static final int OUTGOING_TIME_TO_DIALING_TIMING = 5; // 0x5
+    field public static final int REJECT_TIMING = 1; // 0x1
+    field public static final int SCREENING_COMPLETED_TIMING = 7; // 0x7
+    field public static final int UNHOLD_TIMING = 4; // 0x4
+  }
+
   public final deprecated class Phone {
     method public final void addListener(android.telecom.Phone.Listener);
     method public final boolean canAddCall();
@@ -39578,6 +39643,41 @@
     field public static final android.os.Parcelable.Creator<android.telecom.StatusHints> CREATOR;
   }
 
+  public final class TelecomAnalytics implements android.os.Parcelable {
+    ctor public TelecomAnalytics(java.util.List<android.telecom.TelecomAnalytics.SessionTiming>, java.util.List<android.telecom.ParcelableCallAnalytics>);
+    method public int describeContents();
+    method public java.util.List<android.telecom.ParcelableCallAnalytics> getCallAnalytics();
+    method public java.util.List<android.telecom.TelecomAnalytics.SessionTiming> getSessionTimings();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.TelecomAnalytics> CREATOR;
+  }
+
+  public static final class TelecomAnalytics.SessionTiming implements android.os.Parcelable {
+    ctor public TelecomAnalytics.SessionTiming(int, long);
+    method public int describeContents();
+    method public java.lang.Integer getKey();
+    method public long getTime();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.TelecomAnalytics.SessionTiming> CREATOR;
+    field public static final int CSW_ADD_CONFERENCE_CALL = 108; // 0x6c
+    field public static final int CSW_HANDLE_CREATE_CONNECTION_COMPLETE = 100; // 0x64
+    field public static final int CSW_REMOVE_CALL = 106; // 0x6a
+    field public static final int CSW_SET_ACTIVE = 101; // 0x65
+    field public static final int CSW_SET_DIALING = 103; // 0x67
+    field public static final int CSW_SET_DISCONNECTED = 104; // 0x68
+    field public static final int CSW_SET_IS_CONFERENCED = 107; // 0x6b
+    field public static final int CSW_SET_ON_HOLD = 105; // 0x69
+    field public static final int CSW_SET_RINGING = 102; // 0x66
+    field public static final int ICA_ANSWER_CALL = 1; // 0x1
+    field public static final int ICA_CONFERENCE = 8; // 0x8
+    field public static final int ICA_DISCONNECT_CALL = 3; // 0x3
+    field public static final int ICA_HOLD_CALL = 4; // 0x4
+    field public static final int ICA_MUTE = 6; // 0x6
+    field public static final int ICA_REJECT_CALL = 2; // 0x2
+    field public static final int ICA_SET_AUDIO_ROUTE = 7; // 0x7
+    field public static final int ICA_UNHOLD_CALL = 5; // 0x5
+  }
+
   public class TelecomManager {
     method public void acceptRingingCall();
     method public void acceptRingingCall(int);
@@ -39587,7 +39687,7 @@
     method public deprecated void clearAccounts();
     method public void clearPhoneAccounts();
     method public android.content.Intent createManageBlockedNumbersIntent();
-    method public java.util.List<android.telecom.ParcelableCallAnalytics> dumpAnalytics();
+    method public android.telecom.TelecomAnalytics dumpAnalytics();
     method public void enablePhoneAccount(android.telecom.PhoneAccountHandle, boolean);
     method public boolean endCall();
     method public android.net.Uri getAdnUriForPhoneAccount(android.telecom.PhoneAccountHandle);
@@ -40449,12 +40549,15 @@
     field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6
     field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc
     field public static final int NETWORK_TYPE_GPRS = 1; // 0x1
+    field public static final int NETWORK_TYPE_GSM = 16; // 0x10
     field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8
     field public static final int NETWORK_TYPE_HSPA = 10; // 0xa
     field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf
     field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9
     field public static final int NETWORK_TYPE_IDEN = 11; // 0xb
+    field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12
     field public static final int NETWORK_TYPE_LTE = 13; // 0xd
+    field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11
     field public static final int NETWORK_TYPE_UMTS = 3; // 0x3
     field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
     field public static final int PHONE_TYPE_CDMA = 2; // 0x2
@@ -43272,7 +43375,10 @@
     method public boolean equals(android.util.DisplayMetrics);
     method public void setTo(android.util.DisplayMetrics);
     method public void setToDefaults();
+    field public static final int DENSITY_260 = 260; // 0x104
     field public static final int DENSITY_280 = 280; // 0x118
+    field public static final int DENSITY_300 = 300; // 0x12c
+    field public static final int DENSITY_340 = 340; // 0x154
     field public static final int DENSITY_360 = 360; // 0x168
     field public static final int DENSITY_400 = 400; // 0x190
     field public static final int DENSITY_420 = 420; // 0x1a4
@@ -47696,6 +47802,7 @@
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -47711,7 +47818,6 @@
     method public java.lang.CharSequence getSelectedText(int);
     method public java.lang.CharSequence getTextAfterCursor(int, int);
     method public java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean performContextMenuAction(int);
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -47866,6 +47972,7 @@
     method public abstract boolean clearMetaKeyStates(int);
     method public abstract void closeConnection();
     method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public abstract boolean commitText(java.lang.CharSequence, int);
     method public abstract boolean deleteSurroundingText(int, int);
@@ -47878,7 +47985,6 @@
     method public abstract java.lang.CharSequence getSelectedText(int);
     method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
     method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public abstract boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public abstract boolean performContextMenuAction(int);
     method public abstract boolean performEditorAction(int);
     method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -47900,6 +48006,7 @@
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -47912,7 +48019,6 @@
     method public java.lang.CharSequence getSelectedText(int);
     method public java.lang.CharSequence getTextAfterCursor(int, int);
     method public java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean performContextMenuAction(int);
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
diff --git a/api/test-current.txt b/api/test-current.txt
index 227f161..970ec19 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -420,9 +420,9 @@
     field public static final int contentInsetStart = 16843859; // 0x1010453
     field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522
     field public static final int contextClickable = 16844007; // 0x10104e7
-    field public static final int contextDescription = 16844082; // 0x1010532
+    field public static final int contextDescription = 16844078; // 0x101052e
     field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
-    field public static final int contextUri = 16844081; // 0x1010531
+    field public static final int contextUri = 16844077; // 0x101052d
     field public static final int controlX1 = 16843772; // 0x10103fc
     field public static final int controlX2 = 16843774; // 0x10103fe
     field public static final int controlY1 = 16843773; // 0x10103fd
@@ -1041,7 +1041,7 @@
     field public static final int rotation = 16843558; // 0x1010326
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
-    field public static final int roundIcon = 16844080; // 0x1010530
+    field public static final int roundIcon = 16844076; // 0x101052c
     field public static final int rowCount = 16843637; // 0x1010375
     field public static final int rowDelay = 16843216; // 0x10101d0
     field public static final int rowEdgeFlags = 16843329; // 0x1010241
@@ -1109,20 +1109,16 @@
     field public static final int shareInterpolator = 16843195; // 0x10101bb
     field public static final int sharedUserId = 16842763; // 0x101000b
     field public static final int sharedUserLabel = 16843361; // 0x1010261
-    field public static final int shortcutCategories = 16844077; // 0x101052d
-    field public static final int shortcutDisabledMessage = 16844076; // 0x101052c
-    field public static final int shortcutIcon = 16844073; // 0x1010529
+    field public static final int shortcutDisabledMessage = 16844075; // 0x101052b
     field public static final int shortcutId = 16844072; // 0x1010528
-    field public static final int shortcutIntentAction = 16844078; // 0x101052e
-    field public static final int shortcutIntentData = 16844079; // 0x101052f
-    field public static final int shortcutLongLabel = 16844075; // 0x101052b
-    field public static final int shortcutShortLabel = 16844074; // 0x101052a
+    field public static final int shortcutLongLabel = 16844074; // 0x101052a
+    field public static final int shortcutShortLabel = 16844073; // 0x1010529
     field public static final int shouldDisableView = 16843246; // 0x10101ee
     field public static final int showAsAction = 16843481; // 0x10102d9
     field public static final int showDefault = 16843258; // 0x10101fa
     field public static final int showDividers = 16843561; // 0x1010329
     field public static final int showForAllUsers = 16844015; // 0x10104ef
-    field public static final int showMetadataInPreview = 16844083; // 0x1010533
+    field public static final int showMetadataInPreview = 16844079; // 0x101052f
     field public static final deprecated int showOnLockScreen = 16843721; // 0x10103c9
     field public static final int showSilent = 16843259; // 0x10101fb
     field public static final int showText = 16843949; // 0x10104ad
@@ -10112,14 +10108,14 @@
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
-    method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
     method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
     method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
-    method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setRank(int);
-    method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence);
   }
 
   public class ShortcutManager {
@@ -37544,12 +37540,15 @@
     field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6
     field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc
     field public static final int NETWORK_TYPE_GPRS = 1; // 0x1
+    field public static final int NETWORK_TYPE_GSM = 16; // 0x10
     field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8
     field public static final int NETWORK_TYPE_HSPA = 10; // 0xa
     field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf
     field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9
     field public static final int NETWORK_TYPE_IDEN = 11; // 0xb
+    field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12
     field public static final int NETWORK_TYPE_LTE = 13; // 0xd
+    field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11
     field public static final int NETWORK_TYPE_UMTS = 3; // 0x3
     field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
     field public static final int PHONE_TYPE_CDMA = 2; // 0x2
@@ -40352,7 +40351,10 @@
     method public boolean equals(android.util.DisplayMetrics);
     method public void setTo(android.util.DisplayMetrics);
     method public void setToDefaults();
+    field public static final int DENSITY_260 = 260; // 0x104
     field public static final int DENSITY_280 = 280; // 0x118
+    field public static final int DENSITY_300 = 300; // 0x12c
+    field public static final int DENSITY_340 = 340; // 0x154
     field public static final int DENSITY_360 = 360; // 0x168
     field public static final int DENSITY_400 = 400; // 0x190
     field public static final int DENSITY_420 = 420; // 0x1a4
@@ -44773,6 +44775,7 @@
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -44788,7 +44791,6 @@
     method public java.lang.CharSequence getSelectedText(int);
     method public java.lang.CharSequence getTextAfterCursor(int, int);
     method public java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean performContextMenuAction(int);
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44943,6 +44945,7 @@
     method public abstract boolean clearMetaKeyStates(int);
     method public abstract void closeConnection();
     method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public abstract boolean commitText(java.lang.CharSequence, int);
     method public abstract boolean deleteSurroundingText(int, int);
@@ -44955,7 +44958,6 @@
     method public abstract java.lang.CharSequence getSelectedText(int);
     method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
     method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public abstract boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public abstract boolean performContextMenuAction(int);
     method public abstract boolean performEditorAction(int);
     method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44977,6 +44979,7 @@
     method public boolean clearMetaKeyStates(int);
     method public void closeConnection();
     method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+    method public boolean commitContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
     method public boolean commitText(java.lang.CharSequence, int);
     method public boolean deleteSurroundingText(int, int);
@@ -44989,7 +44992,6 @@
     method public java.lang.CharSequence getSelectedText(int);
     method public java.lang.CharSequence getTextAfterCursor(int, int);
     method public java.lang.CharSequence getTextBeforeCursor(int, int);
-    method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
     method public boolean performContextMenuAction(int);
     method public boolean performEditorAction(int);
     method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 69b5a17..5bf8076 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -122,6 +122,11 @@
             return;
         }
 
+        if ("whitelist".equals(op)) {
+            doPrintWhitelist();
+            return;
+        }
+
         System.err.println("Unknown command");
         showUsage();
     }
@@ -604,6 +609,20 @@
         }
     }
 
+    private void doPrintWhitelist() {
+        try {
+            final String[] whitelist = mBmgr.getTransportWhitelist();
+            if (whitelist != null) {
+                for (String transport : whitelist) {
+                    System.out.println(transport);
+                }
+            }
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            System.err.println(BMGR_NOT_RUNNING_ERR);
+        }
+    }
+
     private String nextArg() {
         if (mNextArg >= mArgs.length) {
             return null;
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 4470eda..c6834f9 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -254,6 +254,10 @@
             return runMovePrimaryStorage();
         }
 
+        if ("set-user-restriction".equals(op)) {
+            return runSetUserRestriction();
+        }
+
         try {
             if (args.length == 1) {
                 if (args[0].equalsIgnoreCase("-l")) {
@@ -1054,6 +1058,38 @@
         }
     }
 
+    public int runSetUserRestriction() {
+        int userId = UserHandle.USER_SYSTEM;
+        String opt = nextOption();
+        if (opt != null && "--user".equals(opt)) {
+            String arg = nextArg();
+            if (arg == null || !isNumber(arg)) {
+                System.err.println("Error: valid userId not specified");
+                return 1;
+            }
+            userId = Integer.parseInt(arg);
+        }
+
+        String restriction = nextArg();
+        String arg = nextArg();
+        boolean value;
+        if ("1".equals(arg)) {
+            value = true;
+        } else if ("0".equals(arg)) {
+            value = false;
+        } else {
+            System.err.println("Error: valid value not specified");
+            return 1;
+        }
+        try {
+            mUm.setUserRestriction(restriction, value, userId);
+            return 0;
+        } catch (RemoteException e) {
+            System.err.println(e.toString());
+            return 1;
+        }
+    }
+
     static class ClearDataObserver extends IPackageDataObserver.Stub {
         boolean finished;
         boolean result;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index f12c284..3c7eef5 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1779,9 +1779,10 @@
 
         case START_BACKUP_AGENT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
-            ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data);
+            String packageName = data.readString();
             int backupRestoreMode = data.readInt();
-            boolean success = bindBackupAgent(info, backupRestoreMode);
+            int userId = data.readInt();
+            boolean success = bindBackupAgent(packageName, backupRestoreMode, userId);
             reply.writeNoException();
             reply.writeInt(success ? 1 : 0);
             return true;
@@ -4448,13 +4449,14 @@
         return binder;
     }
 
-    public boolean bindBackupAgent(ApplicationInfo app, int backupRestoreMode)
+    public boolean bindBackupAgent(String packageName, int backupRestoreMode, int userId)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
-        app.writeToParcel(data, 0);
+        data.writeString(packageName);
         data.writeInt(backupRestoreMode);
+        data.writeInt(userId);
         mRemote.transact(START_BACKUP_AGENT_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean success = reply.readInt() != 0;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 81788da..ac21346 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -250,7 +250,7 @@
     public IBinder peekService(Intent service, String resolvedType, String callingPackage)
             throws RemoteException;
 
-    public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode)
+    public boolean bindBackupAgent(String packageName, int backupRestoreMode, int userId)
             throws RemoteException;
     public void clearPendingBackup() throws RemoteException;
     public void backupAgentCreated(String packageName, IBinder agent) throws RemoteException;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index a4688d1..f56a6ad 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -274,7 +274,7 @@
                 if (libDir.endsWith(".apk")) {
                     // Avoid opening files we know do not have resources,
                     // like code-only .jar files.
-                    if (assets.addAssetPath(libDir) == 0) {
+                    if (assets.addAssetPathAsSharedLibrary(libDir) == 0) {
                         Log.w(TAG, "Asset path '" + libDir +
                                 "' does not exist or contains no resources.");
                     }
@@ -330,6 +330,22 @@
     }
 
     /**
+     * Finds a cached ResourcesImpl object that matches the given ResourcesKey, or
+     * creates a new one and caches it for future use.
+     * @param key The key to match.
+     * @return a ResourcesImpl object matching the key.
+     */
+    private @NonNull ResourcesImpl findOrCreateResourcesImplForKeyLocked(
+            @NonNull ResourcesKey key) {
+        ResourcesImpl impl = findResourcesImplForKeyLocked(key);
+        if (impl == null) {
+            impl = createResourcesImpl(key);
+            mResourceImpls.put(key, new WeakReference<>(impl));
+        }
+        return impl;
+    }
+
+    /**
      * Find the ResourcesKey that this ResourcesImpl object is associated with.
      * @return the ResourcesKey or null if none was found.
      */
@@ -811,4 +827,75 @@
             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
         }
     }
+
+    /**
+     * Appends the library asset path to any ResourcesImpl object that contains the main
+     * assetPath.
+     * @param assetPath The main asset path for which to add the library asset path.
+     * @param libAsset The library asset path to add.
+     */
+    public void appendLibAssetForMainAssetPath(String assetPath, String libAsset) {
+        synchronized (this) {
+            // Record which ResourcesImpl need updating
+            // (and what ResourcesKey they should update to).
+            final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>();
+
+            final int implCount = mResourceImpls.size();
+            for (int i = 0; i < implCount; i++) {
+                final ResourcesImpl impl = mResourceImpls.valueAt(i).get();
+                final ResourcesKey key = mResourceImpls.keyAt(i);
+                if (impl != null && key.mResDir.equals(assetPath)) {
+                    if (!ArrayUtils.contains(key.mLibDirs, libAsset)) {
+                        final int newLibAssetCount = 1 +
+                                (key.mLibDirs != null ? key.mLibDirs.length : 0);
+                        final String[] newLibAssets = new String[newLibAssetCount];
+                        if (key.mLibDirs != null) {
+                            System.arraycopy(key.mLibDirs, 0, newLibAssets, 0, key.mLibDirs.length);
+                        }
+                        newLibAssets[newLibAssetCount - 1] = libAsset;
+
+                        updatedResourceKeys.put(impl, new ResourcesKey(
+                                key.mResDir,
+                                key.mSplitResDirs,
+                                key.mOverlayDirs,
+                                newLibAssets,
+                                key.mDisplayId,
+                                key.mOverrideConfiguration,
+                                key.mCompatInfo));
+                    }
+                }
+            }
+
+            // Bail early if there is no work to do.
+            if (updatedResourceKeys.isEmpty()) {
+                return;
+            }
+
+            // Update any references to ResourcesImpl that require reloading.
+            final int resourcesCount = mResourceReferences.size();
+            for (int i = 0; i < resourcesCount; i++) {
+                final Resources r = mResourceReferences.get(i).get();
+                if (r != null) {
+                    final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
+                    if (key != null) {
+                        r.setImpl(findOrCreateResourcesImplForKeyLocked(key));
+                    }
+                }
+            }
+
+            // Update any references to ResourcesImpl that require reloading for each Activity.
+            for (ActivityResources activityResources : mActivityResourceReferences.values()) {
+                final int resCount = activityResources.activityResources.size();
+                for (int i = 0; i < resCount; i++) {
+                    final Resources r = activityResources.activityResources.get(i).get();
+                    if (r != null) {
+                        final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
+                        if (key != null) {
+                            r.setImpl(findOrCreateResourcesImplForKeyLocked(key));
+                        }
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 63afdd8..325a15f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3030,8 +3030,6 @@
      * @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
      *        {@code false} otherwise. This carries the risk that any failure of the VPN provider
      *        could break networking for all apps. This has no effect when clearing.
-     * @return {@code true} if the package is set as always-on VPN controller; {@code false}
-     *         otherwise.
      * @throws SecurityException if {@code admin} is not a device or a profile owner.
      * @throws NameNotFoundException if {@code vpnPackage} is not installed.
      * @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 5d4cc6f..a320bbf 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -218,6 +218,14 @@
     String[] listAllTransports();
 
     /**
+     * Retrieve the list of whitelisted transport components.  Callers do </i>not</i> need
+     * any special permission.
+     *
+     * @return The names of all whitelisted transport components defined by the system.
+     */
+    String[] getTransportWhitelist();
+
+    /**
      * Specify the current backup transport.  Callers must hold the
      * android.permission.BACKUP permission to use this method.
      *
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 720c84a..7961a72 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -305,7 +305,8 @@
      */
     public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
             UsageCallback callback) {
-        registerUsageCallback(networkType, subscriberId, thresholdBytes, null /* handler */);
+        registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
+                null /* handler */);
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9390bcd..47ae687 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -897,28 +897,10 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean enable() {
-        int state = BluetoothAdapter.STATE_OFF;
         if (isEnabled() == true) {
             if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
             return true;
         }
-        // Use service interface to get the exact state
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                state = mService.getState();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-
-        if (state == BluetoothAdapter.STATE_BLE_ON) {
-                Log.e(TAG, "BT is in BLE_ON State");
-                notifyUserAction(true);
-                return true;
-        }
         try {
             return mManagerService.enable();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index 014cb22..e70c936 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -138,7 +138,7 @@
     }
 
     boolean doBind() {
-        Intent intent = new Intent(IBluetoothMap.class.getName());
+        Intent intent = new Intent(IBluetoothSap.class.getName());
         ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
         intent.setComponent(comp);
         if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index ae12c88..ec01bef 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -532,22 +532,19 @@
                 if(length <= mMaxTxPacketSize) {
                     mSocketOS.write(b, offset, length);
                 } else {
-                    int tmpOffset = offset;
-                    int tmpLength = mMaxTxPacketSize;
-                    int endIndex = offset + length;
-                    boolean done = false;
                     if(DBG) Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n"
                             + "Packet will be divided into SDU packets of size "
                             + mMaxTxPacketSize);
-                    do{
+                    int tmpOffset = offset;
+                    int bytesToWrite = length;
+                    while (bytesToWrite > 0) {
+                        int tmpLength = (bytesToWrite > mMaxTxPacketSize)
+                                ? mMaxTxPacketSize
+                                : bytesToWrite;
                         mSocketOS.write(b, tmpOffset, tmpLength);
-                        tmpOffset += mMaxTxPacketSize;
-                        if((tmpOffset + mMaxTxPacketSize) > endIndex) {
-                            tmpLength = endIndex - tmpOffset;
-                            done = true;
-                        }
-                    } while(!done);
-
+                        tmpOffset += tmpLength;
+                        bytesToWrite -= tmpLength;
+                    }
                 }
             } else {
                 mSocketOS.write(b, offset, length);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8b3eac5..ca798f6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3644,6 +3644,12 @@
     public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
 
     /**
+     * Gatekeeper Service.
+     * @hide
+     */
+    public static final String GATEKEEPER_SERVICE = "android.service.gatekeeper.IGateKeeperService";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index df2c6fc..c140f1bd5 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1556,7 +1556,7 @@
 
     /**
      * Used as an int extra field with {@link #ACTION_INSTALL_PACKAGE} and
-     * {@link} #ACTION_VIEW} to indicate the uid of the package that initiated the install
+     * {@link #ACTION_VIEW} to indicate the uid of the package that initiated the install
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java
index 2b9cfa0..fc3b958 100644
--- a/core/java/android/content/pm/EphemeralResolveInfo.java
+++ b/core/java/android/content/pm/EphemeralResolveInfo.java
@@ -27,6 +27,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Information about an ephemeral application.
@@ -52,7 +53,7 @@
             throw new IllegalArgumentException();
         }
 
-        mDigest = new EphemeralDigest(uri, -1);
+        mDigest = new EphemeralDigest(uri, 0xFFFFFFFF, -1);
         mFilters.addAll(filters);
         mPackageName = packageName;
     }
@@ -134,7 +135,7 @@
         /** The first 4 bytes of the domain hashes */
         private final int[] mDigestPrefix;
 
-        public EphemeralDigest(@NonNull Uri uri, int maxDigests) {
+        public EphemeralDigest(@NonNull Uri uri, int digestMask, int maxDigests) {
             if (uri == null) {
                 throw new IllegalArgumentException();
             }
@@ -142,17 +143,18 @@
             mDigestPrefix = new int[mDigestBytes.length];
             for (int i = 0; i < mDigestBytes.length; i++) {
                 mDigestPrefix[i] =
-                        (mDigestBytes[i][0] & 0xFF) << 24
-                        | (mDigestBytes[i][1] & 0xFF) << 16
-                        | (mDigestBytes[i][2] & 0xFF) << 8
-                        | (mDigestBytes[i][3] & 0xFF) << 0;
+                        ((mDigestBytes[i][0] & 0xFF) << 24
+                                | (mDigestBytes[i][1] & 0xFF) << 16
+                                | (mDigestBytes[i][2] & 0xFF) << 8
+                                | (mDigestBytes[i][3] & 0xFF) << 0)
+                        & digestMask;
             }
         }
 
         private static byte[][] generateDigest(Uri uri, int maxDigests) {
             ArrayList<byte[]> digests = new ArrayList<>();
             try {
-                final String host = uri.getHost();
+                final String host = uri.getHost().toLowerCase(Locale.ENGLISH);
                 final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
                 if (maxDigests <= 0) {
                     final byte[] hostBytes = host.getBytes();
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 6cb50fc..a76bf24 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -171,8 +171,9 @@
          * as defined in {@link #hasShortcutHostPermission()}, will receive it.
          *
          * @param packageName The name of the package that has the shortcuts.
-         * @param shortcuts all shortcuts from the package (dynamic and/or pinned).  Only "key"
-         *    information will be provided, as defined in {@link ShortcutInfo#hasKeyFieldsOnly()}.
+         * @param shortcuts all shortcuts from the package (dynamic, manifest and/or pinned).
+         *    Only "key" information will be provided, as defined in
+         *    {@link ShortcutInfo#hasKeyFieldsOnly()}.
          * @param user The UserHandle of the profile that generated the change.
          */
         public void onShortcutsChanged(@NonNull String packageName,
@@ -199,6 +200,10 @@
          */
         public static final int FLAG_GET_MANIFEST = 1 << 3;
 
+        /** @hide */
+        public static final int FLAG_GET_ALL_KINDS =
+                FLAG_GET_DYNAMIC | FLAG_GET_PINNED | FLAG_GET_MANIFEST;
+
         /**
          * Requests "key" fields only.  See {@link ShortcutInfo#hasKeyFieldsOnly()} for which
          * fields are available.
@@ -485,7 +490,7 @@
         final ShortcutQuery q = new ShortcutQuery();
         q.setPackage(packageName);
         q.setShortcutIds(ids);
-        q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+        q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
         return getShortcuts(q, user);
     }
 
@@ -526,7 +531,7 @@
         final ShortcutQuery q = new ShortcutQuery();
         q.setPackage(packageName);
         q.setShortcutIds(Arrays.asList(shortcutId));
-        q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+        q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
         final List<ShortcutInfo> shortcuts = getShortcuts(q, user);
 
         return shortcuts.size() > 0 ? shortcuts.get(0).getIconResourceId() : 0;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 094b89d..8492fd8 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -30,6 +30,7 @@
 import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -62,6 +63,13 @@
 
     private static final String ANDROID_PACKAGE_NAME = "android";
 
+    private static final int IMPLICIT_RANK_MASK = 0x7fffffff;
+
+    private static final int RANK_CHANGED_BIT = ~IMPLICIT_RANK_MASK;
+
+    /** @hide */
+    public static final int RANK_NOT_SET = Integer.MAX_VALUE;
+
     /** @hide */
     public static final int FLAG_DYNAMIC = 1 << 0;
 
@@ -193,6 +201,15 @@
 
     private int mRank;
 
+    /**
+     * Internally used for auto-rank-adjustment.
+     *
+     * RANK_CHANGED_BIT is used to denote that the rank of a shortcut is changing.
+     * The rest of the bits are used to denote the order in which shortcuts are passed to
+     * APIs, which is used to preserve the argument order when ranks are tie.
+     */
+    private int mImplicitRank;
+
     @Nullable
     private PersistableBundle mExtras;
 
@@ -229,7 +246,7 @@
         mTextResId = b.mTextResId;
         mDisabledMessage = b.mDisabledMessage;
         mDisabledMessageResId = b.mDisabledMessageResId;
-        mCategories = clone(b.mCategories);
+        mCategories = cloneCategories(b.mCategories);
         mIntent = b.mIntent;
         if (mIntent != null) {
             final Bundle intentExtras = mIntent.getExtras();
@@ -243,8 +260,17 @@
         updateTimestamp();
     }
 
-    private <T> ArraySet<T> clone(Set<T> source) {
-        return (source == null) ? null : new ArraySet<>(source);
+    private ArraySet<String> cloneCategories(Set<String> source) {
+        if (source == null) {
+            return null;
+        }
+        final ArraySet<String> ret = new ArraySet<>(source.size());
+        for (CharSequence s : source) {
+            if (!TextUtils.isEmpty(s)) {
+                ret.add(s.toString().intern());
+            }
+        }
+        return ret;
     }
 
     /**
@@ -268,6 +294,7 @@
         mUserId = source.mUserId;
         mId = source.mId;
         mPackageName = source.mPackageName;
+        mActivity = source.mActivity;
         mFlags = source.mFlags;
         mLastChangedTimestamp = source.mLastChangedTimestamp;
 
@@ -275,7 +302,6 @@
         mIconResId = source.mIconResId;
 
         if ((cloneFlags & CLONE_REMOVE_NON_KEY_INFO) == 0) {
-            mActivity = source.mActivity;
 
             if ((cloneFlags & CLONE_REMOVE_ICON) == 0) {
                 mIcon = source.mIcon;
@@ -288,7 +314,7 @@
             mTextResId = source.mTextResId;
             mDisabledMessage = source.mDisabledMessage;
             mDisabledMessageResId = source.mDisabledMessageResId;
-            mCategories = clone(source.mCategories);
+            mCategories = cloneCategories(source.mCategories);
             if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) {
                 mIntent = source.mIntent;
                 mIntentPersistableExtras = source.mIntentPersistableExtras;
@@ -544,7 +570,8 @@
 
     /**
      * Copy non-null/zero fields from another {@link ShortcutInfo}.  Only "public" information
-     * will be overwritten.  The timestamp will be updated.
+     * will be overwritten.  The timestamp will *not* be updated to be consistent with other
+     * setters (and also the clock is not injectable in this file).
      *
      * - Flags will not change
      * - mBitmapPath will not change
@@ -597,20 +624,18 @@
             mDisabledMessageResName = null;
         }
         if (source.mCategories != null) {
-            mCategories = clone(source.mCategories);
+            mCategories = cloneCategories(source.mCategories);
         }
         if (source.mIntent != null) {
             mIntent = source.mIntent;
             mIntentPersistableExtras = source.mIntentPersistableExtras;
         }
-        if (source.mRank != 0) {
+        if (source.mRank != RANK_NOT_SET) {
             mRank = source.mRank;
         }
         if (source.mExtras != null) {
             mExtras = source.mExtras;
         }
-
-        updateTimestamp();
     }
 
     /**
@@ -665,7 +690,7 @@
 
         private Intent mIntent;
 
-        private int mRank;
+        private int mRank = RANK_NOT_SET;
 
         private PersistableBundle mExtras;
 
@@ -737,7 +762,7 @@
          * an icon.  The recommend max length is 10 characters.
          */
         @NonNull
-        public Builder setShortLabel(@NonNull String shortLabel) {
+        public Builder setShortLabel(@NonNull CharSequence shortLabel) {
             Preconditions.checkState(mTitleResId == 0, "shortLabelResId already set");
             mTitle = Preconditions.checkStringNotEmpty(shortLabel, "shortLabel");
             return this;
@@ -761,14 +786,14 @@
          * The recommend max length is 25 characters.
          */
         @NonNull
-        public Builder setLongLabel(@NonNull String longLabel) {
+        public Builder setLongLabel(@NonNull CharSequence longLabel) {
             Preconditions.checkState(mTextResId == 0, "longLabelResId already set");
             mText = Preconditions.checkStringNotEmpty(longLabel, "longLabel");
             return this;
         }
 
         /** @hide -- old signature, the internal code still uses it. */
-        public Builder setTitle(@NonNull String value) {
+        public Builder setTitle(@NonNull CharSequence value) {
             return setShortLabel(value);
         }
 
@@ -778,7 +803,7 @@
         }
 
         /** @hide -- old signature, the internal code still uses it. */
-        public Builder setText(@NonNull String value) {
+        public Builder setText(@NonNull CharSequence value) {
             return setLongLabel(value);
         }
 
@@ -798,7 +823,7 @@
         }
 
         @NonNull
-        public Builder setDisabledMessage(@NonNull String disabledMessage) {
+        public Builder setDisabledMessage(@NonNull CharSequence disabledMessage) {
             Preconditions.checkState(
                     mDisabledMessageResId == 0, "disabledMessageResId already set");
             mDisabledMessage =
@@ -825,15 +850,18 @@
         @NonNull
         public Builder setIntent(@NonNull Intent intent) {
             mIntent = Preconditions.checkNotNull(intent, "intent");
-            Preconditions.checkNotNull(mIntent.getAction(), "Intent action must be set.");
+            Preconditions.checkNotNull(mIntent.getAction(), "Intent action must be set");
             return this;
         }
 
         /**
-         * TODO javadoc.
+         * "Rank" of a shortcut, which is a non-negative value that's used by the launcher app
+         * to sort shortcuts.
          */
         @NonNull
         public Builder setRank(int rank) {
+            Preconditions.checkArgument((0 <= rank),
+                    "Rank cannot be negative or bigger than MAX_RANK");
             mRank = rank;
             return this;
         }
@@ -1014,12 +1042,57 @@
     }
 
     /**
-     * TODO Javadoc
+     * "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
+     * {@link #getActivity} for each of the two kinds, dynamic shortcuts and manifest shortcuts.
+     *
+     * <p>Because manifest shortcuts and dynamic shortcuts have overlapping ranks,
+     * when a launcher application shows shortcuts for an activity, it should first show
+     * the manifest shortcuts followed by the dynamic shortcuts.  Within each of those categories,
+     * shortcuts should be sorted by rank in ascending order.
+     *
+     * <p>"Floating" shortcuts (i.e. shortcuts that are neither dynamic nor manifest) will all
+     * have rank 0, because there's no sorting for them.
      */
     public int getRank() {
         return mRank;
     }
 
+    /** @hide */
+    public boolean hasRank() {
+        return mRank != RANK_NOT_SET;
+    }
+
+    /** @hide */
+    public void setRank(int rank) {
+        mRank = rank;
+    }
+
+    /** @hide */
+    public void clearImplicitRankAndRankChangedFlag() {
+        mImplicitRank = 0;
+    }
+
+    /** @hide */
+    public void setImplicitRank(int rank) {
+        // Make sure to keep RANK_CHANGED_BIT.
+        mImplicitRank = (mImplicitRank & RANK_CHANGED_BIT) | (rank & IMPLICIT_RANK_MASK);
+    }
+
+    /** @hide */
+    public int getImplicitRank() {
+        return mImplicitRank & IMPLICIT_RANK_MASK;
+    }
+
+    /** @hide */
+    public void setRankChanged() {
+        mImplicitRank |= RANK_CHANGED_BIT;
+    }
+
+    /** @hide */
+    public boolean isRankChanged() {
+        return (mImplicitRank & RANK_CHANGED_BIT) != 0;
+    }
+
     /**
      * Optional values that application can set.
      */
@@ -1179,6 +1252,7 @@
      * <ul>
      *     <li>{@link #getId()}
      *     <li>{@link #getPackage()}
+     *     <li>{@link #getActivity()}
      *     <li>{@link #getLastChangedTimestamp()}
      *     <li>{@link #isDynamic()}
      *     <li>{@link #isPinned()}
@@ -1292,6 +1366,37 @@
         mIconResName = iconResName;
     }
 
+    /**
+     * Replaces the intent
+     *
+     * @throws IllegalArgumentException when extra is not compatible with {@link PersistableBundle}.
+     *
+     * @hide
+     */
+    public void setIntent(Intent intent) throws IllegalArgumentException {
+        Preconditions.checkNotNull(intent);
+
+        final Bundle intentExtras = intent.getExtras();
+
+        mIntent = intent;
+
+        if (intentExtras != null) {
+            intent.replaceExtras((Bundle) null);
+            mIntentPersistableExtras = new PersistableBundle(intentExtras);
+        } else {
+            mIntentPersistableExtras = null;
+        }
+    }
+
+    /**
+     * Replaces the categories.
+     *
+     * @hide
+     */
+    public void setCategories(Set<String> categories) {
+        mCategories = cloneCategories(categories);
+    }
+
     private ShortcutInfo(Parcel source) {
         final ClassLoader cl = getClass().getClassLoader();
 
@@ -1299,6 +1404,14 @@
         mId = source.readString();
         mPackageName = source.readString();
         mActivity = source.readParcelable(cl);
+        mFlags = source.readInt();
+        mIconResId = source.readInt();
+        mLastChangedTimestamp = source.readLong();
+
+        if (source.readInt() == 0) {
+            return; // key information only.
+        }
+
         mIcon = source.readParcelable(cl);
         mTitle = source.readCharSequence();
         mTitleResId = source.readInt();
@@ -1310,9 +1423,6 @@
         mIntentPersistableExtras = source.readParcelable(cl);
         mRank = source.readInt();
         mExtras = source.readParcelable(cl);
-        mLastChangedTimestamp = source.readLong();
-        mFlags = source.readInt();
-        mIconResId = source.readInt();
         mBitmapPath = source.readString();
 
         mIconResName = source.readString();
@@ -1337,6 +1447,16 @@
         dest.writeString(mId);
         dest.writeString(mPackageName);
         dest.writeParcelable(mActivity, flags);
+        dest.writeInt(mFlags);
+        dest.writeInt(mIconResId);
+        dest.writeLong(mLastChangedTimestamp);
+
+        if (hasKeyFieldsOnly()) {
+            dest.writeInt(0);
+            return;
+        }
+        dest.writeInt(1);
+
         dest.writeParcelable(mIcon, flags);
         dest.writeCharSequence(mTitle);
         dest.writeInt(mTitleResId);
@@ -1349,9 +1469,6 @@
         dest.writeParcelable(mIntentPersistableExtras, flags);
         dest.writeInt(mRank);
         dest.writeParcelable(mExtras, flags);
-        dest.writeLong(mLastChangedTimestamp);
-        dest.writeInt(mFlags);
-        dest.writeInt(mIconResId);
         dest.writeString(mBitmapPath);
 
         dest.writeString(mIconResName);
@@ -1528,7 +1645,7 @@
         mDisabledMessage = disabledMessage;
         mDisabledMessageResId = disabledMessageResId;
         mDisabledMessageResName = disabledMessageResName;
-        mCategories = clone(categories);
+        mCategories = cloneCategories(categories);
         mIntent = intent;
         mIntentPersistableExtras = intentPersistableExtras;
         mRank = rank;
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index eaccb3a..36ab804 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.TestApi;
+import android.annotation.UserIdInt;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.os.RemoteException;
@@ -379,6 +380,22 @@
         }
     }
 
+    /**
+     * Called internally when an application is considered to have come to foreground
+     * even when technically it's not.  This method resets the throttling for this package.
+     * For example, when the user sends an "inline reply" on an notification, the system UI will
+     * call it.
+     *
+     * @hide
+     */
+    public void onApplicationActive(@NonNull String packageName, @UserIdInt int userId) {
+        try {
+            mService.onApplicationActive(packageName, userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide injection point */
     @VisibleForTesting
     protected int injectMyUserId() {
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 6f43d99..b2d518c 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1543,27 +1543,41 @@
      * @hide
      */
     public static String localesToResourceQualifier(LocaleList locs) {
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         for (int i = 0; i < locs.size(); i++) {
-            Locale loc = locs.get(i);
-            boolean l = (loc.getLanguage().length() != 0);
-            boolean c = (loc.getCountry().length() != 0);
-            boolean s = (loc.getScript().length() != 0);
-            boolean v = (loc.getVariant().length() != 0);
-            // TODO: take script and extensions into account
-            if (l) {
-                if (sb.length() != 0) {
-                    sb.append(",");
-                }
+            final Locale loc = locs.get(i);
+            final int l = loc.getLanguage().length();
+            if (l == 0) {
+                continue;
+            }
+            final int s = loc.getScript().length();
+            final int c = loc.getCountry().length();
+            final int v = loc.getVariant().length();
+            // We ignore locale extensions, since they are not supported by AAPT
+
+            if (sb.length() != 0) {
+                sb.append(",");
+            }
+            if (l == 2 && s == 0 && (c == 0 || c == 2) && v == 0) {
+                // Traditional locale format: xx or xx-rYY
                 sb.append(loc.getLanguage());
-                if (c) {
+                if (c == 2) {
                     sb.append("-r").append(loc.getCountry());
-                    if (s) {
-                        sb.append("-s").append(loc.getScript());
-                        if (v) {
-                            sb.append("-v").append(loc.getVariant());
-                        }
-                    }
+                }
+            } else {
+                sb.append("b+");
+                sb.append(loc.getLanguage());
+                if (s != 0) {
+                    sb.append("+");
+                    sb.append(loc.getScript());
+                }
+                if (c != 0) {
+                    sb.append("+");
+                    sb.append(loc.getCountry());
+                }
+                if (v != 0) {
+                    sb.append("+");
+                    sb.append(loc.getVariant());
                 }
             }
         }
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
index 10fc8e6..01a5404 100644
--- a/core/java/android/hardware/input/InputManagerInternal.java
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -59,4 +59,9 @@
      * @param deviceId The id of input device.
      */
     public abstract void toggleCapsLock(int deviceId);
+
+    /**
+     * Set whether the input stack should deliver pulse gesture events when the device is asleep.
+     */
+    public abstract void setPulseGestureEnabled(boolean enabled);
 }
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 8176189..43e596f 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -21,12 +21,15 @@
 import android.content.pm.PackageManager;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
 import android.util.Log;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * @hide
@@ -57,8 +60,11 @@
 
     private static final int OS_APP_INSTANCE = -1;
 
+    private static final long APP_ID_ACTIVITY_RECOGNITION = 0x476f6f676c001000L;
+
     private final Context mContext;
-    private final HashMap<Integer, NanoAppInstanceInfo> mNanoAppHash = new HashMap<>();
+    private final ConcurrentHashMap<Integer, NanoAppInstanceInfo> mNanoAppHash =
+            new ConcurrentHashMap<>();
     private final ContextHubInfo[] mContextHubInfo;
     private final RemoteCallbackList<IContextHubCallback> mCallbacksList =
             new RemoteCallbackList<>();
@@ -66,6 +72,18 @@
     private native int nativeSendMessage(int[] header, byte[] data);
     private native ContextHubInfo[] nativeInitialize();
 
+    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
+        @Override
+        public void onVrStateChanged(boolean enabled) {
+            for (NanoAppInstanceInfo app : mNanoAppHash.values()) {
+                if (app.getAppId() == APP_ID_ACTIVITY_RECOGNITION) {
+                    sendVrStateChangeMessageToApp(app, enabled);
+                    break;
+                }
+            }
+        }
+    };
+
     public ContextHubService(Context context) {
         mContext = context;
         mContextHubInfo = nativeInitialize();
@@ -74,6 +92,18 @@
             Log.d(TAG, "ContextHub[" + i + "] id: " + mContextHubInfo[i].getId()
                   + ", name:  " + mContextHubInfo[i].getName());
         }
+
+        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
+            IVrManager vrManager =
+                    IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
+            if (vrManager != null) {
+                try {
+                    vrManager.registerListener(mVrStateCallbacks);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "VR state listener registration failed", e);
+                }
+            }
+        }
     }
 
     @Override
@@ -277,4 +307,19 @@
 
         return 0;
     }
+
+    private void sendVrStateChangeMessageToApp(NanoAppInstanceInfo app, boolean vrModeEnabled) {
+        int[] msgHeader = new int[MSG_HEADER_SIZE];
+        msgHeader[MSG_FIELD_TYPE] = 0;
+        msgHeader[MSG_FIELD_VERSION] = 0;
+        msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB;
+        msgHeader[MSG_FIELD_APP_INSTANCE] = app.getHandle();
+
+        byte[] data = new byte[1];
+        data[0] = (byte) ((vrModeEnabled) ? 1 : 0);
+        int ret = nativeSendMessage(msgHeader, data);
+        if (ret != 0) {
+            Log.e(TAG, "Couldn't send VR state change notification (" + ret + ")!");
+        }
+    }
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index f4bf3ea..4acb729 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2385,6 +2385,13 @@
     public abstract LongCounter getDischargeCoulombCounter();
 
     /**
+     * Returns the estimated real battery capacity, which may be less than the capacity
+     * declared by the PowerProfile.
+     * @return The estimated battery capacity in mAh.
+     */
+    public abstract int getEstimatedBatteryCapacity();
+
+    /**
      * Return the array of discharge step durations.
      */
     public abstract LevelStepTracker getDischargeLevelStepTracker();
@@ -2836,7 +2843,8 @@
                 whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
                 totalRealtime / 1000, totalUptime / 1000,
                 getStartClockTime(),
-                whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000);
+                whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000,
+                getEstimatedBatteryCapacity());
 
         
         // Calculate wakelock times across all uids.
@@ -3348,6 +3356,16 @@
         final SparseArray<? extends Uid> uidStats = getUidStats();
         final int NU = uidStats.size();
 
+        final int estimatedBatteryCapacity = getEstimatedBatteryCapacity();
+        if (estimatedBatteryCapacity > 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                sb.append("  Estimated battery capacity: ");
+                sb.append(BatteryStatsHelper.makemAh(estimatedBatteryCapacity));
+                sb.append(" mAh");
+            pw.println(sb.toString());
+        }
+
         sb.setLength(0);
         sb.append(prefix);
                 sb.append("  Time on battery: ");
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 6af0678..80927f3 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -240,6 +240,22 @@
         return new File(getDataDirectory(), "system");
     }
 
+    /**
+     * Returns the base directory for per-user system directory, device encrypted.
+     * {@hide}
+     */
+    public static File getDataSystemDeDirectory() {
+        return buildPath(getDataDirectory(), "system_de");
+    }
+
+    /**
+     * Returns the base directory for per-user system directory, credential encrypted.
+     * {@hide}
+     */
+    public static File getDataSystemCeDirectory() {
+        return buildPath(getDataDirectory(), "system_ce");
+    }
+
     /** {@hide} */
     public static File getDataSystemCeDirectory(int userId) {
         return buildPath(getDataDirectory(), "system_ce", String.valueOf(userId));
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 082194b..cc2af21 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -38,8 +38,6 @@
     long addPowerSaveTempWhitelistAppForMms(String name, int userId, String reason);
     long addPowerSaveTempWhitelistAppForSms(String name, int userId, String reason);
     void exitIdle(String reason);
-    void downloadServiceActive(IBinder token);
-    void downloadServiceInactive();
     boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener);
     void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener);
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 4506f51..f664e70 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1184,6 +1184,8 @@
     /** @hide */
     public static final int PROC_QUOTES = 0x400;
     /** @hide */
+    public static final int PROC_CHAR = 0x800;
+    /** @hide */
     public static final int PROC_OUT_STRING = 0x1000;
     /** @hide */
     public static final int PROC_OUT_LONG = 0x2000;
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index b3cc438..507379b 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -759,7 +759,7 @@
 
                 if (line.startsWith("time")) {
                     timeTotal = scaled;
-                } else if (line.startsWith("source_version")) {
+                } else if (line.startsWith("source_build")) {
                     sourceVersion = scaled;
                 } else if (line.startsWith("bytes_written")) {
                     bytesWrittenInMiB = (bytesWrittenInMiB == -1) ? scaled :
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9b0ef8e..d742206 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1508,7 +1508,9 @@
     }
 
     /**
-     * Returns information for all users on this device.
+     * Returns information for all users on this device, including ones marked for deletion.
+     * To retrieve only users that are alive, use {@link #getUsers(boolean)}.
+     * <p>
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @return the list of users that exist on the device.
      * @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 88cf138..ca45e62 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1322,13 +1322,20 @@
 
     /**
      * @hide Key with the location in the {@link android.util.MemoryIntArray} where
-     * to look up the generation id of the backing table.
+     * to look up the generation id of the backing table. The value is an integer.
      *
      * @see #CALL_METHOD_TRACK_GENERATION_KEY
      */
     public static final String CALL_METHOD_GENERATION_INDEX_KEY = "_generation_index";
 
     /**
+     * @hide Key with the settings table generation. The value is an integer.
+     *
+     * @see #CALL_METHOD_TRACK_GENERATION_KEY
+     */
+    public static final String CALL_METHOD_GENERATION_KEY = "_generation";
+
+    /**
      * @hide - User handle argument extra to the fast-path call()-based requests
      */
     public static final String CALL_METHOD_USER_KEY = "_user";
@@ -1478,11 +1485,11 @@
         private int mCurrentGeneration;
 
         public GenerationTracker(@NonNull MemoryIntArray array, int index,
-                Runnable errorHandler) {
+                int generation, Runnable errorHandler) {
             mArray = array;
             mIndex = index;
             mErrorHandler = errorHandler;
-            mCurrentGeneration = readCurrentGeneration();
+            mCurrentGeneration = generation;
         }
 
         public boolean isGenerationChanged() {
@@ -1638,6 +1645,8 @@
                                     final int index = b.getInt(
                                             CALL_METHOD_GENERATION_INDEX_KEY, -1);
                                     if (array != null && index >= 0) {
+                                        final int generation = b.getInt(
+                                                CALL_METHOD_GENERATION_KEY, 0);
                                         if (DEBUG) {
                                             Log.i(TAG, "Received generation tracker for type:"
                                                     + mUri.getPath() + " in package:"
@@ -1645,7 +1654,7 @@
                                                     + userHandle + " with index:" + index);
                                         }
                                         mGenerationTracker = new GenerationTracker(array, index,
-                                                () -> {
+                                                generation, () -> {
                                             synchronized (this) {
                                                 Log.e(TAG, "Error accessing generation"
                                                         + " tracker - removing");
diff --git a/core/java/android/service/quicksettings/IQSTileService.aidl b/core/java/android/service/quicksettings/IQSTileService.aidl
index bfde8702..b6c830c 100644
--- a/core/java/android/service/quicksettings/IQSTileService.aidl
+++ b/core/java/android/service/quicksettings/IQSTileService.aidl
@@ -15,15 +15,10 @@
  */
 package android.service.quicksettings;
 
-import android.service.quicksettings.Tile;
-import android.service.quicksettings.IQSService;
-
 /**
  * @hide
  */
 oneway interface IQSTileService {
-    void setQSService(in IQSService service);
-    void setQSTile(in Tile tile);
     void onTileAdded();
     void onTileRemoved();
     void onStartListening();
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 4e9a075..67793fd 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -118,6 +118,16 @@
     /**
      * @hide
      */
+    public static final String EXTRA_SERVICE = "service";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_TILE = "tile";
+
+    /**
+     * @hide
+     */
     public static final String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
 
     private final H mHandler = new H(Looper.getMainLooper());
@@ -305,18 +315,11 @@
 
     @Override
     public IBinder onBind(Intent intent) {
+        mTile = intent.getParcelableExtra(EXTRA_TILE);
+        mService = IQSService.Stub.asInterface(intent.getIBinderExtra(EXTRA_SERVICE));
+        mTile.setService(mService);
         return new IQSTileService.Stub() {
             @Override
-            public void setQSService(IQSService service) throws RemoteException {
-                mHandler.obtainMessage(H.MSG_SET_SERVICE, service).sendToTarget();
-            }
-
-            @Override
-            public void setQSTile(Tile tile) throws RemoteException {
-                mHandler.obtainMessage(H.MSG_SET_TILE, tile).sendToTarget();
-            }
-
-            @Override
             public void onTileRemoved() throws RemoteException {
                 mHandler.sendEmptyMessage(H.MSG_TILE_REMOVED);
             }
@@ -349,14 +352,12 @@
     }
 
     private class H extends Handler {
-        private static final int MSG_SET_TILE = 1;
-        private static final int MSG_START_LISTENING = 2;
-        private static final int MSG_STOP_LISTENING = 3;
-        private static final int MSG_TILE_ADDED = 4;
-        private static final int MSG_TILE_REMOVED = 5;
-        private static final int MSG_TILE_CLICKED = 6;
-        private static final int MSG_SET_SERVICE = 7;
-        private static final int MSG_UNLOCK_COMPLETE = 8;
+        private static final int MSG_START_LISTENING = 1;
+        private static final int MSG_STOP_LISTENING = 2;
+        private static final int MSG_TILE_ADDED = 3;
+        private static final int MSG_TILE_REMOVED = 4;
+        private static final int MSG_TILE_CLICKED = 5;
+        private static final int MSG_UNLOCK_COMPLETE = 6;
 
         public H(Looper looper) {
             super(looper);
@@ -365,18 +366,6 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_SET_SERVICE:
-                    mService = (IQSService) msg.obj;
-                    if (mTile != null) {
-                        mTile.setService(mService);
-                    }
-                    break;
-                case MSG_SET_TILE:
-                    mTile = (Tile) msg.obj;
-                    if (mService != null && mTile != null) {
-                        mTile.setService(mService);
-                    }
-                    break;
                 case MSG_TILE_ADDED:
                     TileService.this.onTileAdded();
                     break;
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index d201adef..f4db4d6 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -66,9 +66,23 @@
      * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target,
      * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them.
      */
+    public static final int DENSITY_260 = 260;
+
+    /**
+     * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and
+     * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target,
+     * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them.
+     */
     public static final int DENSITY_280 = 280;
 
     /**
+     * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and
+     * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target,
+     * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them.
+     */
+    public static final int DENSITY_300 = 300;
+
+    /**
      * Standard quantized DPI for extra-high-density screens.
      */
     public static final int DENSITY_XHIGH = 320;
@@ -79,6 +93,14 @@
      * This is not a density that applications should target, instead relying
      * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
      */
+    public static final int DENSITY_340 = 340;
+
+    /**
+     * Intermediate density for screens that sit somewhere between
+     * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
+     * This is not a density that applications should target, instead relying
+     * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
+     */
     public static final int DENSITY_360 = 360;
 
     /**
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index f8a6a17..72126d0 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -106,12 +106,13 @@
      * @param alwaysFocusable True if the app windows are always focusable regardless of the stack
      *                        they are in.
      * @param homeTask True if this is the task.
+     * @param targetSdkVersion The application's target SDK version
      */
     void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
             int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
             int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
             in Rect taskBounds, in Configuration configuration, int taskResizeMode,
-            boolean alwaysFocusable, boolean homeTask);
+            boolean alwaysFocusable, boolean homeTask, int targetSdkVersion);
     /**
      *
      * @param token The token we are adding to the input task Id.
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 3069e5a..c46acae 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -22,6 +22,7 @@
 import android.graphics.Outline;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
@@ -63,6 +64,33 @@
             }
         }
     };
+    final AccessibilityDelegate mExpandDelegate = new AccessibilityDelegate() {
+
+        @Override
+        public boolean performAccessibilityAction(View host, int action, Bundle args) {
+            if (super.performAccessibilityAction(host, action, args)) {
+                return true;
+            }
+            if (action == AccessibilityNodeInfo.ACTION_COLLAPSE
+                    || action == AccessibilityNodeInfo.ACTION_EXPAND) {
+                mExpandClickListener.onClick(mExpandButton);
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+            super.onInitializeAccessibilityNodeInfo(host, info);
+            // Avoid that the button description is also spoken
+            info.setClassName(getClass().getName());
+            if (mExpanded) {
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
+            } else {
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
+            }
+        }
+    };
 
     public NotificationHeaderView(Context context) {
         this(context, null);
@@ -92,6 +120,9 @@
         mAppName = findViewById(com.android.internal.R.id.app_name_text);
         mHeaderText = findViewById(com.android.internal.R.id.header_text);
         mExpandButton = (ImageView) findViewById(com.android.internal.R.id.expand_button);
+        if (mExpandButton != null) {
+            mExpandButton.setAccessibilityDelegate(mExpandDelegate);
+        }
         mIcon = findViewById(com.android.internal.R.id.icon);
         mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
     }
@@ -230,7 +261,7 @@
     public void setOnClickListener(@Nullable OnClickListener l) {
         mExpandClickListener = l;
         setOnTouchListener(mExpandClickListener != null ? mTouchListener : null);
-        setFocusable(l != null);
+        mExpandButton.setOnClickListener(mExpandClickListener);
         updateTouchListener();
     }
 
@@ -380,19 +411,6 @@
         return this;
     }
 
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-        if (mExpandClickListener != null) {
-            AccessibilityNodeInfo.AccessibilityAction expand
-                    = new AccessibilityNodeInfo.AccessibilityAction(
-                    AccessibilityNodeInfo.ACTION_CLICK,
-                    getContext().getString(
-                            com.android.internal.R.string.expand_action_accessibility));
-            info.addAction(expand);
-        }
-    }
-
     public ImageView getExpandButton() {
         return mExpandButton;
     }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index d59c8ac..17834fb 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -464,7 +464,8 @@
             || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
             getLocationInWindow(mLocation);
 
-            if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
+            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                    + "Changes: creating=" + creating
                     + " format=" + formatChanged + " size=" + sizeChanged
                     + " visible=" + visibleChanged
                     + " left=" + (mWindowSpaceLeft != mLocation[0])
@@ -534,7 +535,8 @@
                     mReportDrawNeeded = false;
                     mDrawingStopped = !visible;
 
-                    if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
+                    if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                            + "Cur surface: " + mSurface);
 
                     relayoutResult = mSession.relayout(
                         mWindow, mWindow.mSeq, mLayout, mWindowSpaceWidth, mWindowSpaceHeight,
@@ -547,7 +549,8 @@
                         reportDrawNeeded = true;
                     }
 
-                    if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
+                    if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                            + "New surface: " + mNewSurface
                             + ", vis=" + visible + ", frame=" + mWinFrame);
 
                     mSurfaceFrame.left = 0;
@@ -581,7 +584,8 @@
                     if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
                         mSurfaceCreated = false;
                         if (mSurface.isValid()) {
-                            if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed");
+                            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                                    + "visibleChanged -- surfaceDestroyed");
                             callbacks = getSurfaceCallbacks();
                             for (SurfaceHolder.Callback c : callbacks) {
                                 c.surfaceDestroyed(mSurfaceHolder);
@@ -594,7 +598,8 @@
                         if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
                             mSurfaceCreated = true;
                             mIsCreating = true;
-                            if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated");
+                            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                                    + "visibleChanged -- surfaceCreated");
                             if (callbacks == null) {
                                 callbacks = getSurfaceCallbacks();
                             }
@@ -604,7 +609,8 @@
                         }
                         if (creating || formatChanged || sizeChanged
                                 || visibleChanged || realSizeChanged) {
-                            if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat
+                            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                                    + "surfaceChanged -- format=" + mFormat
                                     + " w=" + myWidth + " h=" + myHeight);
                             if (callbacks == null) {
                                 callbacks = getSurfaceCallbacks();
@@ -614,7 +620,8 @@
                             }
                         }
                         if (redrawNeeded) {
-                            if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded");
+                            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                                    + "surfaceRedrawNeeded");
                             if (callbacks == null) {
                                 callbacks = getSurfaceCallbacks();
                             }
@@ -629,7 +636,8 @@
                 } finally {
                     mIsCreating = false;
                     if (redrawNeeded) {
-                        if (DEBUG) Log.i(TAG, "finishedDrawing");
+                        if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+                                + "finishedDrawing");
                         mSession.finishDrawing(mWindow);
                     }
                     mSession.performDeferredDestroy(mWindow);
@@ -663,8 +671,9 @@
                 }
 
                 try {
-                    Log.d(TAG, String.format("updateWindowPosition UI, " +
-                            "postion = [%d, %d, %d, %d]", mWinFrame.left, mWinFrame.top,
+                    Log.d(TAG, String.format("%d updateWindowPosition UI, " +
+                            "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
+                            mWinFrame.left, mWinFrame.top,
                             mWinFrame.right, mWinFrame.bottom));
                     mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top,
                             mWinFrame.right, mWinFrame.bottom, -1, mWinFrame);
@@ -697,9 +706,9 @@
         }
         try {
             if (DEBUG) {
-                Log.d(TAG, String.format("updateWindowPosition RT, frameNr = %d, " +
-                        "postion = [%d, %d, %d, %d]", frameNumber, left, top,
-                        right, bottom));
+                Log.d(TAG, String.format("%d updateWindowPosition RT, frameNr = %d, " +
+                        "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
+                        frameNumber, left, top, right, bottom));
             }
             // Just using mRTLastReportedPosition as a dummy rect here
             session.repositionChild(window, left, top, right, bottom,
@@ -712,6 +721,25 @@
         }
     }
 
+    /**
+     * Called by native on RenderThread to notify that the window is no longer in the
+     * draw tree
+     * @hide
+     */
+    public final void windowPositionLostRT(long frameNumber) {
+        if (DEBUG) {
+            Log.d(TAG, String.format("%d windowPositionLostRT RT, frameNr = %d",
+                    System.identityHashCode(this), frameNumber));
+        }
+        // TODO: This is a bit of a hack as we don't have an API to report to WM
+        // to hide a window with a frameNumber, so just shift the window very far into
+        // negative space which will do effectively the same thing.
+        // Use the last reported size to avoid influencing the size of the bufferqueue
+        int x = -1000 - mRTLastReportedPosition.width();
+        int y = -1000 - mRTLastReportedPosition.height();
+        updateWindowPositionRT(frameNumber, x, y, -1000, -1000);
+    }
+
     private SurfaceHolder.Callback[] getSurfaceCallbacks() {
         SurfaceHolder.Callback callbacks[];
         synchronized (mCallbacks) {
@@ -750,8 +778,7 @@
                 boolean alwaysConsumeNavBar) {
             SurfaceView surfaceView = mSurfaceView.get();
             if (surfaceView != null) {
-                if (DEBUG) Log.v(
-                        "SurfaceView", surfaceView + " got resized: w=" + frame.width()
+                if (DEBUG) Log.v(TAG, surfaceView + " got resized: w=" + frame.width()
                         + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
                 surfaceView.mSurfaceLock.lock();
                 try {
@@ -907,7 +934,7 @@
         private final Canvas internalLockCanvas(Rect dirty) {
             mSurfaceLock.lock();
 
-            if (DEBUG) Log.i(TAG, "Locking canvas... stopped="
+            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped="
                     + mDrawingStopped + ", win=" + mWindow);
 
             Canvas c = null;
@@ -919,7 +946,7 @@
                 }
             }
 
-            if (DEBUG) Log.i(TAG, "Returned canvas: " + c);
+            if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Returned canvas: " + c);
             if (c != null) {
                 mLastLockTime = SystemClock.uptimeMillis();
                 return c;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 65f0caa..1186569 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1822,6 +1822,19 @@
                             + mAttachInfo.mVisibleInsets);
                 }
 
+                // If any of the insets changed, do a forceLayout on the view so that the
+                // measure cache is cleared. We might have a pending MSG_RESIZED_REPORT
+                // that is supposed to take care of it, but since pending insets are
+                // already modified here, it won't detect the frame change after this.
+                final boolean framesChanged = overscanInsetsChanged
+                        || contentInsetsChanged
+                        || stableInsetsChanged
+                        || visibleInsetsChanged
+                        || outsetsChanged;
+                if (mAdded && mView != null && framesChanged) {
+                    forceLayout(mView);
+                }
+
                 if (!hadSurface) {
                     if (mSurface.isValid()) {
                         // If we are creating a new surface, then we need to
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 7c3fc8b..0ebbf7f 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -855,5 +855,5 @@
     /**
      * The default implementation does nothing.
      */
-    public boolean insertContent(InputContentInfo inputContentInfo, Bundle opts) { return false; }
+    public boolean commitContent(InputContentInfo inputContentInfo, Bundle opts) { return false; }
 }
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 7ed0d27..2dca892 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -368,10 +368,10 @@
 
     /**
      * List of acceptable MIME types for
-     * {@link InputConnection#insertContent(InputContentInfo, Bundle)}.
+     * {@link InputConnection#commitContent(InputContentInfo, Bundle)}.
      *
      * <p>{@code null} or an empty array means that
-     * {@link InputConnection#insertContent(InputContentInfo, Bundle)} is not supported in this
+     * {@link InputConnection#commitContent(InputContentInfo, Bundle)} is not supported in this
      * editor.</p>
      */
     @Nullable
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 05e0569..f7f3694 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -840,7 +840,7 @@
     public void closeConnection();
 
     /**
-     * Called by the input method to insert a content such as PNG image to the editor.
+     * Called by the input method to commit a content such as PNG image to the editor.
      *
      * <p>In order to avoid variety of compatibility issues, this focuses on a simple use case,
      * where we expect editors and IMEs work cooperatively as follows:</p>
@@ -866,5 +866,5 @@
      * @return {@code true} if this request is accepted by the application, no matter if the request
      * is already handled or still being handled in background.
      */
-    public boolean insertContent(@NonNull InputContentInfo inputContentInfo, @Nullable Bundle opts);
+    public boolean commitContent(@NonNull InputContentInfo inputContentInfo, @Nullable Bundle opts);
 }
diff --git a/core/java/android/view/inputmethod/InputConnectionInspector.java b/core/java/android/view/inputmethod/InputConnectionInspector.java
index fb24fcd..727e9ca 100644
--- a/core/java/android/view/inputmethod/InputConnectionInspector.java
+++ b/core/java/android/view/inputmethod/InputConnectionInspector.java
@@ -43,7 +43,7 @@
             MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS,
             MissingMethodFlags.GET_HANDLER,
             MissingMethodFlags.CLOSE_CONNECTION,
-            MissingMethodFlags.INSERT_CONTENT,
+            MissingMethodFlags.COMMIT_CONTENT,
     })
     public @interface MissingMethodFlags {
         /**
@@ -82,10 +82,10 @@
          */
         int CLOSE_CONNECTION = 1 << 6;
         /**
-         * {@link InputConnection#insertContent(InputContentInfo, Bundle)} is available in
+         * {@link InputConnection#commitContent(InputContentInfo, Bundle)} is available in
          * {@link android.os.Build.VERSION_CODES#N} MR-1 and later.
          */
-        int INSERT_CONTENT = 1 << 7;
+        int COMMIT_CONTENT = 1 << 7;
     }
 
     private static final Map<Class, Integer> sMissingMethodsMap = Collections.synchronizedMap(
@@ -135,8 +135,8 @@
         if (!hasCloseConnection(clazz)) {
             flags |= MissingMethodFlags.CLOSE_CONNECTION;
         }
-        if (!hasInsertContent(clazz)) {
-            flags |= MissingMethodFlags.INSERT_CONTENT;
+        if (!hasCommitContent(clazz)) {
+            flags |= MissingMethodFlags.COMMIT_CONTENT;
         }
         sMissingMethodsMap.put(clazz, flags);
         return flags;
@@ -206,9 +206,9 @@
         }
     }
 
-    private static boolean hasInsertContent(@NonNull final Class clazz) {
+    private static boolean hasCommitContent(@NonNull final Class clazz) {
         try {
-            final Method method = clazz.getMethod("insertContent", InputContentInfo.class,
+            final Method method = clazz.getMethod("commitContent", InputContentInfo.class,
                     Bundle.class);
             return !Modifier.isAbstract(method.getModifiers());
         } catch (NoSuchMethodException e) {
@@ -263,11 +263,11 @@
             }
             sb.append("closeConnection()");
         }
-        if ((flags & MissingMethodFlags.INSERT_CONTENT) != 0) {
+        if ((flags & MissingMethodFlags.COMMIT_CONTENT) != 0) {
             if (!isEmpty) {
                 sb.append(",");
             }
-            sb.append("InsertContent(InputContentInfo, Bundle)");
+            sb.append("commitContent(InputContentInfo, Bundle)");
         }
         return sb.toString();
     }
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index 431836a..af9bcae 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -274,7 +274,7 @@
      * {@inheritDoc}
      * @throws NullPointerException if the target is {@code null}.
      */
-    public boolean insertContent(InputContentInfo inputContentInfo, Bundle opts) {
-        return mTarget.insertContent(inputContentInfo, opts);
+    public boolean commitContent(InputContentInfo inputContentInfo, Bundle opts) {
+        return mTarget.commitContent(inputContentInfo, opts);
     }
 }
diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java
index 9e73af2..2cdff79 100644
--- a/core/java/android/webkit/WebViewDelegate.java
+++ b/core/java/android/webkit/WebViewDelegate.java
@@ -21,7 +21,9 @@
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.app.Application;
+import android.app.ResourcesManager;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.os.SystemProperties;
@@ -31,6 +33,8 @@
 import android.view.View;
 import android.view.ViewRootImpl;
 
+import com.android.internal.util.ArrayUtils;
+
 /**
  * Delegate used by the WebView provider implementation to access
  * the required framework functionality needed to implement a {@link WebView}.
@@ -177,7 +181,29 @@
      * Adds the WebView asset path to {@link android.content.res.AssetManager}.
      */
     public void addWebViewAssetPath(Context context) {
-        context.getAssets().addAssetPathAsSharedLibrary(
-                WebViewFactory.getLoadedPackageInfo().applicationInfo.sourceDir);
+        final String newAssetPath = WebViewFactory.getLoadedPackageInfo().applicationInfo.sourceDir;
+
+        final ApplicationInfo appInfo = context.getApplicationInfo();
+        final String[] libs = appInfo.sharedLibraryFiles;
+        if (!ArrayUtils.contains(libs, newAssetPath)) {
+            // Build the new library asset path list.
+            final int newLibAssetsCount = 1 + (libs != null ? libs.length : 0);
+            final String[] newLibAssets = new String[newLibAssetsCount];
+            if (libs != null) {
+                System.arraycopy(libs, 0, newLibAssets, 0, libs.length);
+            }
+            newLibAssets[newLibAssetsCount - 1] = newAssetPath;
+
+            // Update the ApplicationInfo object with the new list.
+            // We know this will persist and future Resources created via ResourcesManager
+            // will include the shared library because this ApplicationInfo comes from the
+            // underlying LoadedApk in ContextImpl, which does not change during the life of the
+            // application.
+            appInfo.sharedLibraryFiles = newLibAssets;
+
+            // Update existing Resources with the WebView library.
+            ResourcesManager.getInstance().appendLibAssetForMainAssetPath(
+                    appInfo.getBaseResourcePath(), newAssetPath);
+        }
     }
 }
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 2d1e0bd..15eb8de 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -141,17 +141,38 @@
      */
     public static int loadWebViewNativeLibraryFromPackage(String packageName,
                                                           ClassLoader clazzLoader) {
-        int ret = waitForProviderAndSetPackageInfo();
-        if (ret != LIBLOAD_SUCCESS && ret != LIBLOAD_FAILED_WAITING_FOR_RELRO) {
-            return ret;
+        WebViewProviderResponse response = null;
+        try {
+            response = getUpdateService().waitForAndGetProvider();
+        } catch (RemoteException e) {
+            Log.e(LOGTAG, "error waiting for relro creation", e);
+            return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN;
         }
-        if (!sPackageInfo.packageName.equals(packageName))
+
+
+        if (response.status != LIBLOAD_SUCCESS
+                && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) {
+            return response.status;
+        }
+        if (!response.packageInfo.packageName.equals(packageName)) {
             return LIBLOAD_WRONG_PACKAGE_NAME;
+        }
+
+        PackageManager packageManager = AppGlobals.getInitialApplication().getPackageManager();
+        PackageInfo packageInfo;
+        try {
+            packageInfo = packageManager.getPackageInfo(packageName,
+                    PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(LOGTAG, "Couldn't find package " + packageName);
+            return LIBLOAD_WRONG_PACKAGE_NAME;
+        }
+        sPackageInfo = packageInfo;
 
         int loadNativeRet = loadNativeLibrary(clazzLoader);
         // If we failed waiting for relro we want to return that fact even if we successfully load
         // the relro file.
-        if (loadNativeRet == LIBLOAD_SUCCESS) return ret;
+        if (loadNativeRet == LIBLOAD_SUCCESS) return response.status;
         return loadNativeRet;
     }
 
@@ -288,7 +309,7 @@
                 Context webViewContext = initialApplication.createApplicationContext(
                         newPackageInfo.applicationInfo,
                         Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
-                sPackageInfo = response.packageInfo;
+                sPackageInfo = newPackageInfo;
                 return webViewContext;
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
@@ -599,22 +620,6 @@
         }
     }
 
-    private static int waitForProviderAndSetPackageInfo() {
-        WebViewProviderResponse response = null;
-        try {
-            response =
-                getUpdateService().waitForAndGetProvider();
-            if (response.status == LIBLOAD_SUCCESS
-                    || response.status == LIBLOAD_FAILED_WAITING_FOR_RELRO) {
-                sPackageInfo = response.packageInfo;
-            }
-        } catch (RemoteException e) {
-            Log.e(LOGTAG, "error waiting for relro creation", e);
-            return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN;
-        }
-        return response.status;
-    }
-
     // Assumes that we have waited for relro creation and set sPackageInfo
     private static int loadNativeLibrary(ClassLoader clazzLoader) {
         if (!sAddressSpaceReserved) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index fb532e2..f296421 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -19,7 +19,6 @@
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
-import android.content.ClipData;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -5986,8 +5985,8 @@
         }
 
         @Override
-        public boolean insertContent(InputContentInfo inputContentInfo, Bundle opts) {
-            return getTarget().insertContent(inputContentInfo, opts);
+        public boolean commitContent(InputContentInfo inputContentInfo, Bundle opts) {
+            return getTarget().commitContent(inputContentInfo, opts);
         }
     }
 
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 9cdb73a..0988c92 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -161,7 +161,7 @@
     private int mTitleMarginTop;
     private int mTitleMarginBottom;
 
-    private final RtlSpacingHelper mContentInsets = new RtlSpacingHelper();
+    private RtlSpacingHelper mContentInsets;
     private int mContentInsetStartWithNavigation;
     private int mContentInsetEndWithActions;
 
@@ -270,6 +270,7 @@
         final int contentInsetRight =
                 a.getDimensionPixelSize(R.styleable.Toolbar_contentInsetRight, 0);
 
+        ensureContentInsets();
         mContentInsets.setAbsolute(contentInsetLeft, contentInsetRight);
 
         if (contentInsetStart != RtlSpacingHelper.UNDEFINED ||
@@ -463,13 +464,13 @@
      */
     public void setTitleMarginBottom(int margin) {
         mTitleMarginBottom = margin;
-
         requestLayout();
     }
 
     @Override
     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
         super.onRtlPropertiesChanged(layoutDirection);
+        ensureContentInsets();
         mContentInsets.setDirection(layoutDirection == LAYOUT_DIRECTION_RTL);
     }
 
@@ -1092,6 +1093,7 @@
      * @attr ref android.R.styleable#Toolbar_contentInsetStart
      */
     public void setContentInsetsRelative(int contentInsetStart, int contentInsetEnd) {
+        ensureContentInsets();
         mContentInsets.setRelative(contentInsetStart, contentInsetEnd);
     }
 
@@ -1112,7 +1114,7 @@
      * @attr ref android.R.styleable#Toolbar_contentInsetStart
      */
     public int getContentInsetStart() {
-        return mContentInsets.getStart();
+        return mContentInsets != null ? mContentInsets.getStart() : 0;
     }
 
     /**
@@ -1132,7 +1134,7 @@
      * @attr ref android.R.styleable#Toolbar_contentInsetEnd
      */
     public int getContentInsetEnd() {
-        return mContentInsets.getEnd();
+        return mContentInsets != null ? mContentInsets.getEnd() : 0;
     }
 
     /**
@@ -1154,6 +1156,7 @@
      * @attr ref android.R.styleable#Toolbar_contentInsetRight
      */
     public void setContentInsetsAbsolute(int contentInsetLeft, int contentInsetRight) {
+        ensureContentInsets();
         mContentInsets.setAbsolute(contentInsetLeft, contentInsetRight);
     }
 
@@ -1174,7 +1177,7 @@
      * @attr ref android.R.styleable#Toolbar_contentInsetLeft
      */
     public int getContentInsetLeft() {
-        return mContentInsets.getLeft();
+        return mContentInsets != null ? mContentInsets.getLeft() : 0;
     }
 
     /**
@@ -1194,7 +1197,7 @@
      * @attr ref android.R.styleable#Toolbar_contentInsetRight
      */
     public int getContentInsetRight() {
-        return mContentInsets.getRight();
+        return mContentInsets != null ? mContentInsets.getRight() : 0;
     }
 
     /**
@@ -2128,6 +2131,12 @@
         }
     }
 
+    private void ensureContentInsets() {
+        if (mContentInsets == null) {
+            mContentInsets = new RtlSpacingHelper();
+        }
+    }
+
     /**
      * Accessor to enable LayoutLib to get ActionMenuPresenter directly.
      */
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 04929a7..d0719ee 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -45,6 +45,7 @@
  * default locale.</p>
  */
 public class LocalePickerWithRegion extends ListFragment implements SearchView.OnQueryTextListener {
+    private static final String PARENT_FRAGMENT_NAME = "localeListEditor";
 
     private SuggestedLocaleAdapter mAdapter;
     private LocaleSelectedListener mListener;
@@ -130,11 +131,24 @@
         return true;
     }
 
+    private void returnToParentFrame() {
+        getFragmentManager().popBackStack(PARENT_FRAGMENT_NAME,
+                FragmentManager.POP_BACK_STACK_INCLUSIVE);
+    }
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setHasOptionsMenu(true);
 
+        if (mLocaleList == null) {
+            // The fragment was killed and restored by the FragmentManager.
+            // At this point we have no data, no listener. Just return, to prevend a NPE.
+            // Fixes b/28748150. Created b/29400003 for a cleaner solution.
+            returnToParentFrame();
+            return;
+        }
+
         final boolean countryMode = mParentLocale != null;
         final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault();
         mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode);
@@ -197,8 +211,7 @@
             if (mListener != null) {
                 mListener.onLocaleSelected(locale);
             }
-            getFragmentManager().popBackStack("localeListEditor",
-                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
+            returnToParentFrame();
         } else {
             LocalePickerWithRegion selector = LocalePickerWithRegion.createCountryPicker(
                     getContext(), mListener, locale, mTranslatedOnly /* translate only */);
@@ -208,8 +221,7 @@
                         .replace(getId(), selector).addToBackStack(null)
                         .commit();
             } else {
-                getFragmentManager().popBackStack("localeListEditor",
-                        FragmentManager.POP_BACK_STACK_INCLUSIVE);
+                returnToParentFrame();
             }
         }
     }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 07d38d7..f853e04 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -108,7 +108,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 146 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 147 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -547,6 +547,8 @@
     private int mLoadedNumConnectivityChange;
     private int mUnpluggedNumConnectivityChange;
 
+    private int mEstimatedBatteryCapacity = -1;
+
     private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
 
     private PowerProfile mPowerProfile;
@@ -578,6 +580,11 @@
         return mDischargeCounter;
     }
 
+    @Override
+    public int getEstimatedBatteryCapacity() {
+        return mEstimatedBatteryCapacity;
+    }
+
     public BatteryStatsImpl() {
         this(new SystemClocks());
     }
@@ -7625,6 +7632,11 @@
                         numSpeedSteps);
                 firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
             }
+
+            if (mEstimatedBatteryCapacity == -1) {
+                // Initialize the estimated battery capacity to a known preset one.
+                mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
+            }
         }
     }
 
@@ -8174,6 +8186,7 @@
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             mScreenBrightnessTimer[i].reset(false);
         }
+        mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
         mInteractiveTimer.reset(false);
         mPowerSaveModeEnabledTimer.reset(false);
         mLastIdleTimeStart = elapsedRealtimeMillis;
@@ -9158,7 +9171,7 @@
     }
 
     void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
-            final int oldStatus, final int level) {
+            final int oldStatus, final int level, final int chargeUAh) {
         boolean doWrite = false;
         Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
         m.arg1 = onBattery ? 1 : 0;
@@ -9212,6 +9225,10 @@
                 }
                 doWrite = true;
                 resetAllStatsLocked();
+                if (chargeUAh > 0) {
+                    // Only use the reported coulomb charge value if it is supported and reported.
+                    mEstimatedBatteryCapacity = (int) ((level / 100.0) * (chargeUAh / 1000));
+                }
                 mDischargeStartLevel = level;
                 reset = true;
                 mDischargeStepTracker.init();
@@ -9379,7 +9396,7 @@
                 mDischargeScreenOffCounter.addCountLocked(chargeDiff);
             }
             mHistoryCur.batteryChargeUAh = chargeUAh;
-            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
+            setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
         } else {
             boolean changed = false;
             if (mHistoryCur.batteryLevel != level) {
@@ -10093,6 +10110,7 @@
         mDischargePlugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
         mCurrentBatteryLevel = in.readInt();
+        mEstimatedBatteryCapacity = in.readInt();
         mLowDischargeAmountSinceCharge = in.readInt();
         mHighDischargeAmountSinceCharge = in.readInt();
         mDischargeAmountScreenOnSinceCharge = in.readInt();
@@ -10445,6 +10463,7 @@
         out.writeInt(mDischargePlugLevel);
         out.writeInt(mDischargeCurrentLevel);
         out.writeInt(mCurrentBatteryLevel);
+        out.writeInt(mEstimatedBatteryCapacity);
         out.writeInt(getLowDischargeAmountSinceCharge());
         out.writeInt(getHighDischargeAmountSinceCharge());
         out.writeInt(getDischargeAmountScreenOnSinceCharge());
@@ -10809,6 +10828,7 @@
         mRealtime = in.readLong();
         mRealtimeStart = in.readLong();
         mOnBattery = in.readInt() != 0;
+        mEstimatedBatteryCapacity = in.readInt();
         mOnBatteryInternal = false; // we are no longer really running.
         mOnBatteryTimeBase.readFromParcel(in);
         mOnBatteryScreenOffTimeBase.readFromParcel(in);
@@ -10992,6 +11012,7 @@
         out.writeLong(mRealtime);
         out.writeLong(mRealtimeStart);
         out.writeInt(mOnBattery ? 1 : 0);
+        out.writeInt(mEstimatedBatteryCapacity);
         mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
         mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 9c960c0..73a3a0b 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -753,7 +753,7 @@
             closeServerSocket();
         } catch (MethodAndArgsCaller caller) {
             caller.run();
-        } catch (RuntimeException ex) {
+        } catch (Throwable ex) {
             Log.e(TAG, "Zygote died with exception", ex);
             closeServerSocket();
             throw ex;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index fc189a3..dce9d2c 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -62,7 +62,7 @@
     private static final int DO_CLEAR_META_KEY_STATES = 130;
     private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
     private static final int DO_CLOSE_CONNECTION = 150;
-    private static final int DO_INSERT_CONTENT = 160;
+    private static final int DO_COMMIT_CONTENT = 160;
 
     @GuardedBy("mLock")
     @Nullable
@@ -243,9 +243,9 @@
         dispatchMessage(obtainMessage(DO_CLOSE_CONNECTION));
     }
 
-    public void insertContent(InputContentInfo inputContentInfo, Bundle opts,
+    public void commitContent(InputContentInfo inputContentInfo, Bundle opts,
             int seq, IInputContextCallback callback) {
-        dispatchMessage(obtainMessageOOSC(DO_INSERT_CONTENT, inputContentInfo, opts, seq, callback));
+        dispatchMessage(obtainMessageOOSC(DO_COMMIT_CONTENT, inputContentInfo, opts, seq, callback));
     }
 
     void dispatchMessage(Message msg) {
@@ -559,26 +559,26 @@
                 }
                 return;
             }
-            case DO_INSERT_CONTENT: {
+            case DO_COMMIT_CONTENT: {
                 SomeArgs args = (SomeArgs) msg.obj;
                 try {
                     InputConnection ic = getInputConnection();
                     if (ic == null || !isActive()) {
-                        Log.w(TAG, "insertContent on inactive InputConnection");
-                        args.callback.setInsertContentResult(false, args.seq);
+                        Log.w(TAG, "commitContent on inactive InputConnection");
+                        args.callback.setCommitContentResult(false, args.seq);
                         return;
                     }
                     final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1;
                     if (inputContentInfo == null || !inputContentInfo.validate()) {
-                        Log.w(TAG, "insertContent with invalid inputContentInfo="
+                        Log.w(TAG, "commitContent with invalid inputContentInfo="
                                 + inputContentInfo);
-                        args.callback.setInsertContentResult(false, args.seq);
+                        args.callback.setCommitContentResult(false, args.seq);
                         return;
                     }
-                    args.callback.setInsertContentResult(
-                            ic.insertContent(inputContentInfo, (Bundle) args.arg2), args.seq);
+                    args.callback.setCommitContentResult(
+                            ic.commitContent(inputContentInfo, (Bundle) args.arg2), args.seq);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "Got RemoteException calling insertContent", e);
+                    Log.w(TAG, "Got RemoteException calling commitContent", e);
                 }
                 return;
             }
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index bd47355..0d5c8a1 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -78,6 +78,6 @@
     void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq,
             IInputContextCallback callback);
 
-    void insertContent(in InputContentInfo inputContentInfo, in Bundle opts, int sec,
+    void commitContent(in InputContentInfo inputContentInfo, in Bundle opts, int sec,
             IInputContextCallback callback);
 }
diff --git a/core/java/com/android/internal/view/IInputContextCallback.aidl b/core/java/com/android/internal/view/IInputContextCallback.aidl
index 933cdc0..0f40a83 100644
--- a/core/java/com/android/internal/view/IInputContextCallback.aidl
+++ b/core/java/com/android/internal/view/IInputContextCallback.aidl
@@ -28,5 +28,5 @@
     void setExtractedText(in ExtractedText extractedText, int seq);
     void setSelectedText(CharSequence selectedText, int seq);
     void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq);
-    void setInsertContentResult(boolean result, int seq);
+    void setCommitContentResult(boolean result, int seq);
 }
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 6d4d45c..5e78ec5 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.view;
 
-import android.content.ClipData;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -48,7 +47,7 @@
         public ExtractedText mExtractedText;
         public int mCursorCapsMode;
         public boolean mRequestUpdateCursorAnchorInfoResult;
-        public boolean mInsertContentResult;
+        public boolean mCommitContentResult;
 
         // A 'pool' of one InputContextCallback.  Each ICW request will attempt to gain
         // exclusive access to this object.
@@ -175,15 +174,15 @@
             }
         }
 
-        public void setInsertContentResult(boolean result, int seq) {
+        public void setCommitContentResult(boolean result, int seq) {
             synchronized (this) {
                 if (seq == mSeq) {
-                    mInsertContentResult = result;
+                    mCommitContentResult = result;
                     mHaveValue = true;
                     notifyAll();
                 } else {
                     Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
-                            + ") in setInsertContentResult, ignoring.");
+                            + ") in setCommitContentResult, ignoring.");
                 }
             }
         }
@@ -507,19 +506,19 @@
         // Nothing should happen when called from input method.
     }
 
-    public boolean insertContent(InputContentInfo inputContentInfo, Bundle opts) {
+    public boolean commitContent(InputContentInfo inputContentInfo, Bundle opts) {
         boolean result = false;
-        if (isMethodMissing(MissingMethodFlags.INSERT_CONTENT)) {
+        if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
             // This method is not implemented.
             return false;
         }
         try {
             InputContextCallback callback = InputContextCallback.getInstance();
-            mIInputContext.insertContent(inputContentInfo, opts, callback.mSeq, callback);
+            mIInputContext.commitContent(inputContentInfo, opts, callback.mSeq, callback);
             synchronized (callback) {
                 callback.waitForResultLocked();
                 if (callback.mHaveValue) {
-                    result = callback.mInsertContentResult;
+                    result = callback.mCommitContentResult;
                 }
             }
             callback.dispose();
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
new file mode 100644
index 0000000..f4f49b1
--- /dev/null
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.widget;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.RemoteViews;
+
+/**
+ * An expand button in a notification
+ */
+@RemoteViews.RemoteView
+public class NotificationExpandButton extends ImageView {
+    public NotificationExpandButton(Context context) {
+        super(context);
+    }
+
+    public NotificationExpandButton(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public NotificationExpandButton(Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public NotificationExpandButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
+        super.getBoundsOnScreen(outRect, clipToParent);
+        extendRectToMinTouchSize(outRect);
+    }
+
+    private void extendRectToMinTouchSize(Rect rect) {
+        int touchTargetSize = (int) (getResources().getDisplayMetrics().density * 48);
+        rect.left = rect.centerX() - touchTargetSize / 2;
+        rect.right = rect.left + touchTargetSize;
+        rect.top = rect.centerY() - touchTargetSize / 2;
+        rect.bottom = rect.top + touchTargetSize;
+    }
+}
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index f7a5e8a..3d952b0 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -832,6 +832,7 @@
     PROC_COMBINE = 0x100,
     PROC_PARENS = 0x200,
     PROC_QUOTES = 0x400,
+    PROC_CHAR = 0x800,
     PROC_OUT_STRING = 0x1000,
     PROC_OUT_LONG = 0x2000,
     PROC_OUT_FLOAT = 0x4000,
@@ -933,8 +934,13 @@
                 floatsData[di] = strtof(buffer+start, &end);
             }
             if ((mode&PROC_OUT_LONG) != 0 && di < NL) {
-                char* end;
-                longsData[di] = strtoll(buffer+start, &end, 10);
+                if ((mode&PROC_CHAR) != 0) {
+                    // Caller wants single first character returned as one long.
+                    longsData[di] = buffer[start];
+                } else {
+                    char* end;
+                    longsData[di] = strtoll(buffer+start, &end, 10);
+                }
             }
             if ((mode&PROC_OUT_STRING) != 0 && di < NS) {
                 jstring str = env->NewStringUTF(buffer+start);
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index a6db0f4..4fc546c 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -534,6 +534,7 @@
 // ----------------------------------------------------------------------------
 
 jmethodID gSurfaceViewPositionUpdateMethod;
+jmethodID gSurfaceViewPositionLostMethod;
 
 static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
         jlong renderNodePtr, jobject surfaceview) {
@@ -581,6 +582,20 @@
             info.canvasContext.enqueueFrameWork(std::move(functor));
         }
 
+        virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
+            if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
+
+            if (info) {
+                auto functor = std::bind(
+                    std::mem_fn(&SurfaceViewPositionUpdater::doNotifyPositionLost), this,
+                    (jlong) info->canvasContext.getFrameNumber());
+
+                info->canvasContext.enqueueFrameWork(std::move(functor));
+            } else {
+                doNotifyPositionLost(0);
+            }
+        }
+
     private:
         JNIEnv* jnienv() {
             JNIEnv* env;
@@ -607,6 +622,21 @@
             env->DeleteLocalRef(localref);
         }
 
+        void doNotifyPositionLost(jlong frameNumber) {
+            ATRACE_NAME("SurfaceView position lost");
+
+            JNIEnv* env = jnienv();
+            jobject localref = env->NewLocalRef(mWeakRef);
+            if (CC_UNLIKELY(!localref)) {
+                jnienv()->DeleteWeakGlobalRef(mWeakRef);
+                mWeakRef = nullptr;
+                return;
+            }
+
+            env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod, frameNumber);
+            env->DeleteLocalRef(localref);
+        }
+
         JavaVM* mVm;
         jobject mWeakRef;
     };
@@ -701,6 +731,8 @@
     jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
     gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
             "updateWindowPositionRT", "(JIIII)V");
+    gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
+            "windowPositionLostRT", "(J)V");
     clazz = FindClassOrDie(env, "android/view/RenderNode");
     gOnRenderNodeDetached = GetMethodIDOrDie(env, clazz,
             "onRenderNodeDetached", "()V");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 89036dd..3783dc8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -469,13 +469,6 @@
     <protected-broadcast android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" />
     <protected-broadcast android:name="com.android.server.notification.CountdownConditionProvider" />
 
-    <protected-broadcast android:name="com.android.ims.IMS_SERVICE_UP" />
-    <protected-broadcast android:name="com.android.ims.IMS_INCOMING_CALL" />
-    <protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_UP" />
-    <protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_DOWN" />
-    <protected-broadcast android:name="com.android.intent.action.IMS_FEATURE_CHANGED" />
-    <protected-broadcast android:name="com.android.intent.action.IMS_CONFIG_CHANGED" />
-
     <protected-broadcast android:name="com.android.internal.location.ALARM_WAKEUP" />
     <protected-broadcast android:name="com.android.internal.location.ALARM_TIMEOUT" />
     <protected-broadcast android:name="android.intent.action.GLOBAL_BUTTON" />
diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
index 28fbea5..b08b0f4 100644
--- a/core/res/res/layout/immersive_mode_cling.xml
+++ b/core/res/res/layout/immersive_mode_cling.xml
@@ -16,7 +16,7 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="#ff009688"
+        android:background="?android:attr/colorAccent"
         android:gravity="center_vertical"
         android:paddingBottom="24dp">
 
@@ -47,7 +47,7 @@
                 android:paddingTop="8dp"
                 android:scaleType="center"
                 android:src="@drawable/ic_expand_more_48dp"
-                android:tint="#ff009688"/>
+                android:tint="?android:attr/colorAccent"/>
     </FrameLayout>
 
     <TextView
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 38ea92a..38f671c2 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -89,7 +89,7 @@
         android:layout="@layout/notification_template_part_chronometer"
         android:visibility="gone"
         />
-    <ImageView
+    <com.android.internal.widget.NotificationExpandButton
         android:id="@+id/expand_button"
         android:background="@null"
         android:layout_width="wrap_content"
diff --git a/core/res/res/values-af-watch/styles_material.xml b/core/res/res/values-af-watch/styles_material.xml
new file mode 100644
index 0000000..80a5fa6
--- /dev/null
+++ b/core/res/res/values-af-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"kandidate"</font></string>
+</resources>
diff --git a/core/res/res/values-am-watch/styles_material.xml b/core/res/res/values-am-watch/styles_material.xml
new file mode 100644
index 0000000..5ec383a8
--- /dev/null
+++ b/core/res/res/values-am-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"እጩዎች"</font></string>
+</resources>
diff --git a/core/res/res/values-ar-watch/styles_material.xml b/core/res/res/values-ar-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-ar-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-az-rAZ-watch/styles_material.xml b/core/res/res/values-az-rAZ-watch/styles_material.xml
new file mode 100644
index 0000000..b621266
--- /dev/null
+++ b/core/res/res/values-az-rAZ-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"namizədlər"</font></string>
+</resources>
diff --git a/core/res/res/values-bg-watch/styles_material.xml b/core/res/res/values-bg-watch/styles_material.xml
new file mode 100644
index 0000000..89c3366
--- /dev/null
+++ b/core/res/res/values-bg-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"кандидати"</font></string>
+</resources>
diff --git a/core/res/res/values-bn-rBD-watch/styles_material.xml b/core/res/res/values-bn-rBD-watch/styles_material.xml
new file mode 100644
index 0000000..cd59902
--- /dev/null
+++ b/core/res/res/values-bn-rBD-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"প্রার্থীরা"</font></string>
+</resources>
diff --git a/core/res/res/values-ca-watch/styles_material.xml b/core/res/res/values-ca-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-ca-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-cs-watch/styles_material.xml b/core/res/res/values-cs-watch/styles_material.xml
new file mode 100644
index 0000000..5b604e8
--- /dev/null
+++ b/core/res/res/values-cs-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"kandidáti"</font></string>
+</resources>
diff --git a/core/res/res/values-da-watch/styles_material.xml b/core/res/res/values-da-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-da-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-de-watch/styles_material.xml b/core/res/res/values-de-watch/styles_material.xml
new file mode 100644
index 0000000..891a647
--- /dev/null
+++ b/core/res/res/values-de-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"Kandidaten"</font></string>
+</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index dc30013..79a2dba 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -245,7 +245,7 @@
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Kontakte"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"auf deine Kontakte zugreifen"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Standort"</string>
-    <string name="permgroupdesc_location" msgid="1346617465127855033">"auf den Standort deines Geräts zugreifen"</string>
+    <string name="permgroupdesc_location" msgid="1346617465127855033">"auf den Standort deines Geräts zuzugreifen"</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalender"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"auf deinen Kalender zugreifen"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
diff --git a/core/res/res/values-el-watch/styles_material.xml b/core/res/res/values-el-watch/styles_material.xml
new file mode 100644
index 0000000..a02b85e
--- /dev/null
+++ b/core/res/res/values-el-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"υποψήφιοι"</font></string>
+</resources>
diff --git a/core/res/res/values-en-rAU-watch/styles_material.xml b/core/res/res/values-en-rAU-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-en-rAU-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-en-rGB-watch/styles_material.xml b/core/res/res/values-en-rGB-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-en-rGB-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-en-rIN-watch/styles_material.xml b/core/res/res/values-en-rIN-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-en-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-es-rUS-watch/styles_material.xml b/core/res/res/values-es-rUS-watch/styles_material.xml
new file mode 100644
index 0000000..898d2fd
--- /dev/null
+++ b/core/res/res/values-es-rUS-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidatos"</font></string>
+</resources>
diff --git a/core/res/res/values-es-watch/styles_material.xml b/core/res/res/values-es-watch/styles_material.xml
new file mode 100644
index 0000000..898d2fd
--- /dev/null
+++ b/core/res/res/values-es-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidatos"</font></string>
+</resources>
diff --git a/core/res/res/values-et-rEE-watch/styles_material.xml b/core/res/res/values-et-rEE-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-et-rEE-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-eu-rES-watch/styles_material.xml b/core/res/res/values-eu-rES-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-eu-rES-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-fa-watch/styles_material.xml b/core/res/res/values-fa-watch/styles_material.xml
new file mode 100644
index 0000000..23b9a7e
--- /dev/null
+++ b/core/res/res/values-fa-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"کاندیدها"</font></string>
+</resources>
diff --git a/core/res/res/values-fi-watch/styles_material.xml b/core/res/res/values-fi-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-fi-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-fr-rCA-watch/styles_material.xml b/core/res/res/values-fr-rCA-watch/styles_material.xml
new file mode 100644
index 0000000..f692d5c
--- /dev/null
+++ b/core/res/res/values-fr-rCA-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidats"</font></string>
+</resources>
diff --git a/core/res/res/values-fr-watch/styles_material.xml b/core/res/res/values-fr-watch/styles_material.xml
new file mode 100644
index 0000000..f692d5c
--- /dev/null
+++ b/core/res/res/values-fr-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidats"</font></string>
+</resources>
diff --git a/core/res/res/values-gl-rES-watch/styles_material.xml b/core/res/res/values-gl-rES-watch/styles_material.xml
new file mode 100644
index 0000000..898d2fd
--- /dev/null
+++ b/core/res/res/values-gl-rES-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidatos"</font></string>
+</resources>
diff --git a/core/res/res/values-gu-rIN-watch/styles_material.xml b/core/res/res/values-gu-rIN-watch/styles_material.xml
new file mode 100644
index 0000000..21c6871
--- /dev/null
+++ b/core/res/res/values-gu-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"ઉમેદવારો"</font></string>
+</resources>
diff --git a/core/res/res/values-hi-watch/styles_material.xml b/core/res/res/values-hi-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-hi-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-hr-watch/styles_material.xml b/core/res/res/values-hr-watch/styles_material.xml
new file mode 100644
index 0000000..88e5751
--- /dev/null
+++ b/core/res/res/values-hr-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"kandidati"</font></string>
+</resources>
diff --git a/core/res/res/values-hu-watch/styles_material.xml b/core/res/res/values-hu-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-hu-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-hy-rAM-watch/styles_material.xml b/core/res/res/values-hy-rAM-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-hy-rAM-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-in-watch/styles_material.xml b/core/res/res/values-in-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-in-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-is-rIS-watch/styles_material.xml b/core/res/res/values-is-rIS-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-is-rIS-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-it-watch/styles_material.xml b/core/res/res/values-it-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-it-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-iw-watch/styles_material.xml b/core/res/res/values-iw-watch/styles_material.xml
new file mode 100644
index 0000000..f44b272
--- /dev/null
+++ b/core/res/res/values-iw-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"מועמדים"</font></string>
+</resources>
diff --git a/core/res/res/values-ja-watch/styles_material.xml b/core/res/res/values-ja-watch/styles_material.xml
new file mode 100644
index 0000000..7712090
--- /dev/null
+++ b/core/res/res/values-ja-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"候補"</font></string>
+</resources>
diff --git a/core/res/res/values-ka-rGE-watch/styles_material.xml b/core/res/res/values-ka-rGE-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-ka-rGE-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-kk-rKZ-watch/styles_material.xml b/core/res/res/values-kk-rKZ-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-kk-rKZ-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-km-rKH-watch/styles_material.xml b/core/res/res/values-km-rKH-watch/styles_material.xml
new file mode 100644
index 0000000..e54cb00
--- /dev/null
+++ b/core/res/res/values-km-rKH-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"បេក្ខជន"</font></string>
+</resources>
diff --git a/core/res/res/values-kn-rIN-watch/styles_material.xml b/core/res/res/values-kn-rIN-watch/styles_material.xml
new file mode 100644
index 0000000..1ec23a4
--- /dev/null
+++ b/core/res/res/values-kn-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"ಅಭ್ಯರ್ಥಿಗಳು"</font></string>
+</resources>
diff --git a/core/res/res/values-ko-watch/styles_material.xml b/core/res/res/values-ko-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-ko-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-ky-rKG-watch/styles_material.xml b/core/res/res/values-ky-rKG-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-ky-rKG-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-lo-rLA-watch/styles_material.xml b/core/res/res/values-lo-rLA-watch/styles_material.xml
new file mode 100644
index 0000000..1f845b9
--- /dev/null
+++ b/core/res/res/values-lo-rLA-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"ແຄນດິເດດ"</font></string>
+</resources>
diff --git a/core/res/res/values-lt-watch/styles_material.xml b/core/res/res/values-lt-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-lt-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-lv-watch/styles_material.xml b/core/res/res/values-lv-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-lv-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-mk-rMK-watch/styles_material.xml b/core/res/res/values-mk-rMK-watch/styles_material.xml
new file mode 100644
index 0000000..89c3366
--- /dev/null
+++ b/core/res/res/values-mk-rMK-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"кандидати"</font></string>
+</resources>
diff --git a/core/res/res/values-ml-rIN-watch/styles_material.xml b/core/res/res/values-ml-rIN-watch/styles_material.xml
new file mode 100644
index 0000000..9d38c0d
--- /dev/null
+++ b/core/res/res/values-ml-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"കാൻഡിഡേറ്റുകൾ"</font></string>
+</resources>
diff --git a/core/res/res/values-mn-rMN-watch/styles_material.xml b/core/res/res/values-mn-rMN-watch/styles_material.xml
new file mode 100644
index 0000000..f65ea48
--- /dev/null
+++ b/core/res/res/values-mn-rMN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"нэр дэвшигч"</font></string>
+</resources>
diff --git a/core/res/res/values-mr-rIN-watch/styles_material.xml b/core/res/res/values-mr-rIN-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-mr-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-ms-rMY-watch/styles_material.xml b/core/res/res/values-ms-rMY-watch/styles_material.xml
new file mode 100644
index 0000000..3f5e687
--- /dev/null
+++ b/core/res/res/values-ms-rMY-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"calon"</font></string>
+</resources>
diff --git a/core/res/res/values-my-rMM-watch/styles_material.xml b/core/res/res/values-my-rMM-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-my-rMM-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-nb-watch/styles_material.xml b/core/res/res/values-nb-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-nb-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-ne-rNP-watch/styles_material.xml b/core/res/res/values-ne-rNP-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-ne-rNP-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-nl-watch/styles_material.xml b/core/res/res/values-nl-watch/styles_material.xml
new file mode 100644
index 0000000..b821347
--- /dev/null
+++ b/core/res/res/values-nl-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"kandidaten"</font></string>
+</resources>
diff --git a/core/res/res/values-pa-rIN-watch/styles_material.xml b/core/res/res/values-pa-rIN-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-pa-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-pl-watch/styles_material.xml b/core/res/res/values-pl-watch/styles_material.xml
new file mode 100644
index 0000000..384d91c
--- /dev/null
+++ b/core/res/res/values-pl-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"elementy"</font></string>
+</resources>
diff --git a/core/res/res/values-pt-rBR-watch/styles_material.xml b/core/res/res/values-pt-rBR-watch/styles_material.xml
new file mode 100644
index 0000000..898d2fd
--- /dev/null
+++ b/core/res/res/values-pt-rBR-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidatos"</font></string>
+</resources>
diff --git a/core/res/res/values-pt-rPT-watch/styles_material.xml b/core/res/res/values-pt-rPT-watch/styles_material.xml
new file mode 100644
index 0000000..898d2fd
--- /dev/null
+++ b/core/res/res/values-pt-rPT-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidatos"</font></string>
+</resources>
diff --git a/core/res/res/values-pt-watch/styles_material.xml b/core/res/res/values-pt-watch/styles_material.xml
new file mode 100644
index 0000000..898d2fd
--- /dev/null
+++ b/core/res/res/values-pt-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidatos"</font></string>
+</resources>
diff --git a/core/res/res/values-ro-watch/styles_material.xml b/core/res/res/values-ro-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-ro-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-ru-watch/styles_material.xml b/core/res/res/values-ru-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-ru-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-si-rLK-watch/styles_material.xml b/core/res/res/values-si-rLK-watch/styles_material.xml
new file mode 100644
index 0000000..37b4afe
--- /dev/null
+++ b/core/res/res/values-si-rLK-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"අපේක්ෂකයන්"</font></string>
+</resources>
diff --git a/core/res/res/values-sk-watch/styles_material.xml b/core/res/res/values-sk-watch/styles_material.xml
new file mode 100644
index 0000000..5b604e8
--- /dev/null
+++ b/core/res/res/values-sk-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"kandidáti"</font></string>
+</resources>
diff --git a/core/res/res/values-sl-watch/styles_material.xml b/core/res/res/values-sl-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-sl-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-sq-rAL-watch/styles_material.xml b/core/res/res/values-sq-rAL-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-sq-rAL-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-sr-watch/styles_material.xml b/core/res/res/values-sr-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-sr-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-sv-watch/styles_material.xml b/core/res/res/values-sv-watch/styles_material.xml
new file mode 100644
index 0000000..f2ab18a
--- /dev/null
+++ b/core/res/res/values-sv-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"kandidater"</font></string>
+</resources>
diff --git a/core/res/res/values-sw-watch/styles_material.xml b/core/res/res/values-sw-watch/styles_material.xml
new file mode 100644
index 0000000..01392b2
--- /dev/null
+++ b/core/res/res/values-sw-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"yanayopendekezwa"</font></string>
+</resources>
diff --git a/core/res/res/values-ta-rIN-watch/styles_material.xml b/core/res/res/values-ta-rIN-watch/styles_material.xml
new file mode 100644
index 0000000..d4605e6
--- /dev/null
+++ b/core/res/res/values-ta-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"கேன்டிடேட்ஸ்"</font></string>
+</resources>
diff --git a/core/res/res/values-te-rIN-watch/styles_material.xml b/core/res/res/values-te-rIN-watch/styles_material.xml
new file mode 100644
index 0000000..877cd58
--- /dev/null
+++ b/core/res/res/values-te-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"క్యాండిడేట్‌లు"</font></string>
+</resources>
diff --git a/core/res/res/values-th-watch/styles_material.xml b/core/res/res/values-th-watch/styles_material.xml
new file mode 100644
index 0000000..3227ced
--- /dev/null
+++ b/core/res/res/values-th-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"ผู้สมัคร"</font></string>
+</resources>
diff --git a/core/res/res/values-tl-watch/styles_material.xml b/core/res/res/values-tl-watch/styles_material.xml
new file mode 100644
index 0000000..70e7a7a
--- /dev/null
+++ b/core/res/res/values-tl-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"mga kandidato"</font></string>
+</resources>
diff --git a/core/res/res/values-tr-watch/styles_material.xml b/core/res/res/values-tr-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-tr-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-uk-watch/styles_material.xml b/core/res/res/values-uk-watch/styles_material.xml
new file mode 100644
index 0000000..698d5b0
--- /dev/null
+++ b/core/res/res/values-uk-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"варіанти"</font></string>
+</resources>
diff --git a/core/res/res/values-ur-rPK-watch/styles_material.xml b/core/res/res/values-ur-rPK-watch/styles_material.xml
new file mode 100644
index 0000000..e569c7c
--- /dev/null
+++ b/core/res/res/values-ur-rPK-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"امیدواران"</font></string>
+</resources>
diff --git a/core/res/res/values-uz-rUZ-watch/styles_material.xml b/core/res/res/values-uz-rUZ-watch/styles_material.xml
new file mode 100644
index 0000000..3cb38d6
--- /dev/null
+++ b/core/res/res/values-uz-rUZ-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"nomzodlar"</font></string>
+</resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index d777ea0..71f5a9f 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -526,7 +526,7 @@
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"Ekran qulfini o‘zgartiradi."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Ekranni qulflash"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"Ekranning qachon va qanday qulflanishini boshqaradi."</string>
-    <string name="policylab_wipeData" msgid="3910545446758639713">"Barcha ma’lumotlarni tozalash"</string>
+    <string name="policylab_wipeData" msgid="3910545446758639713">"Barcha ma’lumotlarni o‘chirib tashlash"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Planshetdagi barcha ma’lumotlarni ogohlantirishsiz zavod sozlamalarini tiklash orqali o‘chirib tashlaydi."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Zavod sozlamalarini tiklaydi va televizordagi barcha ma’lumotlarni ogohlantirishsiz o‘chirib tashlaydi."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Telefondagi barcha ma’lumotlarni ogohlantirishsiz zavod sozlamalarini tiklash orqali o‘chirib tashlaydi."</string>
@@ -537,7 +537,7 @@
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Qurilmaga global proksi o‘rnatish"</string>
     <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Qoida faollashtirilgan vaqtda ishlatiladigan qurilmaning global proksi-serverini o‘rnatadi. Faqat qurilma egasi global proksi-serverini o‘rnatishi mumkin."</string>
     <string name="policylab_expirePassword" msgid="5610055012328825874">"Parol muddatini o‘rnatish"</string>
-    <string name="policydesc_expirePassword" msgid="5367525762204416046">"Ekran qulfi paroli, PIN kodi yoki chizmali paroli o‘zgartiriladigan muddatni o‘zgartiradi."</string>
+    <string name="policydesc_expirePassword" msgid="5367525762204416046">"Ekran qulfi paroli, PIN kodi yoki grafik kaliti o‘zgartiriladigan muddatni o‘zgartiradi."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Xotirani kodlashni o‘rnatish"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Zaxiralangan ilovalar ma‘lumotlarini kodlashni talab qiladi."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Kameralarni o‘chirish"</string>
@@ -672,7 +672,7 @@
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Ekran qulflangan."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Qulfdan chiqarish yoki favqulodda qo‘ng‘iroqni amalga oshirish uchun \"Menyu\"ni bosing."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Qulfni ochish uchun \"Menyu\"ga bosing."</string>
-    <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Qulfni ochish uchun namuna ustiga chizing"</string>
+    <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Qulfni ochish uchun grafik kalitni chizing"</string>
     <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Favqulodda chaqiruv"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Qo‘ng‘iroqni qaytarish"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"To‘g‘ri!"</string>
@@ -700,12 +700,12 @@
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Foydalanuvchi qo‘llanmasiga qarang yoki Abonentlarni qo‘llab-quvvatlash markaziga murojaat qiling."</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM karta qulflangan."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM karta qulfdan chiqarilmoqda…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urining."</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urining."</string>
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Siz parolni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urining."</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Siz PIN-kodni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urining."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Telefon qulfini ochish uchun yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri urinish qilsangiz, sizdan Google hisobingizga kirish talab qilinadi. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qayta urining."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizni qulfdan chiqarish uchun Google hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qaytadan urining."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Telefon qulfini ochish uchun yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri urinish qilsangiz, sizdan Google hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qayta urining."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Telefon qulfini ochish uchun yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri urinish qilsangiz, sizdan Google hisobingizga kirish talab qilinadi. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qayta urining."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizni qulfdan chiqarish uchun Google hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qaytadan urining."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Telefon qulfini ochish uchun yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri urinish qilsangiz, sizdan Google hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qayta urining."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Planshet qulfini <xliff:g id="NUMBER_0">%1$d</xliff:g> marta ochishga urinib ko‘rdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishlardan so‘ng, planshet ishlab chiqarilgan holatiga tiklanadi va barcha foydalanuvchi ma’lumotlari yo‘qoladi."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Siz televizorni qulfdan chiqarish parolini <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizda zavod sozlamalari qayta tiklanadi hamda undagi barcha ma’lumotlaringiz o‘chib ketadi."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Telefon qulfini <xliff:g id="NUMBER_0">%1$d</xliff:g> marta ochishga urinib ko‘rdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishlardan so‘ng, telefon ishlab chiqarilgan holatiga tiklanadi va barcha foydalanuvchi ma’lumotlari yo‘qoladi."</string>
@@ -713,9 +713,9 @@
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Siz televizorni qulfdan chiqarish parolini <xliff:g id="NUMBER">%d</xliff:g> marta noto‘g‘ri kiritdingiz. Endi, televizoringizda zavod sozlamalari qayta tiklanadi."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Telefon qulfini <xliff:g id="NUMBER">%d</xliff:g> marta ochishga urinib ko‘rdingiz. Telefon hozir ishlab chiqarilgan holatiga tiklanadi."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
-    <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Chizma namunasi yodingizdan chiqdimi?"</string>
+    <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Grafik kalit esingizdan chiqdimi?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Qulfni ochish hisobi"</string>
-    <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Chizmali parolni ochishga juda ko‘p urinildi"</string>
+    <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Grafik kalit juda ko‘p marta chizildi"</string>
     <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Qulfni ochish uchun Google hisobingiz bilan kiring."</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Foydalanuvchi nomi (e-pochta)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Parol"</string>
@@ -726,12 +726,12 @@
     <string name="lockscreen_unlock_label" msgid="737440483220667054">"Qulfdan chiqarish"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Ovozni yoqish"</string>
     <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Ovozni o‘chirish"</string>
-    <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Chizma namunasi ishga tushirildi"</string>
-    <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Chizma namunasi tozalandi"</string>
+    <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Grafik kalitni chizish boshlandi"</string>
+    <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Grafik kalit tozalandi"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Katak qo‘shildi"</string>
     <string name="lockscreen_access_pattern_cell_added_verbose" msgid="7264580781744026939">"<xliff:g id="CELL_INDEX">%1$s</xliff:g> katak qo‘shildi"</string>
-    <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Chizma namunasi tugatildi"</string>
-    <string name="lockscreen_access_pattern_area" msgid="400813207572953209">"Chizmali kalit hududi."</string>
+    <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Grafik kalitni chizish tugallandi"</string>
+    <string name="lockscreen_access_pattern_area" msgid="400813207572953209">"Grafik kalit chiziladigan hudud."</string>
     <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Vidjet %2$d / %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Vidjet qo‘shish."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Bo‘sh"</string>
@@ -747,11 +747,11 @@
     <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> vidjeti o‘chirildi."</string>
     <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Qulfni ochish maydonini kengaytirish."</string>
     <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Qulfni silab ochish"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Chizmali qulfni ochish."</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Grafik kalit bilan ochish."</string>
     <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Qulfni yuzni tanitib ochish"</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin qulfini ochish."</string>
     <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parolli qulfni ochish."</string>
-    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Chizmali qulf maydoni."</string>
+    <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Grafik kalit chiziladigan hudud."</string>
     <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Maydonni silang"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
@@ -1378,8 +1378,8 @@
     <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Tasvir uzatish #<xliff:g id="ID">%1$d</xliff:g>"</string>
     <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
     <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", xavfsiz"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Chizmali parol unutilgan"</string>
-    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Chizmali kalit noto‘g‘ri"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Grafik kalit esimdan chiqdi"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Grafik kalit noto‘g‘ri"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Parol noto‘g‘ri"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN-kod noto‘g‘ri"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
@@ -1396,7 +1396,7 @@
     <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK kod 8 ta raqam bo‘lishi shart."</string>
     <string name="kg_invalid_puk" msgid="3638289409676051243">"To‘g‘ri PUK kodni qayta kiriting. Qayta-qayta urinishlar SIM kartani butunlay o‘chirib qo‘yadi."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-kod mos kelmadi"</string>
-    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Chizmali parolni ochishga juda ko‘p urinildi"</string>
+    <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Grafik kalit juda ko‘p marta chizildi"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"Qulfni ochish uchun Google hisobingiz bilan kiring."</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"Foydalanuvchi nomi (e-pochta)"</string>
     <string name="kg_login_password_hint" msgid="9057289103827298549">"Parol"</string>
@@ -1406,16 +1406,16 @@
     <string name="kg_login_checking_password" msgid="1052685197710252395">"Hisob tekshirilmoqda…"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Siz PIN-kodni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Siz parolni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Siz planshet qulfini ochish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta muvaffaqiyatsiz urindingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishlardan so‘ng planshetning zavod sozlamalari tiklanadi va barcha foydalanuvchi ma’lumotlari o‘chiriladi."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Siz televizorni qulfdan chiqarish parolini <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizda zavod sozlamalari qayta tiklanadi hamda undagi barcha ma’lumotlaringiz o‘chib ketadi."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Siz telefon qulfini ochish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta muvaffaqiyatsiz urindingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishlardan so‘ng telefonning zavod sozlamalari tiklanadi va barcha foydalanuvchi ma’lumotlari o‘chiriladi."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Planshet qulfini ochish uchun <xliff:g id="NUMBER">%d</xliff:g> marta muvaffaqiyatsiz urinib ko‘rdingiz. Planshetning hozir zavod sozlamari tiklanadi."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Siz televizorni qulfdan chiqarish parolini <xliff:g id="NUMBER">%d</xliff:g> marta noto‘g‘ri kiritdingiz. Endi, televizoringizda zavod sozlamalari qayta tiklanadi."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Telefon qulfini ochish uchun <xliff:g id="NUMBER">%d</xliff:g> marta muvaffaqiyatsiz urinib ko‘rdingiz. Telefonning hozir zavod sozlamari tiklanadi."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Siz chizmali kalitni  <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, planshet qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizni qulfdan chiqarish uchun sizda e-pochta hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qaytadan urining."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Siz grafik kalitni  <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, planshet qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizni qulfdan chiqarish uchun sizda e-pochta hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qaytadan urining."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"O‘chirish"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Ovoz balandligi tavsiya etilgan darajadan ham yuqori ko‘tarilsinmi?\n\nUzoq vaqt davomida baland ovozda tinglash eshitish qobiliyatingizga salbiy ta’sir ko‘rsatishi mumkin."</string>
@@ -1550,7 +1550,7 @@
     <string name="lock_to_app_start" msgid="6643342070839862795">"Ekran qadab qo‘yildi"</string>
     <string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran bo‘shatildi"</string>
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Yechishda PIN-kod so‘ralsin"</string>
-    <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bo‘shatishdan oldin chizmali parol so‘ralsin"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Yechishdan oldin grafik kalit so‘ralsin"</string>
     <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bo‘shatishdan oldin parol so‘ralsin"</string>
     <string name="package_installed_device_owner" msgid="8420696545959087545">"Administratoringiz tomonidan o‘rnatilgan"</string>
     <string name="package_updated_device_owner" msgid="8856631322440187071">"Administratoringiz tomonidan yangilandi"</string>
diff --git a/core/res/res/values-vi-watch/styles_material.xml b/core/res/res/values-vi-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-vi-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-watch/config_material.xml b/core/res/res/values-watch/config_material.xml
index 951c088..81b53e7 100644
--- a/core/res/res/values-watch/config_material.xml
+++ b/core/res/res/values-watch/config_material.xml
@@ -27,9 +27,6 @@
     <!-- Use micro alert controller -->
     <integer name="config_alertDialogController">1</integer>
 
-    <!-- Dialog windows in watch should occupy the whole screen and not be floating. -->
-    <bool name="config_dialogWindowIsFloating">false</bool>
-
     <!-- Always overscan by default to ensure onApplyWindowInsets will always be called. -->
     <bool name="config_windowOverscanByDefault">true</bool>
 
diff --git a/core/res/res/values-watch/themes_material.xml b/core/res/res/values-watch/themes_material.xml
index d92a947..4ae4367 100644
--- a/core/res/res/values-watch/themes_material.xml
+++ b/core/res/res/values-watch/themes_material.xml
@@ -38,4 +38,25 @@
         <item name="imeFullscreenBackground">?colorBackground</item>
         <item name="imeExtractEnterAnimation">@anim/input_method_extract_enter</item>
     </style>
+
+    <!-- Override behaviour to set the theme colours for dialogs, keep them the same. -->
+    <style name="ThemeOverlay.Material.Dialog" parent="ThemeOverlay.Material.BaseDialog">
+        <item name="windowIsFloating">false</item>
+    </style>
+
+    <!-- Force the background and floating colours to be the default colours. -->
+    <style name="Theme.Material.Dialog" parent="Theme.Material.BaseDialog">
+        <item name="colorBackground">@color/background_material_dark</item>
+        <item name="colorBackgroundFloating">@color/background_floating_material_dark</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_dark</item>
+        <item name="windowIsFloating">false</item>
+    </style>
+
+    <!-- Force the background and floating colours to be the default colours. -->
+    <style name="Theme.Material.Light.Dialog" parent="Theme.Material.Light.BaseDialog">
+        <item name="colorBackground">@color/background_material_light</item>
+        <item name="colorBackgroundFloating">@color/background_floating_material_light</item>
+        <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_light</item>
+        <item name="windowIsFloating">false</item>
+    </style>
 </resources>
diff --git a/core/res/res/values-zh-rCN-watch/styles_material.xml b/core/res/res/values-zh-rCN-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-zh-rCN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-zh-rHK-watch/styles_material.xml b/core/res/res/values-zh-rHK-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-zh-rHK-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-zh-rTW-watch/styles_material.xml b/core/res/res/values-zh-rTW-watch/styles_material.xml
new file mode 100644
index 0000000..36a459d
--- /dev/null
+++ b/core/res/res/values-zh-rTW-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-zu-watch/styles_material.xml b/core/res/res/values-zu-watch/styles_material.xml
new file mode 100644
index 0000000..8b69fef
--- /dev/null
+++ b/core/res/res/values-zu-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<!-- 
+===============================================================
+                        PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+                        PLEASE READ
+===============================================================
+  -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"amakhandidethi"</font></string>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d0c6a8e..13e1d00 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8251,12 +8251,13 @@
     <declare-styleable name="Shortcut">
         <attr name="shortcutId" format="string" />
         <attr name="enabled" />
-        <attr name="shortcutIcon" format="reference" />
+        <attr name="icon" />
         <attr name="shortcutShortLabel" format="reference" />
         <attr name="shortcutLongLabel" format="reference" />
         <attr name="shortcutDisabledMessage" format="reference" />
-        <attr name="shortcutCategories" format="string" />
-        <attr name="shortcutIntentAction" format="string" />
-        <attr name="shortcutIntentData" format="string" />
+    </declare-styleable>
+
+    <declare-styleable name="ShortcutCategories">
+        <attr name="name" />
     </declare-styleable>
 </resources>
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
new file mode 100644
index 0000000..e830b64
--- /dev/null
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Colors specific to DeviceDefault themes. These are mostly pass-throughs to enable
+     overlaying new theme colors. -->
+<resources>
+    <color name="primary_device_default_dark">@color/primary_material_dark</color>
+    <color name="primary_device_default_light">@color/primary_material_light</color>
+    <color name="primary_device_default_settings">@color/primary_material_settings</color>
+    <color name="primary_dark_device_default_dark">@color/primary_dark_material_dark</color>
+    <color name="primary_dark_device_default_light">@color/primary_dark_material_light</color>
+    <color name="primary_dark_device_default_settings">@color/primary_dark_material_settings</color>
+
+    <color name="secondary_device_default_settings">@color/secondary_material_settings</color>
+
+    <color name="accent_device_default_light">@color/accent_material_light</color>
+    <color name="accent_device_default_dark">@color/accent_material_dark</color>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index c8ca116..a18abdf 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -26,9 +26,13 @@
 
     <color name="primary_material_dark">@color/material_grey_900</color>
     <color name="primary_material_light">@color/material_grey_100</color>
+    <color name="primary_material_settings">@color/material_blue_grey_900</color>
     <color name="primary_dark_material_dark">@color/black</color>
     <color name="primary_dark_material_light">@color/material_grey_600</color>
     <color name="primary_dark_material_light_light_status_bar">@color/material_grey_300</color>
+    <color name="primary_dark_material_settings">@color/material_blue_grey_950</color>
+
+    <color name="secondary_material_settings">@color/material_blue_grey_800</color>
 
     <color name="accent_material_light">@color/material_deep_teal_500</color>
     <color name="accent_material_dark">@color/material_deep_teal_200</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5fd3c36..a8bb0e0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2461,6 +2461,10 @@
     <!-- True if the device supports Sustained Performance Mode-->
     <bool name="config_sustainedPerformanceModeSupported">false</bool>
 
+    <!-- File used to enable the double touch gesture.
+         TODO: move to input HAL once ready. -->
+    <string name="config_doubleTouchGestureEnableFile"></string>
+
     <!-- Controls how we deal with externally connected physical keyboards.
          0 - When using this device, it is not clear for users to recognize when the physical
              keyboard is (should be) connected and when it is (should be) disconnected.  Most of
diff --git a/core/res/res/values/config_material.xml b/core/res/res/values/config_material.xml
index f62678a..a37be83 100644
--- a/core/res/res/values/config_material.xml
+++ b/core/res/res/values/config_material.xml
@@ -29,9 +29,6 @@
     <!-- The alert controller to use for alert dialogs. -->
     <integer name="config_alertDialogController">0</integer>
 
-    <!-- True if dialog windows are floating. -->
-    <bool name="config_dialogWindowIsFloating">true</bool>
-
     <!-- True if windowOverscan should be on by default. -->
     <bool name="config_windowOverscanByDefault">false</bool>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index da31767..c187d2c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2733,13 +2733,9 @@
        =============================================================== -->
     <eat-comment />
     <public type="attr" name="shortcutId" />
-    <public type="attr" name="shortcutIcon" />
     <public type="attr" name="shortcutShortLabel" />
     <public type="attr" name="shortcutLongLabel" />
     <public type="attr" name="shortcutDisabledMessage" />
-    <public type="attr" name="shortcutCategories" />
-    <public type="attr" name="shortcutIntentAction" />
-    <public type="attr" name="shortcutIntentData" />
     <public type="attr" name="roundIcon" />
 
     <public type="attr" name="contextUri" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6e937ff..706d2e6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2614,6 +2614,8 @@
   <!-- Pinner Service -->
   <java-symbol type="array" name="config_defaultPinnerServiceFiles" />
 
+  <java-symbol type="string" name="config_doubleTouchGestureEnableFile" />
+
   <java-symbol type="string" name="suspended_widget_accessibility" />
 
   <!-- Used internally for assistant to launch activity transitions -->
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index ea1b626..273d93f 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -199,25 +199,50 @@
 
         <item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.MediaRouteButton</item>
 
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar -->
-    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Material.NoActionBar"  />
+    <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Material.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar.  This theme
          sets {@link android.R.attr#windowFullscreen} to true.  -->
-    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen"  />
+    <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Material.NoActionBar.Fullscreen">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar and
     extending in to overscan region.  This theme
     sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
     to true. -->
-    <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan"  />
+    <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Material.NoActionBar.Overscan">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
          {@link android.R.attr#windowTranslucentNavigation} to true. -->
-    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor"  />
+    <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Material.NoActionBar.TranslucentDecor">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for dialog windows and activities. This changes the window to be
     floating (not fill the entire screen), and puts a frame around its contents. You can set this
@@ -231,18 +256,38 @@
 
         <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
         <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
     regular dialog. -->
-    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth" />
+    <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar" />
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
     for a regular dialog. -->
-    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth" />
+    <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
     <style name="Theme.DeviceDefault.Dialog.FixedSize">
@@ -262,44 +307,99 @@
 
     <!-- DeviceDefault theme for a window that will be displayed either full-screen on smaller
     screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
-    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge"  />
+    <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Material.DialogWhenLarge">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for a window without an action bar that will be displayed either
     full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
     xlarge). -->
-    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar"  />
+    <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Material.DialogWhenLarge.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for a presentation window on a secondary display. -->
-    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation" />
+    <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Material.Dialog.Presentation">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for panel windows. This removes all extraneous window
     decorations, so you basically have an empty rectangle in which to place your content. It makes
     the window floating, with a transparent background, and turns off dimming behind the window. -->
-    <style name="Theme.DeviceDefault.Panel" parent="Theme.Material.Panel"  />
+    <style name="Theme.DeviceDefault.Panel" parent="Theme.Material.Panel">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
     behind them. -->
-    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Material.Wallpaper"  />
+    <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Material.Wallpaper">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
     behind them and without an action bar. -->
-    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Material.Wallpaper.NoTitleBar"  />
+    <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Material.Wallpaper.NoTitleBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- DeviceDefault style for input methods, which is used by the
          {@link android.inputmethodservice.InputMethodService} class.-->
-    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Material.InputMethod"  />
+    <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Material.InputMethod">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- DeviceDefault style for input methods, which is used by the
          {@link android.service.voice.VoiceInteractionSession} class.-->
-    <style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Material.VoiceInteractionSession" >
-
+    <style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Material.VoiceInteractionSession">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
+
     <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Material.Dialog.Alert">
         <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
 
-    <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar" />
-    <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame" />
+    <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
+
+    <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault} with a light-colored style -->
     <style name="Theme.DeviceDefault.Light" parent="Theme.Material.Light" >
@@ -447,34 +547,63 @@
 
         <item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.Light.MediaRouteButton</item>
 
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
     inverse color profile. -->
-    <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Material.Light.DarkActionBar" />
+    <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Material.Light.DarkActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_dark</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Material.Light.NoActionBar"  />
+    <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Material.Light.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar.
          This theme sets {@link android.R.attr#windowFullscreen} to true.  -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen"  />
+    <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Material.Light.NoActionBar.Fullscreen">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar
     and extending in to overscan region.  This theme
     sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
     to true. -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan" />
+    <style name="Theme.DeviceDefault.Light.NoActionBar.Overscan" parent="Theme.Material.Light.NoActionBar.Overscan">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light} that has no title bar and translucent
          system decor.  This theme sets {@link android.R.attr#windowTranslucentStatus} and
          {@link android.R.attr#windowTranslucentNavigation} to true. -->
-    <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor" />
+    <style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor" parent="Theme.Material.Light.NoActionBar.TranslucentDecor">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- DeviceDefault light theme for dialog windows and activities. This changes the window to be
     floating (not fill the entire screen), and puts a frame around its contents. You can set this
     theme on an activity if you would like to make an activity that looks like a Dialog.-->
-    <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Material.Light.Dialog" >
+    <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Material.Light.Dialog">
         <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
         <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
 
@@ -483,18 +612,38 @@
 
         <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>
         <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} that has a nice minimum width for a
     regular dialog. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Material.Light.Dialog.MinWidth" />
+    <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Material.Light.Dialog.MinWidth">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
      <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} without an action bar -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Material.Light.Dialog.NoActionBar" />
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Material.Light.Dialog.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog_NoActionBar} that has a nice minimum
     width for a regular dialog. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Light.Dialog.NoActionBar.MinWidth" />
+    <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Light.Dialog.NoActionBar.MinWidth">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
     <style name="Theme.DeviceDefault.Light.Dialog.FixedSize">
@@ -502,6 +651,11 @@
         <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
         <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
         <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- Variant of Theme.DeviceDefault.Dialog.NoActionBar that has a fixed size. -->
@@ -510,33 +664,74 @@
         <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
         <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
         <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- DeviceDefault light theme for a window that will be displayed either full-screen on smaller
     screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
-    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge"  />
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- DeviceDefault light theme for a window without an action bar that will be displayed either
     full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
     xlarge). -->
-    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar"  />
+    <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- DeviceDefault light theme for a presentation window on a secondary display. -->
-    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation" />
+    <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- DeviceDefault light theme for panel windows. This removes all extraneous window
     decorations, so you basically have an empty rectangle in which to place your content. It makes
     the window floating, with a transparent background, and turns off dimming behind the window. -->
-    <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Material.Light.Panel"  />
+    <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Material.Light.Panel">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.Alert">
         <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault.Light</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
-    <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Material.Light.SearchBar" />
+    <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Material.Light.SearchBar">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
+
 
     <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
-    <style name="Theme.DeviceDefault.Settings" parent="Theme.Material.Settings" />
+    <style name="Theme.DeviceDefault.Settings" parent="Theme.Material.Settings">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
 
     <!-- Theme used for the intent picker activity. -->
     <style name="Theme.DeviceDefault.Resolver" parent="Theme.Material.Light">
@@ -549,8 +744,24 @@
         <item name="colorControlActivated">?attr/colorControlHighlight</item>
         <item name="listPreferredItemPaddingStart">?attr/dialogPreferredPadding</item>
         <item name="listPreferredItemPaddingEnd">?attr/dialogPreferredPadding</item>
+
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
     <!-- DeviceDefault theme for the default system theme.  -->
-    <style name="Theme.DeviceDefault.System" parent="Theme.Material.Light.DarkActionBar" />
+    <style name="Theme.DeviceDefault.System" parent="Theme.DeviceDefault.Light.DarkActionBar" />
+
+    <style name="ThemeOverlay.DeviceDefault" />
+
+    <style name="ThemeOverlay.DeviceDefault.Accent">
+        <item name="colorAccent">@color/accent_device_default_dark</item>
+    </style>
+
+    <style name="ThemeOverlay.DeviceDefault.Accent.Light">
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
+
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 0e4e060..d437032 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -864,17 +864,14 @@
         <item name="searchViewStyle">@style/Widget.Material.SearchView.ActionBar</item>
     </style>
 
-    <!-- Theme overlay that overrides window properties to display as a dialog. -->
-    <style name="ThemeOverlay.Material.Dialog">
-        <item name="colorBackgroundCacheHint">@null</item>
-        <item name="colorBackground">?attr/colorBackgroundFloating</item>
-
+    <!-- Base theme for overlay dialogs, customize the colours in the actual dialog theme. -->
+    <style name="ThemeOverlay.Material.BaseDialog">
         <item name="windowFrame">@null</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Material</item>
         <item name="windowTitleBackgroundStyle">@style/DialogWindowTitleBackground.Material</item>
         <item name="windowBackground">@drawable/dialog_background_material</item>
         <item name="windowElevation">@dimen/floating_window_z</item>
-        <item name="windowIsFloating">@bool/config_dialogWindowIsFloating</item>
+        <item name="windowIsFloating">true</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowAnimationStyle">@style/Animation.Material.Dialog</item>
         <item name="windowSoftInputMode">stateUnspecified|adjustPan</item>
@@ -897,6 +894,12 @@
         <item name="windowFixedHeightMinor">@null</item>
     </style>
 
+    <!-- Theme overlay that overrides window properties to display as a dialog. -->
+    <style name="ThemeOverlay.Material.Dialog" parent="ThemeOverlay.Material.BaseDialog">
+        <item name="colorBackgroundCacheHint">@null</item>
+        <item name="colorBackground">?attr/colorBackgroundFloating</item>
+    </style>
+
     <!-- Theme overlay that overrides window properties to display as a date picker dialog. -->
     <style name="ThemeOverlay.Material.Dialog.DatePicker">
         <item name="alertDialogStyle">@style/DatePickerDialog.Material</item>
@@ -1080,7 +1083,7 @@
         <item name="windowTitleBackgroundStyle">@style/DialogWindowTitleBackground.Material</item>
         <item name="windowBackground">@drawable/dialog_background_material</item>
         <item name="windowElevation">@dimen/floating_window_z</item>
-        <item name="windowIsFloating">@bool/config_dialogWindowIsFloating</item>
+        <item name="windowIsFloating">true</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowAnimationStyle">@style/Animation.Material.Dialog</item>
         <item name="windowSoftInputMode">stateUnspecified|adjustPan</item>
@@ -1300,8 +1303,8 @@
 
     <!-- Default theme for Settings and activities launched from Settings. -->
     <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
 
         <item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
         <item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
@@ -1310,8 +1313,8 @@
 
     <!-- Default theme for Settings and activities launched from Settings. -->
     <style name="Theme.Material.Settings.NoActionBar" parent="Theme.Material.Light.NoActionBar">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
 
         <item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
         <item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
@@ -1319,41 +1322,41 @@
     </style>
 
     <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
     </style>
 
     <style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
 
     <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
     </style>
 
     <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
 
     <style name="Theme.Material.Settings.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge.DarkActionBar">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
     </style>
 
     <style name="Theme.Material.Settings.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
     </style>
 
     <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
     </style>
 
     <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
     </style>
 
     <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
-        <item name="colorPrimary">@color/material_blue_grey_900</item>
-        <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
+        <item name="colorPrimary">@color/primary_material_settings</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
     </style>
 </resources>
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index ae858fe..0d65602 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -797,54 +797,6 @@
   to: https://code.google.com/p/android/issues/list?can=2&q=label%3ADevPreview-N
 - from: /2016/03/first-preview-of-android-n-developer.html
   to: http://android-developers.blogspot.com/2016/03/first-preview-of-android-n-developer.html
-- from: /r/studio-ui/vector-asset-studio.html
-  to: /studio/write/vector-asset-studio.html
-- from: /r/studio-ui/image-asset-studio.html
-  to: /studio/write/image-asset-studio.html
-- from: /r/studio-ui/project-structure.html
-  to: /studio/projects/index.html
-- from: /r/studio-ui/android-monitor.html
-  to: /studio/profile/android-monitor.html
-- from: /r/studio-ui/am-logcat.html
-  to: /studio/debug/am-logcat.html
-- from: /r/studio-ui/am-memory.html
-  to: /studio/profile/am-memory.html
-- from: /r/studio-ui/am-cpu.html
-  to: /studio/profile/am-cpu.html
-- from: /r/studio-ui/am-gpu.html
-  to: /studio/profile/am-gpu.html
-- from: /r/studio-ui/am-network.html
-  to: /studio/profile/am-network.html
-- from: /r/studio-ui/am-hprof.html
-  to: /studio/profile/am-hprof.html
-- from: /r/studio-ui/am-allocation.html
-  to: /studio/profile/am-allocation.html
-- from: /r/studio-ui/am-methodtrace.html
-  to: /studio/profile/am-methodtrace.html
-- from: /r/studio-ui/am-sysinfo.html
-  to: /studio/profile/am-sysinfo.html
-- from: /r/studio-ui/am-screenshot.html
-  to: /studio/debug/am-screenshot.html
-- from: /r/studio-ui/am-video.html
-  to: /studio/debug/am-video.html
-- from: /r/studio-ui/avd-manager.html
-  to: /studio/run/managing-avds.html
-- from: /r/studio-ui/rundebugconfig.html
-  to: /studio/run/index.html
-- from: /r/studio-ui/devicechooser.html
-  to: /studio/run/emulator.html
-- from: /r/studio-ui/virtualdeviceconfig.html
-  to: /studio/run/managing-avds.html
-- from: /r/studio-ui/emulator.html
-  to: /studio/run/emulator.html
-- from: /r/studio-ui/instant-run.html
-  to: /studio/run/index.html#instant-run
-- from: /r/studio-ui/test-recorder.html
-  to: http://tools.android.com/tech-docs/test-recorder
-- from: /r/studio-ui/export-licenses.html
-  to: http://tools.android.com/tech-docs/new-build-system/license
-- from: /r/studio-ui/experimental-to-stable-gradle.html
-  to: http://tools.android.com/tech-docs/new-build-system/gradle-experimental/experimental-to-stable-gradle
 - from: /reference/org/apache/http/...
   to: /about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
 - from: /shareables/...
@@ -1169,3 +1121,55 @@
   to: /preview/features/background-optimization.html
 - from: /bgopt/
   to: /preview/features/background-optimization.html
+
+
+
+# Android Studio help button redirects
+- from: /r/studio-ui/vector-asset-studio.html
+  to: /studio/write/vector-asset-studio.html
+- from: /r/studio-ui/image-asset-studio.html
+  to: /studio/write/image-asset-studio.html
+- from: /r/studio-ui/project-structure.html
+  to: /studio/projects/index.html
+- from: /r/studio-ui/android-monitor.html
+  to: /studio/profile/android-monitor.html
+- from: /r/studio-ui/am-logcat.html
+  to: /studio/debug/am-logcat.html
+- from: /r/studio-ui/am-memory.html
+  to: /studio/profile/am-memory.html
+- from: /r/studio-ui/am-cpu.html
+  to: /studio/profile/am-cpu.html
+- from: /r/studio-ui/am-gpu.html
+  to: /studio/profile/am-gpu.html
+- from: /r/studio-ui/am-network.html
+  to: /studio/profile/am-network.html
+- from: /r/studio-ui/am-hprof.html
+  to: /studio/profile/am-hprof.html
+- from: /r/studio-ui/am-allocation.html
+  to: /studio/profile/am-allocation.html
+- from: /r/studio-ui/am-methodtrace.html
+  to: /studio/profile/am-methodtrace.html
+- from: /r/studio-ui/am-sysinfo.html
+  to: /studio/profile/am-sysinfo.html
+- from: /r/studio-ui/am-screenshot.html
+  to: /studio/debug/am-screenshot.html
+- from: /r/studio-ui/am-video.html
+  to: /studio/debug/am-video.html
+- from: /r/studio-ui/avd-manager.html
+  to: /studio/run/managing-avds.html
+- from: /r/studio-ui/rundebugconfig.html
+  to: /studio/run/index.html
+- from: /r/studio-ui/devicechooser.html
+  to: /studio/run/emulator.html
+- from: /r/studio-ui/virtualdeviceconfig.html
+  to: /studio/run/managing-avds.html
+- from: /r/studio-ui/emulator.html
+  to: /studio/run/emulator.html
+- from: /r/studio-ui/instant-run.html
+  to: /studio/run/index.html#instant-run
+- from: /r/studio-ui/test-recorder.html
+  to: http://tools.android.com/tech-docs/test-recorder
+- from: /r/studio-ui/export-licenses.html
+  to: http://tools.android.com/tech-docs/new-build-system/license
+- from: /r/studio-ui/experimental-to-stable-gradle.html
+  to: http://tools.android.com/tech-docs/new-build-system/gradle-experimental/experimental-to-stable-gradle
\ No newline at end of file
diff --git a/docs/html/distribute/essentials/quality/core.jd b/docs/html/distribute/essentials/quality/core.jd
index 4b0b546..0ff44eb 100644
--- a/docs/html/distribute/essentials/quality/core.jd
+++ b/docs/html/distribute/essentials/quality/core.jd
@@ -1041,7 +1041,7 @@
     CR-11
   </td>
   <td>
-    Trigger and observe in the notications drawer all types of notifications
+    Trigger and observe in the notifications drawer all types of notifications
     that the app can display. Expand notifications where applicable (Android
     4.1 and higher), and tap all actions offered.
   </td>
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index 564215e..fc795ff 100755
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -21,7 +21,7 @@
     <h2>Related Samples</h2>
 
     <ol>
-      <li><a href="{@docRoot}resources/samples/RenderScript/HelloCompute/index.html">Hello
+      <li><a class="external-link"href="https://github.com/android/platform_development/tree/master/samples/RenderScript/HelloCompute">Hello
       Compute</a></li>
     </ol>
   </div>
diff --git a/docs/html/ndk/downloads/index.jd b/docs/html/ndk/downloads/index.jd
index 47d3113..954b049 100644
--- a/docs/html/ndk/downloads/index.jd
+++ b/docs/html/ndk/downloads/index.jd
@@ -332,35 +332,199 @@
 <h2 id="rel">Release Notes</h2>
 
 <p>
-  Android NDK, Revision 11c <em>(March 2016)</em>
+  Android NDK, Revision 12 <em>(June 2016)</em>
 </p>
 
 <dl>
-  <dt>
-    NDK
-  </dt>
+<dt>
+  Announcements
+</dt>
 
-  <dd>
-    <ul>
-      <li>Changes
-        <ul>
-          <li>Applied additional fixes to the {@code ndk-gdb.py} script.
-          </li>
-          <li>Added an optional package name argument to the {@code ndk-gdb}
-            command {@code --attach} option.
-            (<a href="https://github.com/android-ndk/ndk/issues/13">Issue 13</a>)
-          </li>
-          <li>Fixed invalid toolchain paths for 32-bit Windows platform.
-            (<a href="https://github.com/android-ndk/ndk/issues/45">Issue 45</a>)
-          </li>
-          <li>Fixed the relative path for the {@code ndk-which} command.
-            (<a href="https://github.com/android-ndk/ndk/issues/29">Issue 29</a>)
-          </li>
-          <li>Fixed use of cygpath for the libgcc compiler.
-            (Android <a href="http://b.android.com/195486">Issue 195486</a>)
-          </li>
-        </ul>
-      </li>
-    </ul>
-  </dd>
-</dl>
\ No newline at end of file
+<ul>
+  <li>The <code>ndk-build</code> command will default to using
+  Clang in an upcoming release. GCC will be removed in a later release.
+  </li>
+  <li>The <code>make-standalone-toolchain.sh</code> script will be removed
+  in an upcoming release. If you use this script, please plan to migrate to the
+  <code>make_standalone_toolchain.py</code> as soon as possible.
+  </li>
+</ul>
+
+<dt>
+  NDK
+</dt>
+
+<ul>
+  <li>Removed support for the armeabi-v7a-hard ABI. See the explanation in the
+  <a href=
+  "https://android.googlesource.com/platform/ndk/+/ndk-r12-release/docs/HardFloatAbi.md">
+    documentation</a>.
+  </li>
+
+  <li>Removed all sysroots for platform levels prior to Android 2.3 (API level 10).
+    We dropped support for them in NDK r11, but neglected to actually remove them.
+  </li>
+
+  <li>Updated exception handling when using c++_shared on ARM32 so that it
+    mostly works (see <a href="#known-issues">Known Issues</a>). The unwinder
+    is now linked into each linked object rather than into libc++ itself.
+  </li>
+
+  <li>Pruned the default compiler flags (<a href=
+  "https://github.com/android-ndk/ndk/issues/27">NDK Issue 27</a>). You can see
+  details of this update in <a href=
+  "https://android-review.googlesource.com/#/c/207721/5">Change 207721</a>.
+  </li>
+
+  <li>Added a Python implementation of standalone toolchains in <code>
+  build/tools/make_standalone_toolchain.py</code>. On Windows, you no longer
+  need Cygwin to use this feature. Note that the bash flavor will be removed
+  in an upcoming release, so please test the new one now.
+  </li>
+
+  <li>Configured Clang debug builds to have the <code>-fno-limit-debug-info</code>
+  option is enabled by default. This change enables better debugging with LLDB.
+  </li>
+
+  <li>Enabled the <code>--build-id</code> as a default option. This option
+  causes an identifier to be shown in native crash reports so you can easily
+  identify which version of your code was running.
+  </li>
+
+  <li>Fixed issue with <code>NDK_USE_CYGPATH</code> so that it no longer causes
+  problems with libgcc
+  (<a href="http://b.android.com/195486">Issue 195486</a>).
+  </li>
+
+  <li>Enabled the following options as default:
+  <code>-Wl,--warn-shared-textrel</code> and <code>-Wl,--fatal-warnings</code>.
+  If you have shared text relocations, your app does not load on Android 6.0
+  (API level 23) and higher. Note that this configuration has never been
+  allowed for 64-bit apps.
+  </li>
+
+  <li>Fixed a few issues so that precompiled headers work better
+    (<a href="https://github.com/android-ndk/ndk/issues/14">NDK Issue 14</a>,
+     <a href="https://github.com/android-ndk/ndk/issues/16">NDK Issue 16</a>).
+  </li>
+
+  <li>Removed unreachable ARM (non-thumb) STL libraries.
+  </li>
+
+  <li>Added Vulkan support to android-24.
+  </li>
+
+  <li>Added Choreographer API to android-24.
+  </li>
+
+  <li>Added libcamera2 APIs for devices that support the
+  <code>INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED</code> feature level or higher.
+  For more information, see the
+  <a href="{@docRoot}reference/android/hardware/camera2/CameraCharacteristics.html#INFO_SUPPORTED_HARDWARE_LEVEL">
+    <code>CameraCharacteristics</code></a> reference.
+  </li>
+
+</ul>
+
+<dt>
+  Clang
+</dt>
+
+<ul>
+  <li>Clang has been updated to 3.8svn (r256229, build 2812033). Note that
+    Clang packaged in the Windows 64-bit NDK is actually 32-bit.
+  </li>
+
+  <li>Fixed <code>__thread</code> so that it works for real this time.
+  </li>
+</ul>
+
+<dt>
+  GCC
+</dt>
+
+<ul>
+  <li>Synchronized the compiler with the ChromeOS GCC @ google/gcc-4_9 r227810.
+  </li>
+
+  <li>Backported coverage sanitizer patch from ToT (r231296).
+  </li>
+
+  <li>Fixed <code>libatomic</code> to not use ifuncs (<a href=
+  "https://github.com/android-ndk/ndk/issues/31">NDK Issue 31</a>).
+  </li>
+</ul>
+
+<dt>
+  Binutils
+</dt>
+
+<ul>
+  <li>Silenced the "Erratum 843419 found and fixed" info messages.
+  </li>
+
+  <li>Introduced option <code>--long-plt</code> to fix an internal linker error
+  when linking huge arm32 binaries.
+  </li>
+
+  <li>Fixed wrong run time stubs for <code>AArch64</code>. This problem was
+  causing jump addresses to be calculated incorrectly for very large
+  dynamic shared objects (DSOs).
+  </li>
+
+  <li>Introduced default option <code>--no-apply-dynamic</code> to work around
+  a dynamic linker bug for earlier Android releases.
+  </li>
+
+  <li>Fixed a known issue with NDK r11 where <code>dynamic_cast</code> was not
+  working with Clang, x86, stlport_static and optimization.
+  </li>
+</ul>
+
+<dt>
+  GDB
+</dt>
+
+<ul>
+  <li>Updated to GDB version 7.11. For more information about this release, see
+  <a href="https://www.gnu.org/software/gdb/news/">GDB News</a>.
+  </li>
+
+  <li>Fixed a number of bugs in the <code>ndk-gdb.py</code> script.
+  </li>
+</ul>
+
+<dt id="known-issues">
+  Known Issues
+</dt>
+
+<ul>
+  <li>The x86 <a href="http://source.android.com/devices/tech/debug/asan.html">Address
+  Sanitizer</a> (ASAN) currently does not work. For more information, see
+  <a href="https://android-review.googlesource.com/#/c/186276/">Issue 186276</a>.
+  </li>
+
+  <li>Exception unwinding with <code>c++_shared</code> does not work for ARM on
+  Android 2.3 (API level 9) or Android 4.0 (API level 14).
+  </li>
+
+  <li>Bionic headers and libraries for Android 6.0 (API level 23) and higher
+  are not yet exposed despite the presence of android-24. Those platforms still
+  have the Android 5.0 (API level 21) headers and libraries, which is consistent
+  with NDK r11.
+  </li>
+
+  <li>The RenderScript tools are not present, which is consistent with
+  NDK r11.
+  (<a href="https://github.com/android-ndk/ndk/issues/7">NDK Issue 7</a>)
+  </li>
+
+  <li>In <code>NdkCameraMetadataTags.h</code> header file, the camera metadata
+  tag enum value <code>ACAMERA_STATISTICS_LENS_SHADING_CORRECTION_MAP</code>
+  was listed by accident and will be removed in next release. Use
+  the <code>ACAMERA_STATISTICS_LENS_SHADING_MAP</code> value instead.
+  </li>
+
+</ul>
+
+</dl>
diff --git a/docs/html/ndk/downloads/revision_history.jd b/docs/html/ndk/downloads/revision_history.jd
index c5a0d48..211b64e 100644
--- a/docs/html/ndk/downloads/revision_history.jd
+++ b/docs/html/ndk/downloads/revision_history.jd
@@ -10,6 +10,44 @@
  <p>
    <a href="#" onclick="return toggleContent(this)"> <img
      src="/assets/images/styles/disclosure_down.png" class="toggle-content-img" alt=""
+   >Android NDK, Revision 11c</a> <em>(March 2016)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+
+<dl>
+  <dd>
+    <ul>
+      <li>Changes
+        <ul>
+          <li>Applied additional fixes to the {@code ndk-gdb.py} script.
+          </li>
+          <li>Added an optional package name argument to the {@code ndk-gdb}
+            command {@code --attach} option.
+            (<a href="https://github.com/android-ndk/ndk/issues/13">Issue 13</a>)
+          </li>
+          <li>Fixed invalid toolchain paths for 32-bit Windows platform.
+            (<a href="https://github.com/android-ndk/ndk/issues/45">Issue 45</a>)
+          </li>
+          <li>Fixed the relative path for the {@code ndk-which} command.
+            (<a href="https://github.com/android-ndk/ndk/issues/29">Issue 29</a>)
+          </li>
+          <li>Fixed use of cygpath for the libgcc compiler.
+            (Android <a href="http://b.android.com/195486">Issue 195486</a>)
+          </li>
+        </ul>
+      </li>
+    </ul>
+  </dd>
+</dl>
+
+ </div>
+</div>
+
+<div class="toggle-content closed">
+<a name="11b"></a>
+ <p>
+   <a href="#" onclick="return toggleContent(this)"> <img
+     src="/assets/images/styles/disclosure_down.png" class="toggle-content-img" alt=""
    >Android NDK, Revision 11b</a> <em>(March 2016)</em>
  </p>
  <div class="toggle-content-toggleme">
diff --git a/docs/html/preview/behavior-changes.jd b/docs/html/preview/behavior-changes.jd
index b38f1b8..3a37295 100644
--- a/docs/html/preview/behavior-changes.jd
+++ b/docs/html/preview/behavior-changes.jd
@@ -737,7 +737,17 @@
 
   <li>The Work Mode setting controls access to work apps. When work mode is off the
   system launcher indicates work apps are unavailable by greying them out. Enabling
-  work mode again restores normal behavior.
+  work mode again restores normal behavior.</li>
+
+  <li>When installing a PKCS #12 file containing a client certificate chain and
+  the corresponding private key from Settings UI, the CA certificate in the
+  chain is no longer installed to the trusted credentials storage. This does
+  not affect the result of {@link android.security.KeyChain#getCertificateChain
+  KeyChain.getCertificateChain()} when apps attempt to retrieve the client
+  certificate chain later. If required, the CA certificate should be installed
+  to the trusted credentials storage via Settings UI separately, with a
+  DER-encoded format under a .crt or .cer file extension.
+  </li>
 </ul>
 
 <p>
diff --git a/docs/html/preview/support.jd b/docs/html/preview/support.jd
index 5328fd8..ef8a652 100644
--- a/docs/html/preview/support.jd
+++ b/docs/html/preview/support.jd
@@ -17,6 +17,7 @@
       <li><a href="#general">General advisories</a></li>
       <li><a href="#new">New in DP4</a></li>
       <li><a href="#ki">Known issues</a></li>
+      <li><a href="#upgrade-notes">Notes on publishing apps that target API 24</a></li>
     </ul>
   </li>
   <li><a href="#dp3">Developer Preview 3</a></li>
@@ -279,6 +280,15 @@
   </li>
 </ul>
 
+<h4 id="">Android Auto</h4>
+
+<p>
+  The version of Google Maps included in Developer Preview 4 (9.30) crashes
+  when used with Android Auto. This issue will be fixed in the next update to
+  Google Maps (9.31), expected in the coming weeks.
+</p>
+
+
 <!-- TBA, if any
 <h4>Device-specific issues</h4>
 
@@ -328,13 +338,34 @@
 
   <li>Additional bluetooth connectivity fixes
   </li>
+
 </ul>
 
 <p>For the full list of fixed issues, see <a href="https://goo.gl/6uCKtf">the
 issue tracker</a>.</p>
 
+<h3 id="upgrade-notes">Notes on publishing apps that target API 24</h3>
 
+<p>
+  Before publishing apps that target API 24 in Google Play, keep these points
+  in mind:
+</p>
 
+<ul>
+  <li>If your app’s current <code>targetSdkVersion</code> is 22 or lower and
+  you want to target API 24, you’ll need to support <a href=
+  "{@docRoot}about/versions/marshmallow/android-6.0-changes.html">behaviors
+  introduced with Android 6.0 (Marshmallow)</a>, such as <a href=
+  "{@docRoot}training/permissions/requesting.html">runtime permissions</a>, in
+  addition to Android N behaviors.
+  </li>
+
+  <li>Once you publish an app with <code>targetSdkVersion</code> set to 23 or
+  higher, you can't later publish a version of the app with a higher
+  <code>versionCode</code> that targets 22 or lower. This restriction applies
+  in alpha and beta channels as well as production channel.
+  </li>
+</ul>
 
 <!-- DP3 Release Notes Archive -->
 
diff --git a/docs/html/sdk/sdk_vars.cs b/docs/html/sdk/sdk_vars.cs
index 32fdb0a..80da297 100644
--- a/docs/html/sdk/sdk_vars.cs
+++ b/docs/html/sdk/sdk_vars.cs
@@ -1,18 +1,19 @@
 <?cs
-set:ndk.mac64_download='android-ndk-r11c-darwin-x86_64.zip' ?><?cs
-set:ndk.mac64_bytes='772428792' ?><?cs
-set:ndk.mac64_checksum='4ce8e7ed8dfe08c5fe58aedf7f46be2a97564696' ?><?cs
+set:ndk.mac64_download='android-ndk-r12-darwin-x86_64.zip' ?><?cs
+set:ndk.mac64_bytes='734014148' ?><?cs
+set:ndk.mac64_checksum='708d4025142924f7097a9f44edf0a35965706737' ?><?cs
 
-set:ndk.linux64_download='android-ndk-r11c-linux-x86_64.zip' ?><?cs
-set:ndk.linux64_bytes='794135138' ?><?cs
-set:ndk.linux64_checksum='de5ce9bddeee16fb6af2b9117e9566352aa7e279' ?><?cs
+set:ndk.linux64_download='android-ndk-r12-linux-x86_64.zip' ?><?cs
+set:ndk.linux64_bytes='755431993' ?><?cs
+set:ndk.linux64_checksum='b7e02dc733692447366a2002ad17e87714528b39' ?><?cs
 
-set:ndk.win64_download='android-ndk-r11c-windows-x86_64.zip' ?><?cs
-set:ndk.win64_bytes='771407642' ?><?cs
-set:ndk.win64_checksum='3d89deb97b3191c7e5555f1313ad35059479f071' ?><?cs
-set:ndk.win32_download='android-ndk-r11c-windows-x86.zip' ?><?cs
-set:ndk.win32_bytes='728899082' ?><?cs
-set:ndk.win32_checksum='ff939bde6cd374eecbd2c3b2ad218697f9a5038c'
+set:ndk.win64_download='android-ndk-r12-windows-x86.zip' ?><?cs
+set:ndk.win64_bytes='706332762' ?><?cs
+set:ndk.win64_checksum='37fcd7acf6012d0068a57c1524edf24b0fef69c9' ?><?cs
+
+set:ndk.win32_download='android-ndk-r12-windows-x86_64.zip' ?><?cs
+set:ndk.win32_bytes='749444245' ?><?cs
+set:ndk.win32_checksum='80d64a77aab52df867ac55cec1e976663dd3326f'
 ?>
 <?cs
 def:size_in_mb(bytes)
diff --git a/docs/html/topic/libraries/data-binding/index.jd b/docs/html/topic/libraries/data-binding/index.jd
index ca8784e..293de51 100644
--- a/docs/html/topic/libraries/data-binding/index.jd
+++ b/docs/html/topic/libraries/data-binding/index.jd
@@ -18,7 +18,7 @@
         <a href="#data_binding_layout_files">Data Binding Layout Files</a>
         <ol>
           <li>
-            <a href="#writing_expressions">Writing your first data binding
+            <a href="#writing_expressions">Writing your first set of data binding
             expressions</a>
           </li>
 
@@ -29,9 +29,16 @@
           <li>
             <a href="#binding_data">Binding Data</a>
           </li>
-
           <li>
-            <a href="#binding_events">Binding Events</a>
+            <a href="#event_handling">Event Handling</a>
+            <ol>
+              <li>
+                <a href="#method_references">Method References</a>
+              </li>
+              <li>
+                <a href="#listener_bindings">Listener Bindings</a>
+              </li>
+            </ol>
           </li>
         </ol>
       </li>
@@ -147,27 +154,34 @@
   application logic and layouts.
 </p>
 
-<p>The Data Binding Library offers both flexibility and broad compatibility
-&mdash; it's a support library, so you can use it with all Android platform
-versions back to <strong>Android 2.1</strong> (API level 7+).</p>
+<p>
+  The Data Binding Library offers both flexibility and broad compatibility —
+  it's a support library, so you can use it with all Android platform versions
+  back to <strong>Android 2.1</strong> (API level 7+).
+</p>
 
-<p>To use data binding, Android Plugin for Gradle <strong>1.5.0-alpha1</strong>
-or higher is required.</p>
+<p>
+  To use data binding, Android Plugin for Gradle <strong>1.5.0-alpha1</strong>
+  or higher is required.
+</p>
 
 <h2 id="build_environment">
   Build Environment
 </h2>
 
-<p>To get started with Data Binding, download the library from the Support
-repository in the Android SDK manager. </p>
-
 <p>
-To configure your app to use data binding, add the <code>dataBinding</code> element to your
-<code>build.gradle</code> file in the app module.
+  To get started with Data Binding, download the library from the Support
+  repository in the Android SDK manager.
 </p>
 
- <p>Use the following code snippet to configure data binding: </p>
+<p>
+  To configure your app to use data binding, add the <code>dataBinding</code>
+  element to your <code>build.gradle</code> file in the app module.
+</p>
 
+<p>
+  Use the following code snippet to configure data binding:
+</p>
 <pre>
 android {
     ....
@@ -176,13 +190,17 @@
     }
 }
 </pre>
+<p>
+  If you have an app module that depends on a library which uses data binding,
+  your app module must configure data binding in its <code>build.gradle</code>
+  file as well.
+</p>
 
-<p>If you have an app module that depends on a library which uses data binding, your app module
- must configure data binding in its <code>build.gradle</code> file as well.</p>
-
-<p>Also, make sure you are using a compatible version of Android Studio.
-<strong>Android Studio 1.3</strong> and later provides support for data binding as described in
-<a href="#studio_support">Android Studio Support for Data Binding</a>.
+<p>
+  Also, make sure you are using a compatible version of Android Studio.
+  <strong>Android Studio 1.3</strong> and later provides support for data
+  binding as described in <a href="#studio_support">Android Studio Support for
+  Data Binding</a>.
 </p>
 
 <h2 id="data_binding_layout_files">
@@ -190,7 +208,7 @@
 </h2>
 
 <h3 id="writing_expressions">
-  Writing your first data binding expressions
+  Writing your first set of data binding expressions
 </h3>
 
 <p>
@@ -223,20 +241,19 @@
   The user <strong>variable</strong> within <strong>data</strong> describes a
   property that may be used within this layout.
 </p>
-
 <pre>
 &lt;<strong>variable name="user" type="com.example.User"</strong>/&gt;
 </pre>
 <p>
   Expressions within the layout are written in the attribute properties using
-  the “<code>&commat;{}</code>” syntax. Here, the TextView’s text is set to the
-  firstName property of user:
+  the “<code>&amp;commat;{}</code>” syntax. Here, the TextView’s text is set to
+  the firstName property of user:
 </p>
 
 <pre>
 &lt;TextView android:layout_width="wrap_content"
           android:layout_height="wrap_content"
-          android:text="&commat;{user.firstName}"/&gt;
+          android:text="&amp;commat;{user.firstName}"/&gt;
 </pre>
 <h3 id="data_object">
   Data Object
@@ -261,7 +278,6 @@
   to have data that is read once and never changes thereafter. It is also
   possible to use a JavaBeans objects:
 </p>
-
 <pre>
 public class User {
    private final String firstName;
@@ -280,11 +296,12 @@
 </pre>
 <p>
   From the perspective of data binding, these two classes are equivalent. The
-  expression <strong><code>&commat;{user.firstName}</code></strong> used for
-  the TextView’s <strong><code>android:text</code></strong> attribute will
+  expression <strong><code>&amp;commat;{user.firstName}</code></strong> used
+  for the TextView’s <strong><code>android:text</code></strong> attribute will
   access the <strong><code>firstName</code></strong> field in the former class
-  and the <code>getFirstName()</code> method in the latter class. Alternatively, it
-  will also be resolved to <code>firstName()</code> if that method exists.
+  and the <code>getFirstName()</code> method in the latter class.
+  Alternatively, it will also be resolved to <code>firstName()</code> if that
+  method exists.
 </p>
 
 <h3 id="binding_data">
@@ -328,16 +345,38 @@
 //or
 ListItemBinding binding = DataBindingUtil.<em>inflate</em>(layoutInflater, R.layout.<em><strong>list_item</strong></em>, viewGroup, <strong>false</strong>);
 </pre>
-
-<h3 id="binding_events">
-  Binding Events
-</h3>
+<h3 id="event_handling">Event Handling</h3>
 <p>
-  Events may be bound to handler methods directly, similar to the way
-  <strong><code>android:onClick</code></strong> can be assigned to a method in the Activity.
-  Event attribute names are governed by the name of the listener method with a few exceptions.
-  For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()},
-  so the attribute for this event is <code>android:onLongClick</code>.
+Data Binding allows you to write expressions handling events that are dispatched from the views (e.g. onClick).
+Event attribute names are governed by the name of the listener method with a few exceptions.
+For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()},
+so the attribute for this event is <code>android:onLongClick</code>.
+There are two ways to handle an event.
+</p>
+<ul>
+  <li>
+    <a href="#method_references">Method References</a>: In your expressions, you can reference methods that conform to the signature of the listener method. When an expression evaluates to a method reference, Data Binding wraps the method reference and owner object in a listener, and sets that listener on the target view. If the expression evaluates to null, Data Binding does not create a listener and sets a null listener instead.
+  </li>
+  <li>
+    <a href="#listener_bindings">Listener Bindings</a>: These are lambda expressions that are evaluated when the event happens.
+Data Binding always creates a listener, which it sets on the view. When the event is dispatched, the listener evaluates the lambda expression.
+  </li>
+</ul>
+<h4 id="method_references">
+  Method References
+</h4>
+<p>
+  Events can be bound to handler methods directly, similar to the way
+  <strong><code>android:onClick</code></strong> can be assigned to a method in an Activity.
+  One major advantage compared to the {@code View#onClick} attribute is that the expression
+  is processed at compile time, so if the method does not exist or its signature is not
+  correct, you receive a compile time error.</p>
+<p>
+  The major difference between Method References and Listener Bindings is that
+  the actual listener implementation is created when the data is bound, not
+  when the event is triggered. If you prefer to evaluate the expression when
+  the event happens, you should use <a href="#listener_bindings">listener
+  binding</a>.
 </p>
 <p>
   To assign an event to its handler, use a normal binding expression, with the value
@@ -345,7 +384,6 @@
 </p>
 <pre>public class MyHandlers {
     public void onClickFriend(View view) { ... }
-    public void onClickEnemy(View view) { ... }
 }
 </pre>
 <p>
@@ -365,14 +403,121 @@
        &lt;TextView android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="&commat;{user.firstName}"
-           android:onClick="&commat;{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/&gt;
-       &lt;TextView android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:text="&commat;{user.lastName}"
-           android:onClick="&commat;{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/&gt;
+           android:onClick="&commat;{handlers::onClickFriend}"/&gt;
    &lt;/LinearLayout&gt;
 &lt;/layout&gt;
 </pre>
+<p>
+Note that the signature of the method in the expression must exactly match the signature of the method in the
+Listener object.
+</p>
+<h4 id="listener_bindings">
+  Listener Bindings
+</h4>
+<p>
+  Listener Bindings are binding expressions that run when an event happens.
+  They are similar to method references, but they let you run arbitrary data
+  binding expressions. This feature is available with Android Gradle Plugin for Gradle
+  version 2.0 and later.
+</p>
+<p>
+  In method references, the parameters of the method must
+  match the parameters of the event listener. In Listener Bindings, only your
+  return value must match the expected return value of the listener (unless it
+  is expecting void).
+  For example, you can have a presenter class that has the following method:
+</p>
+<pre>
+public class Presenter {
+    public void onSaveClick(Task task){}
+}
+</pre>
+  Then you can bind the click event to your class as follows:
+<pre>
+  &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+  &lt;layout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
+      &lt;data&gt;
+          &lt;variable name=&quot;task&quot; type=&quot;com.android.example.Task&quot; /&gt;
+          &lt;variable name=&quot;presenter&quot; type=&quot;com.android.example.Presenter&quot; /&gt;
+      &lt;/data&gt;
+      &lt;LinearLayout android:layout_width=&quot;match_parent&quot; android:layout_height=&quot;match_parent&quot;&gt;
+          &lt;Button android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot;
+          android:onClick=&quot;@{() -&gt; presenter.onSaveClick(task)}&quot; /&gt;
+      &lt;/LinearLayout&gt;
+  &lt;/layout&gt;
+</pre>
+<p>
+  Listeners are represented by lambda expressions that are allowed only as root
+  elements of your expressions. When a callback is used in an expression, Data
+  Binding automatically creates the necessary listener and registers for the
+  event. When the view fires the event, Data Binding evaluates the given
+  expression. As in regular binding expressions, you still get the null and
+  thread safety of Data Binding while these listener expressions are being
+  evaluated.
+</p>
+<p>
+  Note that in the example above, we haven't defined the {@code view} parameter
+  that is passed into {@link
+  android.view.View.OnClickListener#onClick(android.view.View view)}. Listener
+  bindings provide two choices for listener parameters: you can either ignore
+  all parameters to the method or name all of them. If you prefer to name the
+  parameters, you can use them in your expression. For example, the expression
+  above could be written as:
+</p>
+<pre>
+  android:onClick=&quot;@{(view) -&gt; presenter.onSaveClick(task)}&quot;
+</pre>
+Or if you wanted to use the parameter in the expression, it could work as follows:
+<pre>
+public class Presenter {
+    public void onSaveClick(View view, Task task){}
+}
+</pre>
+<pre>
+  android:onClick=&quot;@{(theView) -&gt; presenter.onSaveClick(theView, task)}&quot;
+</pre>
+You can use a lambda expression with more than one parameter:
+<pre>
+public class Presenter {
+    public void onCompletedChanged(Task task, boolean completed){}
+}
+</pre>
+<pre>
+  &lt;CheckBox android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot;
+        android:onCheckedChanged=&quot;@{(cb, isChecked) -&gt; presenter.completeChanged(task, isChecked)}&quot; /&gt;
+</pre>
+<p>
+  If the event you are listening to returns a value whose type is not {@code
+  void}, your expressions must return the same type of value as well. For
+  example, if you want to listen for the long click event, your expression
+  should return {@code boolean}.
+</p>
+<pre>
+public class Presenter {
+    public boolean onLongClick(View view, Task task){}
+}
+</pre>
+<pre>
+  android:onLongClick=&quot;@{(theView) -&gt; presenter.onLongClick(theView, task)}&quot;
+</pre>
+<p>
+If the expression cannot be evaluated due to {@code null} objects, Data Binding returns
+the default Java value for that type. For example, {@code null} for reference types, {@code 0} for {@code int},
+{@code false} for {@code boolean}, etc.
+</p>
+<p>
+If you need to use an expression with a predicate (e.g. ternary), you can use
+{@code void} as a symbol.
+</p>
+<pre>
+  android:onClick=&quot;@{(v) -&gt; v.isVisible() ? doSomething() : void}&quot;
+</pre>
+
+<h5>Avoid Complex Listeners</h5>
+Listener expressions are very powerful and can make your code very easy to read.
+On the other hand, listeners containing complex expressions make your layouts hard to read and unmaintainable. 
+These expressions should be as simple as passing available data from your UI to your callback method. You should implement 
+any business logic inside the callback method that you invoked from the listener expression.
 
 <p>
   Some specialized click event handlers exist and they need an attribute other than
diff --git a/docs/html/training/articles/user-data-ids.jd b/docs/html/training/articles/user-data-ids.jd
index 5a4648b..9102166 100644
--- a/docs/html/training/articles/user-data-ids.jd
+++ b/docs/html/training/articles/user-data-ids.jd
@@ -189,15 +189,15 @@
 
 <div style="padding:.5em 2em;">
 <div style="border-left:4px solid #999;padding:0 1em;font-style:italic;">
-<p>...upon reset, a new advertising
+<p>...if reset, a new advertising
   identifier must not be connected to a previous advertising identifier or data
   derived from a previous advertising identifier without the explicit consent
-  of the user</span></p>
+  of the user.</span></p>
 </div>
 </div>
 
 <p>
-  <em><strong>Always respect the associated Interest Based Advertising
+  <em><strong>Always respect the associated Personalized Ads
   flag</strong></em>. Advertising IDs are configurable in that users can limit
   the amount of tracking associated with the ID. Always use the <code><a href=
   "https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html#isLimitAdTrackingEnabled()">
@@ -210,10 +210,10 @@
 
 <div style="padding:.5em 2em;">
 <div style="border-left:4px solid #999;padding:0 1em;font-style:italic;">
-<p>...you must abide by a user’s ‘opt out of
-  interest-based advertising’ setting. If a user has enabled this setting, you
+<p>...you must abide by a user’s ‘Opt out of interest-based advertising’ or 'Opt
+  out of Ads Personalization' setting. If a user has enabled this setting, you
   may not use the advertising identifier for creating user profiles for
-  advertising purposes or for targeting users with interest-based advertising.
+  advertising purposes or for targeting users with personalized advertising.
   Allowed activities include contextual advertising, frequency capping,
   conversion tracking, reporting and security and fraud detection.</span></p>
 </div>
@@ -286,7 +286,8 @@
   <code>account_id</code> column in both tables, which would be a violation of
   the <a href=
   "https://play.google.com/about/developer-content-policy.html">Google Play
-  Developer Content Policy</a>.
+  Developer Content Policy</a>, if you did not get explicit permission from
+  your users.
 </p>
 
 <p>
diff --git a/docs/html/training/auto/audio/index.jd b/docs/html/training/auto/audio/index.jd
index aa20e3a..3a1b1e88 100644
--- a/docs/html/training/auto/audio/index.jd
+++ b/docs/html/training/auto/audio/index.jd
@@ -21,6 +21,7 @@
       <li><a href="#config_manifest">Configure Your Manifest</a></li>
       <li><a href="#isconnected">Determine if Your App is Connected</a></li>
       <li><a href="#alarm">Handle Alarms</a></li>
+      <li><a href="#mediaadv">Handle Media Advertisements</a></li>
       <li><a href="#implement_browser">Build a Browser Service</a></li>
       <li><a href="#implement_callback">Implement Play Controls</a></li>
       <li><a href="#support_voice">Support Voice Actions</a></li>
@@ -261,7 +262,7 @@
 <ul>
 <li>Disable the alarm.</li>
 <li>Play the alarm over
-<a href="{@docRoot}reference/android/media/AudioManager.html">STREAM_ALARM</a>,
+<a href="{@docRoot}reference/android/media/AudioManager.html#STREAM_ALARM">STREAM_ALARM</a>,
  and provide a UI on the phone screen to disable the alarm.</li>
 </ul>
 
@@ -279,6 +280,33 @@
   }
 </pre>
 
+<h2 id="mediaadv">Handle Media Advertisements</h2>
+<p>By default, Android Auto displays a notification when
+the media metadata changes during an audio playback session. When a media
+app switches from playing music to running an advertisement, it is distracting
+(and unnecessary) to display a notification to the user. To prevent Android Auto
+from displaying a notification in this case, you must set the media metadata
+key {@code android.media.metadata.ADVERTISEMENT} to 1, as shown in the code
+snippet below:
+
+<pre>
+
+&#64;Override
+public static final String EXTRA_METADATA_ADVERTISEMENT =
+            "android.media.metadata.ADVERTISEMENT";
+
+public void onPlayFromMediaId(String mediaId, Bundle extras) {
+    MediaMetadata.Builder builder = new MediaMetadata.Builder();
+    // ...
+    if (isAd(mediaId)) {
+        builder.putLong(EXTRA_METADATA_ADVERTISEMENT, 1);
+    }
+    // ...
+    mediaSession.setMetadata(builder.build());
+}
+
+</pre>
+
 <h2 id="implement_browser">Build a Browser Service</h2>
 
 <p>Auto devices interact with your app by contacting its implementation of a
diff --git a/docs/html/training/wearables/watch-faces/service.jd b/docs/html/training/wearables/watch-faces/service.jd
index 20eb0c77..b54f51a 100755
--- a/docs/html/training/wearables/watch-faces/service.jd
+++ b/docs/html/training/wearables/watch-faces/service.jd
@@ -93,24 +93,20 @@
 
 <h3 id="Permissions">Declare Permissions</h3>
 
-<p>Watch faces require the <code>PROVIDE_BACKGROUND</code> and <code>WAKE_LOCK</code> permissions.
-Add the following permissions to the manifest files of both the wearable app and the mobile
-app under the <code>manifest</code> element:</p>
+<p>A watch face requires the <code>WAKE_LOCK</code> permission.
+Add the following permission to the manifest files of both the wearable app
+and the mobile app under the <code>manifest</code> element:</p>
 
 <pre>
 &lt;manifest ...>
     &lt;uses-permission
-        android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
-    &lt;uses-permission
         android:name="android.permission.WAKE_LOCK" />
     ...
 &lt;/manifest>
 </pre>
 
-<p class="caution"><strong>Caution:</strong> The handheld app must include all the permissions
-declared in the wearable app.</p>
-
-
+<p class="caution"><strong>Caution:</strong> The handheld app must include all
+of the permissions declared in the wearable app.</p>
 
 <h2 id="CallbackMethods">Implement the Service and Callback Methods</h2>
 
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 6bb93aec..0bdc76f 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -239,6 +239,17 @@
 
     @Override
     public void draw(Canvas canvas) {
+        if (!canvas.isHardwareAccelerated() && mAnimatorSet instanceof VectorDrawableAnimatorRT) {
+            // If we have SW canvas and the RT animation is waiting to start, We need to fallback
+            // to UI thread animation for AVD.
+            if (!mAnimatorSet.isRunning() &&
+                    ((VectorDrawableAnimatorRT) mAnimatorSet).mPendingAnimationActions.size() > 0) {
+                VectorDrawableAnimatorRT oldAnim = (VectorDrawableAnimatorRT) mAnimatorSet;
+                mAnimatorSet = new VectorDrawableAnimatorUI(this);
+                mAnimatorSet.init(mAnimatorSetFromXml);
+                oldAnim.transferPendingActions(mAnimatorSet);
+            }
+        }
         mAnimatorSet.onDraw(canvas);
         mAnimatedVectorState.mVectorDrawable.draw(canvas);
     }
@@ -1590,6 +1601,25 @@
         private static void callOnFinished(VectorDrawableAnimatorRT set, int id) {
             set.onAnimationEnd(id);
         }
+
+        private void transferPendingActions(VectorDrawableAnimator animatorSet) {
+            for (int i = 0; i < mPendingAnimationActions.size(); i++) {
+                int pendingAction = mPendingAnimationActions.get(i);
+                if (pendingAction == START_ANIMATION) {
+                    animatorSet.start();
+                } else if (pendingAction == END_ANIMATION) {
+                    animatorSet.end();
+                } else if (pendingAction == REVERSE_ANIMATION) {
+                    animatorSet.reverse();
+                } else if (pendingAction == RESET_ANIMATION) {
+                    animatorSet.reset();
+                } else {
+                    throw new UnsupportedOperationException("Animation action " +
+                            pendingAction + "is not supported");
+                }
+            }
+            mPendingAnimationActions.clear();
+        }
     }
 
     private static native long nCreateAnimatorSet();
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index c6977746..d5143da 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -75,6 +75,9 @@
     private long mEnterAnimationEnd;
     private long mExitAnimationEnd;
 
+    /** Callback that blocks invalidation. Used for drawable initialization. */
+    private BlockInvalidateCallback mBlockInvalidateCallback;
+
     // overrides from Drawable
 
     @Override
@@ -500,11 +503,14 @@
      * @param d The drawable to initialize.
      */
     private void initializeDrawableForDisplay(Drawable d) {
+        if (mBlockInvalidateCallback == null) {
+            mBlockInvalidateCallback = new BlockInvalidateCallback();
+        }
+
         // Temporary fix for suspending callbacks during initialization. We
         // don't want any of these setters causing an invalidate() since that
         // may call back into DrawableContainer.
-        final Callback cb = d.getCallback();
-        d.setCallback(null);
+        d.setCallback(mBlockInvalidateCallback.wrap(d.getCallback()));
 
         try {
             if (mDrawableContainerState.mEnterFadeDuration <= 0 && mHasAlpha) {
@@ -537,7 +543,7 @@
                         hotspotBounds.right, hotspotBounds.bottom);
             }
         } finally {
-            d.setCallback(cb);
+            d.setCallback(mBlockInvalidateCallback.unwrap());
         }
     }
 
@@ -1215,4 +1221,41 @@
         mLastIndex = -1;
         mLastDrawable = null;
     }
+
+    /**
+     * Callback that blocks drawable invalidation.
+     */
+    private static class BlockInvalidateCallback implements Drawable.Callback {
+        private Drawable.Callback mCallback;
+
+        public BlockInvalidateCallback wrap(Drawable.Callback callback) {
+            mCallback = callback;
+            return this;
+        }
+
+        public Drawable.Callback unwrap() {
+            final Drawable.Callback callback = mCallback;
+            mCallback = null;
+            return callback;
+        }
+
+        @Override
+        public void invalidateDrawable(@NonNull Drawable who) {
+            // Ignore invalidation.
+        }
+
+        @Override
+        public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
+            if (mCallback != null) {
+                mCallback.scheduleDrawable(who, what, when);
+            }
+        }
+
+        @Override
+        public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
+            if (mCallback != null) {
+                mCallback.unscheduleDrawable(who, what);
+            }
+        }
+    }
 }
diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java
index c1df28c..7a2cbd0 100644
--- a/keystore/java/android/security/GateKeeper.java
+++ b/keystore/java/android/security/GateKeeper.java
@@ -16,6 +16,7 @@
 
 package android.security;
 
+import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -32,7 +33,7 @@
 
     public static IGateKeeperService getService() {
         IGateKeeperService service = IGateKeeperService.Stub.asInterface(
-                ServiceManager.getService("android.service.gatekeeper.IGateKeeperService"));
+                ServiceManager.getService(Context.GATEKEEPER_SERVICE));
         if (service == null) {
             throw new IllegalStateException("Gatekeeper service not available");
         }
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index d447a38..ceeb12b 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -6174,7 +6174,7 @@
     if (id >= 256) {
         LOG_ALWAYS_FATAL("Package id out of range");
         return NO_ERROR;
-    } else if (id == 0 || appAsLib || isSystemAsset) {
+    } else if (id == 0 || (id == 0x7f && appAsLib) || isSystemAsset) {
         // This is a library or a system asset, so assign an ID
         id = mNextPackageId++;
     }
diff --git a/libs/hwui/AnimationContext.cpp b/libs/hwui/AnimationContext.cpp
index 097be08..5759ccd 100644
--- a/libs/hwui/AnimationContext.cpp
+++ b/libs/hwui/AnimationContext.cpp
@@ -63,7 +63,7 @@
         mCurrentFrameAnimations.mNextHandle = head;
         head->mPreviousHandle = &mCurrentFrameAnimations;
     }
-    mFrameTimeMs = mClock.computeFrameTimeMs();
+    mFrameTimeMs = ns2ms(mClock.latestVsync());
 }
 
 void AnimationContext::runRemainingAnimations(TreeInfo& info) {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 5a3300a..f8797bf 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -474,7 +474,7 @@
 }
 #endif
 
-void RenderNode::syncDisplayList(TreeObserver* observer) {
+void RenderNode::syncDisplayList(TreeInfo* info) {
     // Make sure we inc first so that we don't fluctuate between 0 and 1,
     // which would thrash the layer cache
     if (mStagingDisplayList) {
@@ -482,7 +482,7 @@
             child->renderNode->incParentRefCount();
         }
     }
-    deleteDisplayList(observer);
+    deleteDisplayList(info ? info->observer : nullptr, info);
     mDisplayList = mStagingDisplayList;
     mStagingDisplayList = nullptr;
     if (mDisplayList) {
@@ -501,15 +501,15 @@
         // Damage with the old display list first then the new one to catch any
         // changes in isRenderable or, in the future, bounds
         damageSelf(info);
-        syncDisplayList(info.observer);
+        syncDisplayList(&info);
         damageSelf(info);
     }
 }
 
-void RenderNode::deleteDisplayList(TreeObserver* observer) {
+void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) {
     if (mDisplayList) {
         for (auto&& child : mDisplayList->getChildren()) {
-            child->renderNode->decParentRefCount(observer);
+            child->renderNode->decParentRefCount(observer, info);
         }
     }
     delete mDisplayList;
@@ -541,35 +541,38 @@
     }
 }
 
-void RenderNode::destroyHardwareResources(TreeObserver* observer) {
+void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) {
     if (mLayer) {
         destroyLayer(mLayer);
         mLayer = nullptr;
     }
     if (mDisplayList) {
         for (auto&& child : mDisplayList->getChildren()) {
-            child->renderNode->destroyHardwareResources(observer);
+            child->renderNode->destroyHardwareResources(observer, info);
         }
         if (mNeedsDisplayListSync) {
             // Next prepare tree we are going to push a new display list, so we can
             // drop our current one now
-            deleteDisplayList(observer);
+            deleteDisplayList(observer, info);
         }
     }
 }
 
-void RenderNode::decParentRefCount(TreeObserver* observer) {
+void RenderNode::decParentRefCount(TreeObserver* observer, TreeInfo* info) {
     LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!");
     mParentCount--;
     if (!mParentCount) {
         if (observer) {
             observer->onMaybeRemovedFromTree(this);
         }
+        if (CC_UNLIKELY(mPositionListener.get())) {
+            mPositionListener->onPositionLost(*this, info);
+        }
         // If a child of ours is being attached to our parent then this will incorrectly
         // destroy its hardware resources. However, this situation is highly unlikely
         // and the failure is "just" that the layer is re-created, so this should
         // be safe enough
-        destroyHardwareResources(observer);
+        destroyHardwareResources(observer, info);
     }
 }
 
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index acdc3d8..f80be5e 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -196,7 +196,7 @@
     }
 
     ANDROID_API virtual void prepareTree(TreeInfo& info);
-    void destroyHardwareResources(TreeObserver* observer);
+    void destroyHardwareResources(TreeObserver* observer, TreeInfo* info = nullptr);
 
     // UI thread only!
     ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
@@ -228,10 +228,19 @@
     OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
 #endif
 
+    // Note: The position callbacks are relying on the listener using
+    // the frameNumber to appropriately batch/synchronize these transactions.
+    // There is no other filtering/batching to ensure that only the "final"
+    // state called once per frame.
     class ANDROID_API PositionListener {
     public:
         virtual ~PositionListener() {}
+        // Called when the RenderNode's position changes
         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
+        // Called when the RenderNode no longer has a position. As in, it's
+        // no longer being drawn.
+        // Note, tree info might be null
+        virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0;
     };
 
     // Note this is not thread safe, this needs to be called
@@ -306,7 +315,7 @@
 
 
     void syncProperties();
-    void syncDisplayList(TreeObserver* observer);
+    void syncDisplayList(TreeInfo* info);
 
     void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
     void pushStagingPropertiesChanges(TreeInfo& info);
@@ -317,11 +326,11 @@
 #endif
     void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
     void pushLayerUpdate(TreeInfo& info);
-    void deleteDisplayList(TreeObserver* observer);
+    void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr);
     void damageSelf(TreeInfo& info);
 
     void incParentRefCount() { mParentCount++; }
-    void decParentRefCount(TreeObserver* observer);
+    void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr);
 
     String8 mName;
     sp<VirtualLightRefBase> mUserContext;
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index f846d6a..6c2575f 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -43,10 +43,6 @@
     return mFrameTimeNanos;
 }
 
-nsecs_t TimeLord::computeFrameTimeMs() {
-    return nanoseconds_to_milliseconds(computeFrameTimeNanos());
-}
-
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 5464399..68a0f7f 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -34,7 +34,6 @@
     // returns true if the vsync is newer, false if it was rejected for staleness
     bool vsyncReceived(nsecs_t vsync);
     nsecs_t latestVsync() { return mFrameTimeNanos; }
-    nsecs_t computeFrameTimeMs();
     nsecs_t computeFrameTimeNanos();
 
 private:
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index b246360..2b3ed87 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -2008,7 +2008,7 @@
      * No-op method to keep backward-compatibility.
      * Don't use it. Use {@link #registerGnssMeasurementsCallback} instead.
      * @hide
-     * @deprecated
+     * @deprecated Not supported anymore.
      */
     @Deprecated
     @SystemApi
@@ -2065,7 +2065,7 @@
      * No-op method to keep backward-compatibility.
      * Don't use it. Use {@link #registerGnssNavigationMessageCallback} instead.
      * @hide
-     * @deprecated
+     * @deprecated Not supported anymore.
      */
     @Deprecated
     @SystemApi
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 4d40e6b..8d4a151 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -476,10 +476,10 @@
  *     <td>This method can be called in any state and calling it does not change
  *         the object state. </p></td></tr>
  * <tr><td>setPlaybackParams</p></td>
- *     <td>any </p></td>
- *     <td>{} </p></td>
- *     <td>This method can be called in any state and calling it does not change
- *         the object state. </p></td></tr>
+ *     <td>{Initialized, Prepared, Started, Paused, PlaybackCompleted, Error}</p></td>
+ *     <td>{Idle, Stopped} </p></td>
+ *     <td>This method will change state in some cases, depending on when it's called.
+ *         </p></td></tr>
  * <tr><td>setScreenOnWhilePlaying</></td>
  *     <td>any </p></td>
  *     <td>{} </p></td>
@@ -1449,12 +1449,18 @@
     }
 
     /**
-     * Sets playback rate using {@link PlaybackParams}.
+     * Sets playback rate using {@link PlaybackParams}. The object sets its internal
+     * PlaybackParams to the input, except that the object remembers previous speed
+     * when input speed is zero. This allows the object to resume at previous speed
+     * when start() is called. Calling it before the object is prepared does not change
+     * the object state. After the object is prepared, calling it with zero speed is
+     * equivalent to calling pause(). After the object is prepared, calling it with
+     * non-zero speed is equivalent to calling start().
      *
      * @param params the playback params.
      *
      * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
+     * initialized or has been released.
      * @throws IllegalArgumentException if params is not supported.
      */
     public native void setPlaybackParams(@NonNull PlaybackParams params);
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index 359ebad..c62d930 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -68,16 +68,19 @@
         if (sizeToRead <= kMinSizeToRead) {
             sizeToRead = kMinSizeToRead;
         }
+
         void* tempBuffer = malloc(sizeToRead);
-        if (tempBuffer != NULL) {
-            size_t bytesRead = mStream->read(tempBuffer, sizeToRead);
-            if (bytesRead != sizeToRead) {
-                free(tempBuffer);
-                return piex::Error::kFail;
-            }
-            mStreamBuffer.write(tempBuffer, bytesRead);
-            free(tempBuffer);
+        if (tempBuffer == NULL) {
+          return piex::Error::kFail;
         }
+
+        size_t bytesRead = mStream->read(tempBuffer, sizeToRead);
+        if (bytesRead != sizeToRead) {
+            free(tempBuffer);
+            return piex::Error::kFail;
+        }
+        mStreamBuffer.write(tempBuffer, bytesRead);
+        free(tempBuffer);
     }
 
     // Read bytes.
@@ -126,8 +129,8 @@
     size_t size = fread((void*)data, sizeof(std::uint8_t), length, mFile);
     mPosition += size;
 
-    // Handle errors.
-    if (ferror(mFile)) {
+    // Handle errors and verify the size.
+    if (ferror(mFile) || size != length) {
         ALOGV("GetData read failed: (offset: %zu, length: %zu)", offset, length);
         return piex::Error::kFail;
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 9d4b50c..1922773 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -215,9 +215,12 @@
         includeState(state);
 
         // Advanced roots are shown by default without menu option if forced by config or intent.
-        state.showAdvanced = Shared.shouldShowDeviceRoot(this, intent);
+        boolean forceAdvanced = Shared.shouldShowDeviceRoot(this, intent);
+        boolean chosenAdvanced = LocalPreferences.getShowDeviceRoot(this, state.action);
+        state.showAdvanced = forceAdvanced || chosenAdvanced;
+
         // Menu option is shown for whitelisted intents if advanced roots are not shown by default.
-        state.showAdvancedOption = !state.showAdvanced && (
+        state.showAdvancedOption = !forceAdvanced && (
                 Shared.shouldShowFancyFeatures(this)
                 || state.action == ACTION_OPEN
                 || state.action == ACTION_CREATE
@@ -483,6 +486,7 @@
         Metrics.logUserAction(this,
                 display ? Metrics.USER_ACTION_SHOW_ADVANCED : Metrics.USER_ACTION_HIDE_ADVANCED);
 
+        LocalPreferences.setShowDeviceRoot(this, mState.action, display);
         mState.showAdvanced = display;
         RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
         invalidateOptionsMenu();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index 2315664..d2e9885e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -18,9 +18,6 @@
 
 import static com.android.documentsui.State.MODE_UNKNOWN;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -28,11 +25,16 @@
 import android.os.UserHandle;
 import android.preference.PreferenceManager;
 
+import com.android.documentsui.State.ActionType;
 import com.android.documentsui.State.ViewMode;
 import com.android.documentsui.model.RootInfo;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 public class LocalPreferences {
     private static final String KEY_FILE_SIZE = "fileSize";
+    private static final String INCLUDE_DEVICE_ROOT = "includeDeviceRoot-";
     private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
 
     public static boolean getDisplayFileSize(Context context) {
@@ -48,9 +50,17 @@
         getPrefs(context).edit().putBoolean(KEY_FILE_SIZE, display).apply();
     }
 
+    public static boolean getShowDeviceRoot(Context context, @ActionType int action) {
+        return getPrefs(context).getBoolean(INCLUDE_DEVICE_ROOT + action, false);
+    }
+
+    public static void setShowDeviceRoot(
+            Context context, @ActionType int action, boolean display) {
+        getPrefs(context).edit().putBoolean(INCLUDE_DEVICE_ROOT + action, display).apply();
+    }
+
     public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) {
         assert(viewMode != MODE_UNKNOWN);
-
         getPrefs(context).edit().putInt(createKey(root), viewMode).apply();
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
index f10af43..53fa3cc4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/CopyJob.java
@@ -227,7 +227,7 @@
         try {
             mBatchSize = calculateSize(mSrcs);
         } catch (ResourceException e) {
-            Log.w(TAG, "Failed to calculate total size. Copying without progress.");
+            Log.w(TAG, "Failed to calculate total size. Copying without progress.", e);
             mBatchSize = -1;
         }
 
@@ -236,25 +236,19 @@
         for (int i = 0; i < mSrcs.size() && !isCanceled(); ++i) {
             srcInfo = mSrcs.get(i);
 
-            // Guard unsupported recursive operation.
-            try {
-                if (dstInfo.equals(srcInfo) || isDescendentOf(srcInfo, dstInfo)) {
-                    throw new ResourceException("Cannot copy to itself recursively.");
-                }
-            } catch (ResourceException e) {
-                Log.e(TAG, e.toString());
-                onFileFailed(srcInfo);
-                continue;
-            }
-
             if (DEBUG) Log.d(TAG,
                     "Copying " + srcInfo.displayName + " (" + srcInfo.derivedUri + ")"
                     + " to " + dstInfo.displayName + " (" + dstInfo.derivedUri + ")");
 
             try {
-                processDocument(srcInfo, null, dstInfo);
+                if (dstInfo.equals(srcInfo) || isDescendentOf(srcInfo, dstInfo)) {
+                    Log.e(TAG, "Skipping recursive copy of " + srcInfo.derivedUri);
+                    onFileFailed(srcInfo);
+                } else {
+                    processDocument(srcInfo, null, dstInfo);
+                }
             } catch (ResourceException e) {
-                Log.e(TAG, e.toString());
+                Log.e(TAG, "Failed to copy " + srcInfo.derivedUri, e);
                 onFileFailed(srcInfo);
             }
         }
@@ -306,7 +300,7 @@
                     }
                 } catch (RemoteException | RuntimeException e) {
                     Log.e(TAG, "Provider side copy failed for: " + src.derivedUri
-                            + " due to an exception: " + e);
+                            + " due to an exception.", e);
                 }
                 // If optimized copy fails, then fallback to byte-by-byte copy.
                 if (DEBUG) Log.d(TAG, "Fallback to byte-by-byte copy for: " + src.derivedUri);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
index 8f45162..36a0f32 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/DeleteJob.java
@@ -86,7 +86,7 @@
             try {
                 deleteDocument(doc, mSrcParent);
             } catch (ResourceException e) {
-                Log.e(TAG, "Failed to delete document @ " + doc.derivedUri);
+                Log.e(TAG, "Failed to delete document @ " + doc.derivedUri, e);
                 onFileFailed(doc);
             }
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
index aaa7596..1118171 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/services/MoveJob.java
@@ -98,7 +98,7 @@
                     }
                 } catch (RemoteException | RuntimeException e) {
                     Log.e(TAG, "Provider side move failed for: " + src.derivedUri
-                            + " due to an exception: " + e);
+                            + " due to an exception: ", e);
                 }
                 // If optimized move fails, then fallback to byte-by-byte copy.
                 if (DEBUG) Log.d(TAG, "Fallback to byte-by-byte move for: " + src.derivedUri);
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index 13fdb05..bd0cc8c 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -85,7 +85,7 @@
     <string name="accessibility_wifi_signal_full" msgid="7061045677694702">"Wi-Fi: signal to‘liq"</string>
     <string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
     <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"O‘chirilgan ilovalar"</string>
-    <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"O‘chirib yuborilgan ilovalar va foydalanuvchilar"</string>
+    <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"O‘chirib tashlangan ilova va foydalanuvchilar"</string>
     <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB modem"</string>
     <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ixcham hotspot"</string>
     <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth modem"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
index 76ba0a7..5791168 100644
--- a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.Log;
@@ -162,10 +163,9 @@
             intent.putExtra(EXTRA_CONTEXT, backupContext);
         }
         intent.putExtra(EXTRA_THEME, 1 /* Light, dark action bar */);
-        Theme theme = context.getTheme();
-        TypedValue typedValue = new TypedValue();
-        theme.resolveAttribute(android.R.attr.colorPrimary, typedValue, true);
-        intent.putExtra(EXTRA_PRIMARY_COLOR, context.getColor(typedValue.resourceId));
+        TypedArray array = context.obtainStyledAttributes(new int[]{android.R.attr.colorPrimary});
+        intent.putExtra(EXTRA_PRIMARY_COLOR, array.getColor(0, 0));
+        array.recycle();
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index d98f1a4..7993131 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -1,5 +1,6 @@
 package com.android.settingslib;
 
+import android.annotation.ColorInt;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
@@ -8,6 +9,7 @@
 import android.content.pm.UserInfo;
 import android.content.pm.Signature;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.Drawable;
@@ -154,6 +156,14 @@
         return statusString;
     }
 
+    @ColorInt
+    public static int getColorAccent(Context context) {
+        TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
+        @ColorInt int colorAccent = ta.getColor(0, 0);
+        ta.recycle();
+        return colorAccent;
+    }
+
     /**
      * Determine whether a package is a "system package", in which case certain things (like
      * disabling notifications or disabling the package altogether) should be disallowed.
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 08364d2..6658c14 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -326,6 +326,13 @@
         }
 
         @Override
+        protected void onPreExecute() {
+            if (sConfigTracker == null || sTileCache == null) {
+                getDashboardCategories();
+            }
+        }
+
+        @Override
         protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
             for (int i = 0; i < dashboardCategories.size(); i++) {
                 DashboardCategory category = dashboardCategories.get(i);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
index 8512dca..f4f7986 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -76,6 +76,8 @@
                         bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
                                 backingStore);
                         bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
+                        bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
+                                backingStore.get(index));
                         if (DEBUG) {
                             Slog.i(LOG_TAG, "Exported index:" + index + " for key:"
                                     + SettingsProvider.keyToString(key));
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 25dc357..809774b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -165,6 +165,9 @@
     <!-- the ability to rename notifications posted by other apps -->
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
 
+    <!-- shortcut manager -->
+    <uses-permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING" />
+
     <application
         android:name=".SystemUIApplication"
         android:persistent="true"
diff --git a/packages/SystemUI/res/color/notification_guts_buttons.xml b/packages/SystemUI/res/color/notification_guts_buttons.xml
index c211e43..3b8d59b 100644
--- a/packages/SystemUI/res/color/notification_guts_buttons.xml
+++ b/packages/SystemUI/res/color/notification_guts_buttons.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_checked="true"
-          android:color="@*android:color/material_deep_teal_500" />
+          android:color="?android:attr/colorAccent" />
     <item android:color="@android:color/black"
           android:alpha=".54" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/fab_background.xml b/packages/SystemUI/res/color/qs_detail_progress_track.xml
similarity index 62%
copy from packages/SystemUI/res/drawable/fab_background.xml
copy to packages/SystemUI/res/color/qs_detail_progress_track.xml
index 7f23f2b..c56382e 100644
--- a/packages/SystemUI/res/drawable/fab_background.xml
+++ b/packages/SystemUI/res/color/qs_detail_progress_track.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,11 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@color/fab_ripple">
-    <item>
-        <shape>
-            <solid android:color="@color/fab_shape" />
-        </shape>
-    </item>
-</ripple>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- I really don't want to define this, but the View that uses this asset uses both the
+         light and dark accent colors. -->
+    <item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_light" />
+</selector>
diff --git a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml b/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
index 20251c2..344859c 100644
--- a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
+++ b/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
@@ -17,6 +17,6 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true" android:color="@color/current_user_border_color" />
+    <item android:state_activated="true" android:color="?android:attr/colorAccent" />
     <item android:color="@android:color/transparent" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/qs_user_detail_name.xml b/packages/SystemUI/res/color/qs_user_detail_name.xml
index 35c7a4f..e262209 100644
--- a/packages/SystemUI/res/color/qs_user_detail_name.xml
+++ b/packages/SystemUI/res/color/qs_user_detail_name.xml
@@ -17,7 +17,7 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_activated="true" android:color="@color/current_user_border_color" />
+    <item android:state_activated="true" android:color="?android:attr/colorAccent" />
     <item android:state_enabled="false" android:color="@color/qs_tile_disabled_color" />
     <item android:color="#66ffffff" /> <!-- 40% white -->
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/fab_background.xml b/packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml
similarity index 67%
rename from packages/SystemUI/res/drawable/fab_background.xml
rename to packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml
index 7f23f2b..5370f7a 100644
--- a/packages/SystemUI/res/drawable/fab_background.xml
+++ b/packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,11 +13,6 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-        android:color="@color/fab_ripple">
-    <item>
-        <shape>
-            <solid android:color="@color/fab_shape" />
-        </shape>
-    </item>
-</ripple>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:alpha="0.25" android:color="?android:attr/colorAccent" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
index e901e40..0c69d89 100644
--- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml
+++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@color/system_primary_color" />
+    <solid android:color="?android:attr/colorPrimary" />
 </shape>
diff --git a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
index dc978fe..24ac018 100644
--- a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
+++ b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
@@ -20,7 +20,7 @@
         android:viewportHeight="24.0">
     <path
         android:pathData="m18.250000,12.000000a6.250000,6.250000 0.000000,1.000000 1.000000,-12.500000 0.000000,6.250000 6.250000,0.000000 1.000000,1.000000 12.500000,0.000000z"
-        android:fillColor="@color/system_primary_color" />
+        android:fillColor="?android:attr/colorPrimary" />
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M20.000000,8.700000L20.000000,4.000000L15.300000,4.000000L12.000000,0.700000 8.700000,4.000000L4.000000,4.000000L4.000000,8.700000L0.700000,12.000000 4.000000,15.300000L4.000000,20.000000L8.700000,20.000000L12.000000,23.299999 15.300000,20.000000L20.000000,20.000000L20.000000,15.300000L23.299999,12.000000 20.000000,8.700000zM12.000000,18.000000C8.700000,18.000000 6.000000,15.300000 6.000000,12.000000 6.000000,8.700000 8.700000,6.000000 12.000000,6.000000c3.300000,0.000000 6.000000,2.700000 6.000000,6.000000 0.000000,3.300000 -2.700000,6.000000 -6.000000,6.000000zM12.000000,8.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000 0.000000,2.200000 1.800000,4.000000 4.000000,4.000000 2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000 0.000000,-2.200000 -1.800000,-4.000000 -4.000000,-4.000000z"/>
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 1bf7d4c..8ea9e06 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -15,6 +15,6 @@
 -->
 <inset xmlns:android="http://schemas.android.com/apk/res/android">
     <shape>
-        <solid android:color="@color/system_primary_color"/>
+        <solid android:color="?android:attr/colorPrimary"/>
     </shape>
 </inset>
diff --git a/packages/SystemUI/res/drawable/qs_customizer_background.xml b/packages/SystemUI/res/drawable/qs_customizer_background.xml
index d90f820..12d8016 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_background.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_background.xml
@@ -15,5 +15,5 @@
 -->
 <transition xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:drawable="@color/qs_detail_transition" />
-    <item android:drawable="@color/system_primary_color" />
+    <item android:drawable="?android:attr/colorPrimary" />
 </transition>
diff --git a/packages/SystemUI/res/drawable/qs_detail_background.xml b/packages/SystemUI/res/drawable/qs_detail_background.xml
index 692cd44..84c793f 100644
--- a/packages/SystemUI/res/drawable/qs_detail_background.xml
+++ b/packages/SystemUI/res/drawable/qs_detail_background.xml
@@ -15,5 +15,5 @@
 -->
 <transition xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:drawable="@color/qs_detail_transition" />
-    <item android:drawable="@color/system_primary_color" />
+    <item android:drawable="?android:attr/colorPrimary" />
 </transition>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/quick_header_bg.xml b/packages/SystemUI/res/drawable/quick_header_bg.xml
index d45d673..920e6f5 100644
--- a/packages/SystemUI/res/drawable/quick_header_bg.xml
+++ b/packages/SystemUI/res/drawable/quick_header_bg.xml
@@ -17,5 +17,5 @@
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
     android:color="?android:attr/colorControlHighlight" >
-    <item android:drawable="@color/system_primary_color"/>
+    <item android:drawable="?android:attr/colorPrimary"/>
 </ripple>
diff --git a/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml b/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml
index 354b8bd..1303bdb 100644
--- a/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml
+++ b/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml
@@ -19,7 +19,7 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="oval" >
 
-    <solid android:color="@color/system_accent_color" />
+    <solid android:color="?android:attr/colorAccent" />
 
     <size
         android:height="@dimen/screen_pinning_nav_highlight_size"
diff --git a/packages/SystemUI/res/drawable/switchbar_background.xml b/packages/SystemUI/res/drawable/switchbar_background.xml
index 8d97c46..fdb6c77 100644
--- a/packages/SystemUI/res/drawable/switchbar_background.xml
+++ b/packages/SystemUI/res/drawable/switchbar_background.xml
@@ -16,6 +16,6 @@
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
     android:color="?android:attr/colorControlHighlight">
-    <item android:drawable="@color/switch_bar_background" />
+    <item android:drawable="@color/system_secondary_color" />
 </ripple>
 
diff --git a/packages/SystemUI/res/drawable/volume_dialog_background.xml b/packages/SystemUI/res/drawable/volume_dialog_background.xml
index e98bfb8..d6adea9 100644
--- a/packages/SystemUI/res/drawable/volume_dialog_background.xml
+++ b/packages/SystemUI/res/drawable/volume_dialog_background.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android" >
-    <solid android:color="@color/system_primary_color" />
+    <solid android:color="?android:attr/colorPrimary" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/zen_introduction_message_background.xml b/packages/SystemUI/res/drawable/zen_introduction_message_background.xml
index 352fb57..e5b41a3 100644
--- a/packages/SystemUI/res/drawable/zen_introduction_message_background.xml
+++ b/packages/SystemUI/res/drawable/zen_introduction_message_background.xml
@@ -17,6 +17,6 @@
 
       <corners android:radius="@dimen/borderless_button_radius" />
 
-      <solid android:color="@color/zen_introduction_message_background" />
+      <solid android:color="?android:attr/colorAccent" />
 
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
index 52cab72..69e52c5 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
@@ -53,5 +53,6 @@
             android:layout_alignParentEnd="true"
             android:textSize="14sp"
             android:scrollHorizontally="false"
-            android:layout_centerVertical="true"/>
+            android:layout_centerVertical="true"
+            android:focusable="true"/>
 </RelativeLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
index 5db6789..a3901d0 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
@@ -21,4 +21,4 @@
         android:padding="@dimen/ksh_item_padding"
         android:layout_marginStart="@dimen/ksh_item_margin_start"
         android:scaleType="fitXY"
-        android:background="@drawable/ksh_key_item_background"/>
+        android:background="@drawable/ksh_key_item_background" />
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
index 31a8773..b06f7fc 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
@@ -23,4 +23,5 @@
           android:textColor="@color/ksh_key_item_color"
           android:singleLine="true"
           android:gravity="center"
-          android:textSize="@dimen/ksh_item_text_size"/>
+          android:textSize="@dimen/ksh_item_text_size"
+          android:textAllCaps="true"/>
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index d09c42b..e84ed23 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -26,7 +26,8 @@
         android:orientation="vertical"
         android:paddingStart="@*android:dimen/notification_content_margin_start"
         android:paddingEnd="8dp"
-        android:background="@color/notification_guts_bg_color">
+        android:background="@color/notification_guts_bg_color"
+        android:theme="@*android:style/Theme.DeviceDefault.Light">
 
     <!-- header -->
     <LinearLayout
@@ -145,8 +146,8 @@
                     android:focusable="true"
                     android:background="#00ffffff"
                     android:progressBackgroundTint="@color/notification_guts_secondary_slider_color"
-                    android:thumbTint="@color/notification_guts_slider_color"
-                    android:progressTint="@color/notification_guts_slider_color"
+                    android:thumbTint="?android:attr/colorAccent"
+                    android:progressTint="?android:attr/colorAccent"
                     style="@android:style/Widget.Material.SeekBar.Discrete"
                     android:tickMarkTint="@android:color/black" />
 
diff --git a/packages/SystemUI/res/layout/screen_pinning_request.xml b/packages/SystemUI/res/layout/screen_pinning_request.xml
index fea45cc..d55ba94 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request.xml
@@ -21,7 +21,8 @@
     android:layout_height="wrap_content"
     android:gravity="bottom|center_horizontal"
     android:layoutDirection="ltr"
-    android:orientation="vertical" >
+    android:orientation="vertical"
+    android:theme="@android:style/Theme.DeviceDefault.Light">
 
     <include
         android:layout_width="@dimen/screen_pinning_request_width"
@@ -32,7 +33,7 @@
         android:id="@+id/spacer"
         android:layout_width="@dimen/screen_pinning_request_width"
         android:layout_height="18dp"
-        android:background="@color/screen_pinning_request_bg" />
+        android:background="?android:attr/colorAccent" />
 
     <include
         android:layout_width="@dimen/screen_pinning_request_width"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
index 60112be..e3662f17 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
@@ -28,7 +28,7 @@
     android:id="@+id/screen_pinning_buttons"
     android:layout_width="match_parent"
     android:layout_height="@dimen/screen_pinning_request_button_height"
-    android:background="@color/screen_pinning_request_bg" >
+    android:background="?android:attr/colorAccent">
 
     <View
         android:layout_width="@dimen/screen_pinning_request_side_width"
@@ -42,7 +42,8 @@
         android:layout_height="@dimen/screen_pinning_request_button_height"
         android:layout_weight="0"
         android:paddingStart="@dimen/screen_pinning_request_frame_padding"
-        android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
+        android:paddingEnd="@dimen/screen_pinning_request_frame_padding"
+        android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
 
         <ImageView
             android:id="@+id/screen_pinning_back_bg_light"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
index ebad7a4..3649ffb 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
@@ -25,8 +25,8 @@
     android:id="@+id/screen_pinning_buttons"
     android:layout_height="match_parent"
     android:layout_width="@dimen/screen_pinning_request_button_height"
-    android:background="@color/screen_pinning_request_bg"
-    android:orientation="vertical" >
+    android:background="?android:attr/colorAccent"
+    android:orientation="vertical">
 
     <View
         android:layout_height="@dimen/screen_pinning_request_side_width"
@@ -82,7 +82,8 @@
         android:id="@+id/screen_pinning_back_group"
         android:layout_height="@dimen/screen_pinning_request_button_width"
         android:layout_width="@dimen/screen_pinning_request_button_height"
-        android:layout_weight="0" >
+        android:layout_weight="0"
+        android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
 
         <ImageView
             android:id="@+id/screen_pinning_back_bg_light"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml b/packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml
index e6c22d4..ec16991 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml
@@ -20,7 +20,8 @@
     android:layout_height="@dimen/screen_pinning_request_width"
     android:layout_width="wrap_content"
     android:gravity="right|center_vertical"
-    android:orientation="horizontal" >
+    android:orientation="horizontal"
+    android:theme="@android:style/Theme.DeviceDefault.Light">
 
     <include
         android:layout_width="360dp"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
index df957f4..cdad94b 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
@@ -20,8 +20,8 @@
     android:id="@+id/screen_pinning_text_area"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:background="@color/screen_pinning_request_bg"
-    android:gravity="center_vertical" >
+    android:background="?android:attr/colorAccent"
+    android:gravity="center_vertical">
 
     <TextView
         android:id="@+id/screen_pinning_title"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
deleted file mode 100644
index c5cd65e..0000000
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ /dev/null
@@ -1,195 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
--->
-
-<!-- Extends RelativeLayout -->
-<com.android.systemui.statusbar.phone.StatusBarHeaderView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/header"
-    android:layout_width="@dimen/notification_panel_width"
-    android:layout_height="@dimen/status_bar_header_height"
-    android:layout_gravity="@integer/notification_panel_layout_gravity"
-    android:baselineAligned="false"
-    android:elevation="4dp"
-    android:background="@drawable/notification_header_bg"
-    android:clickable="true"
-    android:focusable="true"
-    >
-
-    <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
-        android:layout_width="@dimen/multi_user_switch_width_collapsed"
-        android:layout_height="@dimen/status_bar_header_height"
-        android:layout_alignParentEnd="true"
-        android:background="@drawable/ripple_drawable" >
-        <ImageView android:id="@+id/multi_user_avatar"
-            android:layout_width="@dimen/multi_user_avatar_expanded_size"
-            android:layout_height="@dimen/multi_user_avatar_expanded_size"
-            android:layout_gravity="center"
-            android:scaleType="centerInside"/>
-    </com.android.systemui.statusbar.phone.MultiUserSwitch>
-
-    <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
-        android:id="@+id/settings_button_container"
-        android:layout_width="48dp"
-        android:layout_height="@dimen/status_bar_header_height"
-        android:clipChildren="false"
-        android:clipToPadding="false"
-        android:layout_toStartOf="@id/multi_user_switch">
-
-        <com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button"
-            style="@android:style/Widget.Material.Button.Borderless"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:background="@drawable/ripple_drawable"
-            android:src="@drawable/ic_settings"
-            android:contentDescription="@string/accessibility_desc_settings" />
-        <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:paddingStart="36dp"
-            android:tint="#4DFFFFFF"
-            android:tintMode="src_in"
-            android:visibility="invisible"
-            android:src="@drawable/tuner" />
-
-    </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-
-    <LinearLayout android:id="@+id/system_icons_super_container"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/status_bar_header_height"
-        android:layout_toStartOf="@id/multi_user_switch"
-        android:layout_alignWithParentIfMissing="true"
-        android:layout_marginStart="16dp"
-        android:background="@drawable/ripple_drawable"
-        android:paddingEnd="4dp" >
-        <FrameLayout android:id="@+id/system_icons_container"
-            android:layout_width="wrap_content"
-            android:layout_height="@dimen/status_bar_height"
-            android:layout_gravity="center_vertical"
-            >
-            <include layout="@layout/system_icons" />
-        </FrameLayout>
-        <TextView android:id="@+id/battery_level"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical"
-            android:layout_marginStart="@dimen/header_battery_margin_expanded"
-            android:paddingEnd="@dimen/battery_level_padding_end"
-            android:textColor="#ffffff"
-            android:textSize="@dimen/battery_level_text_size"
-            android:importantForAccessibility="noHideDescendants"/>
-    </LinearLayout>
-
-    <TextView
-        android:id="@+id/header_emergency_calls_only"
-        android:layout_height="@dimen/status_bar_header_height"
-        android:layout_width="wrap_content"
-        android:layout_alignParentStart="true"
-        android:layout_toStartOf="@id/system_icons_super_container"
-        android:paddingStart="16dp"
-        android:paddingEnd="16dp"
-        android:visibility="gone"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
-        android:text="@*android:string/emergency_calls_only"
-        android:singleLine="true"
-        android:gravity="center_vertical" />
-
-    <FrameLayout
-        android:id="@+id/date_group"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/clock_collapsed_bottom_margin"
-        android:layout_alignParentBottom="true">
-        <com.android.systemui.statusbar.policy.DateView android:id="@+id/date_collapsed"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="16dp"
-            android:singleLine="true"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
-            android:layout_below="@id/clock"
-            systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm"
-            />
-
-        <com.android.systemui.statusbar.policy.DateView android:id="@+id/date_expanded"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="16dp"
-            android:singleLine="true"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
-            android:layout_below="@id/clock"
-            systemui:datePattern="eeeeMMMMd"
-            />
-    </FrameLayout>
-
-    <include layout="@layout/split_clock_view"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_above="@id/date_group"
-        android:id="@+id/clock"
-        />
-
-    <com.android.systemui.statusbar.AlphaOptimizedButton android:id="@+id/alarm_status"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:layout_toEndOf="@id/date_group"
-        android:layout_marginBottom="4dp"
-        android:drawablePadding="6dp"
-        android:drawableStart="@drawable/ic_access_alarms_small"
-        android:textColor="#64ffffff"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
-        android:paddingEnd="6dp"
-        android:paddingStart="6dp"
-        android:paddingTop="16dp"
-        android:paddingBottom="16dp"
-        android:background="?android:attr/selectableItemBackground"
-        android:visibility="gone"
-        />
-
-    <include
-        android:id="@+id/qs_detail_header"
-        layout="@layout/qs_detail_header"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        />
-
-    <com.android.systemui.statusbar.AlphaOptimizedImageView
-        android:id="@+id/qs_detail_header_progress"
-        android:src="@drawable/indeterminate_anim"
-        android:alpha="0"
-        android:background="@color/qs_detail_progress_track"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        />
-
-    <TextView
-        android:id="@+id/header_debug_info"
-        android:visibility="invisible"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        android:fontFamily="sans-serif-condensed"
-        android:textSize="11dp"
-        android:textStyle="bold"
-        android:textColor="#00A040"
-        android:padding="2dp"
-        />
-
-</com.android.systemui.statusbar.phone.StatusBarHeaderView>
diff --git a/packages/SystemUI/res/layout/switch_bar.xml b/packages/SystemUI/res/layout/switch_bar.xml
index f98de96..41cdb78 100644
--- a/packages/SystemUI/res/layout/switch_bar.xml
+++ b/packages/SystemUI/res/layout/switch_bar.xml
@@ -22,7 +22,8 @@
     android:paddingStart="16dp"
     android:paddingEnd="16dp"
     android:clickable="true"
-    android:gravity="center">
+    android:gravity="center"
+    android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
 
     <TextView android:id="@+id/switch_text"
         android:layout_height="wrap_content"
@@ -42,7 +43,6 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:background="@null"
-        android:theme="@style/ThemeOverlay.SwitchBar" />
+        android:background="@null" />
 
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
index f30023d..ea26bba 100644
--- a/packages/SystemUI/res/layout/volume_zen_footer.xml
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -78,7 +78,7 @@
         android:paddingStart="15dp"
         android:paddingEnd="15dp"
         android:text="@string/volume_zen_end_now"
-        android:textColor="@color/system_accent_color"
+        android:textColor="?android:attr/colorAccent"
         android:textAppearance="@style/TextAppearance.QS.DetailButton" />
 
 </com.android.systemui.volume.ZenFooter>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 906b867..c0be676 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -40,7 +40,8 @@
         android:layout_marginEnd="16dp"
         android:paddingTop="8dp"
         android:paddingBottom="8dp"
-        android:background="@drawable/zen_introduction_message_background" >
+        android:background="@drawable/zen_introduction_message_background"
+        android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent.Light">
 
         <ImageView
             android:id="@+id/zen_introduction_confirm"
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2f5d97c..68ce2cb 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -72,7 +72,7 @@
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"Probíhá ukládání snímku obrazovky."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky Snímek obrazovky pořízen."</string>
+    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky pořízen"</string>
     <string name="screenshot_saved_text" msgid="2685605830386712477">"Klepnutím zobrazíte snímek obrazovky."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Při ukládání snímku obrazovky došlo k problému."</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index cb51649..f7fd368 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -30,9 +30,10 @@
     <color name="batterymeter_charge_color">#FFFFFFFF</color>
     <color name="batterymeter_bolt_color">#FFFFFFFF</color>
     <color name="qs_batterymeter_frame_color">#FF404040</color>
-    <color name="system_primary_color">#ff263238</color><!-- blue grey 900 -->
+
+    <!-- TODO: use a theme color for this and delete it -->
     <color name="system_secondary_color">#ff37474F</color><!-- blue grey 800 -->
-    <color name="system_accent_color">#ff80CBC4</color><!-- deep teal 200 -->
+
     <color name="system_warning_color">#fff4511e</color><!-- deep orange 600 -->
     <color name="qs_text">#FFFFFFFF</color>
     <color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
@@ -41,7 +42,6 @@
     <color name="qs_detail_button">#FFB0BEC5</color><!-- 100% blue grey 200 -->
     <color name="qs_detail_button_white">#B3FFFFFF</color><!-- 70% white -->
     <color name="qs_detail_transition">#66FFFFFF</color>
-    <color name="qs_detail_progress_track">#99009688</color><!-- 60% deep teal 500 -->
     <color name="data_usage_secondary">#99FFFFFF</color><!-- 60% white -->
     <color name="data_usage_graph_track">#33FFFFFF</color><!-- 20% white -->
     <color name="data_usage_graph_warning">#FFFFFFFF</color>
@@ -99,15 +99,11 @@
     <!-- The color of the ripples on the tinted notifications -->
     <color name="notification_ripple_tinted_color">#30ffffff</color>
 
-    <!-- The color of the circle around the primary user in the user switcher -->
-    <color name="current_user_border_color">@color/system_accent_color</color>
-
     <!-- The color of the gear shown behind a notification -->
     <color name="notification_gear_color">#ff757575</color>
 
     <!-- The "inside" of a notification, reached via longpress -->
     <color name="notification_guts_bg_color">#eeeeee</color>
-    <color name="notification_guts_slider_color">@*android:color/material_deep_teal_500</color>
     <color name="notification_guts_disabled_slider_color">@*android:color/material_grey_300</color>
     <color name="notification_guts_secondary_slider_color">#858383</color>
     <color name="notification_guts_icon_tint">#8a000000</color>
@@ -126,8 +122,6 @@
     <!-- Shadow color for the furthest pixels around the fake shadow for recents. -->
     <color name="fake_shadow_end_color">#03000000</color>
 
-    <color name="screen_pinning_nav_icon_highlight_outer">#4080cbc4</color><!-- 25% deep teal 200 -->
-    <color name="screen_pinning_request_bg">#ff009688</color><!-- deep teal 500 -->
     <color name="screen_pinning_request_window_bg">#80000000</color>
 
     <color name="segmented_buttons_background">#14FFFFFF</color><!-- 8% white -->
@@ -142,14 +136,10 @@
     <color name="light_mode_icon_color_dual_tone_background">#4dffffff</color>
     <color name="light_mode_icon_color_dual_tone_fill">#ffffff</color>
 
-    <color name="zen_introduction_message_background">#ff009688</color><!-- deep teal 500 -->
     <color name="volume_icon_color">#ffffffff</color>
     <color name="volume_settings_icon_color">#7fffffff</color>
     <color name="volume_slider_inactive">#FFB0BEC5</color><!-- blue grey 200 -->
 
-    <color name="fab_ripple">#1fffffff</color><!-- 12% white -->
-    <color name="fab_shape">#ff009688</color><!-- Teal 500 -->
-
     <color name="docked_divider_background">#ff000000</color>
     <color name="docked_divider_handle">#ffffff</color>
     <drawable name="forced_resizable_background">#59000000</drawable>
@@ -167,10 +157,8 @@
     <color name="qs_tile_tint_active">#ffffffff</color>
 
     <color name="switch_bar_background">#ff37474f</color>
-    <color name="switch_accent_color">#ff7fcac3</color>
 
     <!-- Keyboard shortcuts colors -->
-    <color name="ksh_system_group_color">@color/material_deep_teal_500</color>
     <color name="ksh_application_group_color">#fff44336</color>
     <color name="ksh_keyword_color">#d9000000</color>
     <color name="ksh_key_item_color">@color/material_grey_600</color>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index aeb484f..caada1b 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -132,7 +132,7 @@
 
     <style name="TextAppearance.QS.DetailItemSecondary">
         <item name="android:textSize">@dimen/qs_detail_item_secondary_text_size</item>
-        <item name="android:textColor">@color/system_accent_color</item>
+        <item name="android:textColor">?android:attr/colorAccent</item>
     </style>
 
     <style name="TextAppearance.QS.Introduction">
@@ -177,7 +177,7 @@
 
     <style name="TextAppearance.QS.DataUsage.Usage">
         <item name="android:textSize">@dimen/qs_data_usage_usage_text_size</item>
-        <item name="android:textColor">@color/system_accent_color</item>
+        <item name="android:textColor">?android:attr/colorAccent</item>
     </style>
 
     <style name="TextAppearance.QS.DataUsage.Secondary">
@@ -217,19 +217,13 @@
     <style name="Animation.StatusBar">
     </style>
 
-    <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault">
-        <item name="android:colorPrimary">@color/system_primary_color</item>
-        <item name="android:colorControlActivated">@color/system_accent_color</item>
-    </style>
+    <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
 
     <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
         <item name="android:colorAccent">@color/remote_input_accent</item>
     </style>
 
-    <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog">
-        <item name="android:colorPrimary">@color/system_primary_color</item>
-        <item name="android:colorControlActivated">@color/system_accent_color</item>
-    </style>
+    <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog" />
 
     <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
 
@@ -320,12 +314,12 @@
         <item name="android:layout_height">48dp</item>
     </style>
 
-    <style name="TunerSettings" parent="@android:style/Theme.Material.Settings">
+    <style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings">
         <item name="android:windowActionBar">false</item>
         <item name="preferenceTheme">@style/TunerPreferenceTheme</item>
     </style>
 
-    <style name="TunerPreferenceTheme" parent="@android:style/Theme.Material.Settings">
+    <style name="TunerPreferenceTheme" parent="@android:style/Theme.DeviceDefault.Settings">
         <item name="dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
     </style>
 
@@ -341,16 +335,16 @@
     </style>
 
     <style name="TextAppearance.NotificationGuts.Secondary">
-        <item name="android:alpha">.54</item>
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
 
     <style name="TextAppearance.NotificationGuts.Primary">
-        <item name="android:alpha">.87</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textSize">16sp</item>
     </style>
 
     <style name="TextAppearance.NotificationGuts.Radio">
-        <item name="android:alpha">.87</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.NotificationGuts.Button">
@@ -358,11 +352,7 @@
         <item name="android:textAllCaps">true</item>
         <item name="android:fontFamily">sans-serif-medium</item>
         <item name="android:gravity">center</item>
-        <item name="android:textColor">@*android:color/material_deep_teal_500</item>
-    </style>
-
-    <style name="ThemeOverlay.SwitchBar" parent="@android:style/ThemeOverlay">
-        <item name="android:colorAccent">@color/switch_accent_color</item>
+        <item name="android:textColor">?android:attr/colorAccent</item>
     </style>
 
     <style name="edit_theme" parent="@android:style/Theme.Material">
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 85befff..f30baee 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -16,8 +16,10 @@
 
 package com.android.systemui;
 
+import android.app.Notification;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.os.Bundle;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -48,4 +50,12 @@
             mComponents.put(interfaceType, component);
         }
     }
+
+    public static void overrideNotificationAppName(Context context, Notification.Builder n) {
+        final Bundle extras = new Bundle();
+        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
+                context.getString(com.android.internal.R.string.android_system_label));
+
+        n.addExtras(extras);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3bbcf6e..42a9ed5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -926,6 +926,11 @@
             // In this case, send out ACTION_USER_PRESENT here instead of in
             // handleKeyguardDone()
             sendUserPresentBroadcast();
+        } else if (mSystemReady && shouldWaitForProvisioning()) {
+            // Skipping the lockscreen because we're not yet provisioned, but we still need to
+            // notify the StrongAuthTracker that it's now safe to run trust agents, in case the
+            // user sets a credential later.
+            getLockPatternUtils().userPresent(KeyguardUpdateMonitor.getCurrentUser());
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index ea1c9bf..b831235 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -38,6 +38,7 @@
 import android.util.Slog;
 
 import com.android.systemui.R;
+import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
@@ -143,6 +144,7 @@
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
                 .setColor(mContext.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
+        SystemUI.overrideNotificationAppName(mContext, nb);
         final Notification n = nb.build();
         mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
     }
@@ -173,8 +175,8 @@
             attachLowBatterySound(nb);
             mPlaySound = false;
         }
-        final Notification n = nb.build();
-        mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
+        SystemUI.overrideNotificationAppName(mContext, nb);
+        mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, nb.build(), UserHandle.ALL);
     }
 
     private PendingIntent pendingActivity(Intent intent) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
index aff5d2b..5f23a40 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
@@ -24,6 +24,7 @@
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.settingslib.Utils;
 import com.android.systemui.R;
 
 public class DataUsageGraph extends View {
@@ -45,7 +46,7 @@
         super(context, attrs);
         final Resources res = context.getResources();
         mTrackColor = context.getColor(R.color.data_usage_graph_track);
-        mUsageColor = context.getColor(R.color.system_accent_color);
+        mUsageColor = Utils.getColorAccent(context);
         mOverlimitColor = context.getColor(R.color.system_warning_color);
         mWarningColor = context.getColor(R.color.data_usage_graph_warning);
         mMarkerWidth = res.getDimensionPixelSize(R.dimen.data_usage_graph_marker_width);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 109d2c2..ce6aa71 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -72,6 +72,8 @@
     private QSCustomizer mCustomizePanel;
     private Record mDetailRecord;
 
+    private BrightnessMirrorController mBrightnessMirrorController;
+
     public QSPanel(Context context) {
         this(context, null);
     }
@@ -157,7 +159,7 @@
     }
 
     public void setBrightnessMirror(BrightnessMirrorController c) {
-        super.onFinishInflate();
+        mBrightnessMirrorController = c;
         ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider);
         ToggleSlider mirror = (ToggleSlider) c.getMirror().findViewById(R.id.brightness_slider);
         brightnessSlider.setMirror(mirror);
@@ -203,6 +205,11 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         mFooter.onConfigurationChanged();
+
+        if (mBrightnessMirrorController != null) {
+            // Reload the mirror in case it got reinflated but we didn't.
+            setBrightnessMirror(mBrightnessMirrorController);
+        }
     }
 
     public void onCollapse() {
@@ -351,7 +358,6 @@
             }
         };
         r.tileView.init(click, longClick);
-        callback.onStateChanged(r.tile.getState());
         r.tile.refreshState();
         mRecords.add(r);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 974de08..27b079a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -225,7 +225,7 @@
 
     private void handleAddCallback(Callback callback) {
         mCallbacks.add(callback);
-        handleRefreshState(null);
+        callback.onStateChanged(mState);
     }
 
     private void handleRemoveCallback(Callback callback) {
@@ -634,6 +634,18 @@
         }
     }
 
+    public static class AirplaneBooleanState extends BooleanState {
+        public boolean isAirplaneMode;
+
+        @Override
+        public boolean copyTo(State other) {
+            final AirplaneBooleanState o = (AirplaneBooleanState) other;
+            final boolean changed = super.copyTo(other) || o.isAirplaneMode != isAirplaneMode;
+            o.isAirplaneMode = isAirplaneMode;
+            return changed;
+        }
+    }
+
     public static final class SignalState extends BooleanState {
         public boolean connected;
         public boolean activityIn;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index afc987e2..f09275d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -113,6 +113,11 @@
     }
 
     @Override
+    protected void onTileClick(QSTile<?> tile) {
+        tile.secondaryClick();
+    }
+
+    @Override
     public void onTuningChanged(String key, String newValue) {
         // No tunings for you.
         if (key.equals(QS_SHOW_BRIGHTNESS)) {
@@ -130,7 +135,7 @@
                 break;
             }
         }
-        super.setTiles(quickTiles, false);
+        super.setTiles(quickTiles, true);
     }
 
     private final Tunable mNumTiles = new Tunable() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 60c24d0..f060502 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -37,6 +37,7 @@
 import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 import android.widget.TextView;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto;
 import com.android.systemui.R;
@@ -227,6 +228,8 @@
             });
             if (mNeedsFocus) {
                 // Wait for this to get laid out then set its focus.
+                // Ensure that tile gets laid out so we get the callback.
+                holder.mTileView.requestLayout();
                 holder.mTileView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
                     @Override
                     public void onLayoutChange(View v, int left, int top, int right, int bottom,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 23a3ca1..46e7277 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -71,17 +71,12 @@
         super(host);
         mWindowManager = WindowManagerGlobal.getWindowManagerService();
         mComponent = ComponentName.unflattenFromString(action);
+        mTile = new Tile(mComponent);
+        setTileIcon();
         mServiceManager = host.getTileServices().getTileWrapper(this);
         mService = mServiceManager.getTileService();
         mServiceManager.setTileChangeListener(this);
-        mTile = new Tile(mComponent);
         mUser = ActivityManager.getCurrentUser();
-        setTileIcon();
-        try {
-            mService.setQSTile(mTile);
-        } catch (RemoteException e) {
-            // Called through wrapper, won't happen here.
-        }
     }
 
     private void setTileIcon() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index 3830ac5..407453c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -35,16 +35,6 @@
         return mService.asBinder();
     }
 
-    public boolean setQSTile(Tile tile) {
-        try {
-            mService.setQSTile(tile);
-            return true;
-        } catch (Exception e) {
-            Log.d(TAG, "Caught exception from TileService", e);
-            return false;
-        }
-    }
-
     public boolean onTileAdded() {
         try {
             mService.onTileAdded();
@@ -95,16 +85,6 @@
         }
     }
 
-    public boolean setQSService(IQSService service) {
-        try {
-            mService.setQSService(service);
-            return true;
-        } catch (Exception e) {
-            Log.d(TAG, "Caught exception from TileService", e);
-            return false;
-        }
-    }
-
     public boolean onUnlockComplete() {
         try {
             mService.onUnlockComplete();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 87d6307..dd46779 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -71,23 +71,24 @@
     private Set<Integer> mQueuedMessages = new ArraySet<>();
     private QSTileServiceWrapper mWrapper;
     private boolean mListening;
-    private Tile mTile;
     private IBinder mClickBinder;
 
     private int mBindTryCount;
     private boolean mBound;
     @VisibleForTesting
     boolean mReceiverRegistered;
-    private IQSService mService;
     private boolean mUnbindImmediate;
     private TileChangeListener mChangeListener;
     // Return value from bindServiceAsUser, determines whether safe to call unbind.
     private boolean mIsBound;
 
-    public TileLifecycleManager(Handler handler, Context context, Intent intent, UserHandle user) {
+    public TileLifecycleManager(Handler handler, Context context, IQSService service,
+            Tile tile, Intent intent, UserHandle user) {
         mContext = context;
         mHandler = handler;
         mIntent = intent;
+        mIntent.putExtra(TileService.EXTRA_SERVICE, service.asBinder());
+        mIntent.putExtra(TileService.EXTRA_TILE, tile);
         mUser = user;
         if (DEBUG) Log.d(TAG, "Creating " + mIntent + " " + mUser);
     }
@@ -164,14 +165,6 @@
             service.linkToDeath(this, 0);
         } catch (RemoteException e) {
         }
-        if (!wrapper.setQSService(mService)) {
-            handleDeath();
-            return;
-        }
-        if (!wrapper.setQSTile(mTile)) {
-            handleDeath();
-            return;
-        }
         mWrapper = wrapper;
         handlePendingMessages();
     }
@@ -255,15 +248,6 @@
         }
     }
 
-    @Override
-    public void setQSTile(Tile tile) {
-        if (DEBUG) Log.d(TAG, "setQSTile " + tile);
-        mTile = tile;
-        if (mWrapper != null && !mWrapper.setQSTile(tile)) {
-            handleDeath();
-        }
-    }
-
     private boolean checkComponentState() {
         PackageManager pm = mContext.getPackageManager();
         if (!isPackageAvailable(pm) || !isComponentAvailable(pm)) {
@@ -347,14 +331,6 @@
     }
 
     @Override
-    public void setQSService(IQSService service) {
-        mService = service;
-        if (mWrapper == null || !mWrapper.setQSService(service)) {
-            handleDeath();
-        }
-    }
-
-    @Override
     public void onTileAdded() {
         if (DEBUG) Log.d(TAG, "onTileAdded");
         if (mWrapper == null || !mWrapper.onTileAdded()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index ce9bbf4..3d030f9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -27,6 +27,7 @@
 import android.os.Handler;
 import android.os.UserHandle;
 import android.service.quicksettings.IQSTileService;
+import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
 import android.support.annotation.VisibleForTesting;
 import android.util.Log;
@@ -68,9 +69,10 @@
     // This defaults to true to ensure tiles start out unavailable.
     private boolean mPendingBind = true;
 
-    TileServiceManager(TileServices tileServices, Handler handler, ComponentName component) {
+    TileServiceManager(TileServices tileServices, Handler handler, ComponentName component,
+            Tile tile) {
         this(tileServices, handler, new TileLifecycleManager(handler,
-                tileServices.getContext(), new Intent().setComponent(component),
+                tileServices.getContext(), tileServices, tile, new Intent().setComponent(component),
                 new UserHandle(ActivityManager.getCurrentUser())));
     }
 
@@ -80,7 +82,6 @@
         mServices = tileServices;
         mHandler = handler;
         mStateManager = tileLifecycleManager;
-        mStateManager.setQSService(tileServices);
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 2ab6b5f..f84c5d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -78,7 +78,7 @@
 
     public TileServiceManager getTileWrapper(CustomTile tile) {
         ComponentName component = tile.getComponent();
-        TileServiceManager service = onCreateTileService(component);
+        TileServiceManager service = onCreateTileService(component, tile.getQsTile());
         synchronized (mServices) {
             mServices.put(tile, service);
             mTiles.put(component, tile);
@@ -86,8 +86,8 @@
         return service;
     }
 
-    protected TileServiceManager onCreateTileService(ComponentName component) {
-        return new TileServiceManager(this, mHandler, component);
+    protected TileServiceManager onCreateTileService(ComponentName component, Tile tile) {
+        return new TileServiceManager(this, mHandler, component, tile);
     }
 
     public void freeService(CustomTile tile, TileServiceManager service) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 18191cf..0de5105 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -95,14 +95,6 @@
     }
 
     @Override
-    protected void handleSecondaryClick() {
-        boolean dataEnabled = mDataController.isMobileDataSupported()
-                && mDataController.isMobileDataEnabled();
-        MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, !dataEnabled);
-        mDataController.setMobileDataEnabled(!dataEnabled);
-    }
-
-    @Override
     public CharSequence getTileLabel() {
         return mContext.getString(R.string.quick_settings_cellular_detail_title);
     }
@@ -152,8 +144,8 @@
         }
         state.contentDescription = state.contentDescription + "," + r.getString(
                 R.string.accessibility_quick_settings_open_settings, getTileLabel());
-        state.expandedAccessibilityClassName = Button.class.getName();
-        state.minimalAccessibilityClassName = Switch.class.getName();
+        state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
+                = Button.class.getName();
         state.value = mDataController.isMobileDataSupported()
                 && mDataController.isMobileDataEnabled();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index bad4e79..e0049b5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -24,6 +24,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.settingslib.Utils;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
@@ -64,7 +65,7 @@
         final Resources res = mContext.getResources();
         final int titleId;
         final long bytes;
-        int usageColor = R.color.system_accent_color;
+        int usageColor = 0;
         final String top;
         String bottom = null;
         if (info.usageLevel < info.warningLevel || info.limitLevel <= 0) {
@@ -92,6 +93,10 @@
             usageColor = R.color.system_warning_color;
         }
 
+        if (usageColor == 0) {
+            usageColor = Utils.getColorAccent(mContext);
+        }
+
         final TextView title = (TextView) findViewById(android.R.id.title);
         title.setText(titleId);
         final TextView usage = (TextView) findViewById(R.id.usage_text);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 1c134c1..d3434e5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -36,15 +36,16 @@
 import com.android.systemui.statusbar.policy.HotspotController;
 
 /** Quick settings tile: Hotspot **/
-public class HotspotTile extends QSTile<QSTile.BooleanState> {
+public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> {
     private final AnimationIcon mEnable =
             new AnimationIcon(R.drawable.ic_hotspot_enable_animation,
                     R.drawable.ic_hotspot_disable);
     private final AnimationIcon mDisable =
             new AnimationIcon(R.drawable.ic_hotspot_disable_animation,
                     R.drawable.ic_hotspot_enable);
-    private final Icon mUnavailable =
-            ResourceIcon.get(R.drawable.ic_hotspot_unavailable);
+    private final Icon mDisableNoAnimation = ResourceIcon.get(R.drawable.ic_hotspot_enable);
+    private final Icon mUnavailable = ResourceIcon.get(R.drawable.ic_hotspot_unavailable);
+
     private final HotspotController mController;
     private final Callback mCallback = new Callback();
     private final GlobalSetting mAirplaneMode;
@@ -72,8 +73,8 @@
     }
 
     @Override
-    public BooleanState newTileState() {
-        return new BooleanState();
+    public AirplaneBooleanState newTileState() {
+        return new AirplaneBooleanState();
     }
 
     @Override
@@ -84,10 +85,8 @@
             mController.addCallback(mCallback);
             final IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-            mContext.registerReceiver(mReceiver, filter);
         } else {
             mController.removeCallback(mCallback);
-            mContext.unregisterReceiver(mReceiver);
         }
         mAirplaneMode.setListening(listening);
     }
@@ -113,7 +112,7 @@
     }
 
     @Override
-    protected void handleUpdateState(BooleanState state, Object arg) {
+    protected void handleUpdateState(AirplaneBooleanState state, Object arg) {
         state.label = mContext.getString(R.string.quick_settings_hotspot_label);
 
         checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
@@ -123,12 +122,16 @@
             state.value = mController.isHotspotEnabled();
         }
         state.icon = state.value ? mEnable : mDisable;
-        if (mAirplaneMode.getValue() != 0) {
+        boolean wasAirplane = state.isAirplaneMode;
+        state.isAirplaneMode = mAirplaneMode.getValue() != 0;
+        if (state.isAirplaneMode) {
             final int disabledColor = mHost.getContext().getColor(R.color.qs_tile_tint_unavailable);
             state.label = new SpannableStringBuilder().append(state.label,
                     new ForegroundColorSpan(disabledColor),
                     SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
             state.icon = mUnavailable;
+        } else if (wasAirplane) {
+            state.icon = mDisableNoAnimation;
         }
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
                 = Switch.class.getName();
@@ -155,13 +158,4 @@
             refreshState(enabled);
         }
     };
-
-    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
-                refreshState();
-            }
-        }
-    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
index 913da18..3921a20 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
@@ -30,6 +30,7 @@
 import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
+import com.android.systemui.recents.misc.ForegroundThread;
 
 /**
  * An implementation of the system user's Recents interface to be called remotely by secondary
@@ -78,12 +79,16 @@
 
     @Override
     public void updateRecentsVisibility(boolean visible) {
-        mImpl.onVisibilityChanged(mContext, visible);
+        ForegroundThread.getHandler().post(() -> {
+            mImpl.onVisibilityChanged(mContext, visible);
+        });
     }
 
     @Override
     public void startScreenPinning(int taskId) {
-        mImpl.onStartScreenPinning(mContext, taskId);
+        ForegroundThread.getHandler().post(() -> {
+            mImpl.onStartScreenPinning(mContext, taskId);
+        });
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 992b13f..b961055 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -72,7 +72,12 @@
     }
 
     public void showPrompt(int taskId, boolean allowCancel) {
-        clearPrompt();
+        try {
+            clearPrompt();
+        } catch (IllegalArgumentException e) {
+            // If the call to show the prompt fails due to the request window not already being
+            // attached, then just ignore the error since we will be re-adding it below.
+        }
 
         this.taskId = taskId;
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e6cbbea..d789477 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -60,6 +60,7 @@
 import android.widget.ImageView;
 
 import com.android.systemui.R;
+import com.android.systemui.SystemUI;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -165,11 +166,6 @@
         c.drawColor(overlayColor);
         c.setBitmap(null);
 
-        // swap "System UI" out for "Android System"
-        final Bundle extras = new Bundle();
-        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
-                context.getString(com.android.internal.R.string.android_system_label));
-
         // Show the intermediate notification
         mTickerAddSpace = !mTickerAddSpace;
         mNotificationManager = nManager;
@@ -187,9 +183,9 @@
                 .setCategory(Notification.CATEGORY_PROGRESS)
                 .setWhen(now)
                 .setShowWhen(true)
-                .addExtras(extras)
                 .setColor(r.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
+        SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder);
 
         mNotificationBuilder = new Notification.Builder(context)
             .setTicker(r.getString(R.string.screenshot_saving_ticker)
@@ -199,11 +195,11 @@
             .setSmallIcon(R.drawable.stat_notify_image)
             .setWhen(now)
             .setShowWhen(true)
-            .addExtras(extras)
             .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color))
             .setStyle(mNotificationStyle)
             .setPublicVersion(mPublicNotificationBuilder.build());
         mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
+        SystemUI.overrideNotificationAppName(context, mNotificationBuilder);
 
         mNotificationManager.notify(R.id.notification_screenshot, mNotificationBuilder.build());
 
@@ -864,6 +860,7 @@
             .setAutoCancel(true)
             .setColor(context.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
+        SystemUI.overrideNotificationAppName(context, b);
 
         Notification n = new Notification.BigTextStyle(b)
                 .bigText(errorMsg)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 91889d3..7bc4100 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -134,6 +134,7 @@
             = SystemProperties.getBoolean("debug.child_notifs", true);
     public static final boolean FORCE_REMOTE_INPUT_HISTORY =
             SystemProperties.getBoolean("debug.force_remoteinput_history", false);
+    private static boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
 
     protected static final int MSG_SHOW_RECENT_APPS = 1019;
     protected static final int MSG_HIDE_RECENT_APPS = 1020;
@@ -704,10 +705,13 @@
                 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
                 mSettingsObserver,
                 UserHandle.USER_ALL);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT), false,
-                mSettingsObserver,
-                UserHandle.USER_ALL);
+        if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
+                    false,
+                    mSettingsObserver,
+                    UserHandle.USER_ALL);
+        }
 
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
@@ -840,7 +844,6 @@
                     new Intent(BANNER_ACTION_SETUP).setPackage(packageName),
                     PendingIntent.FLAG_CANCEL_CURRENT);
 
-            final Resources res = mContext.getResources();
             final int colorRes = com.android.internal.R.color.system_notification_accent_color;
             Notification.Builder note = new Notification.Builder(mContext)
                     .setSmallIcon(R.drawable.ic_android)
@@ -856,6 +859,7 @@
                     .addAction(R.drawable.ic_settings,
                             mContext.getString(R.string.hidden_notifications_setup),
                             setupIntent);
+            overrideNotificationAppName(mContext, note);
 
             NotificationManager noMan =
                     (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -1096,6 +1100,7 @@
             settingsButton.setVisibility(View.GONE);
         }
 
+        guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
         row.findViewById(R.id.done).setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -1116,7 +1121,6 @@
                 }
             }
         });
-        guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
     }
 
     private void saveImportanceCloseControls(StatusBarNotification sbn,
@@ -2304,16 +2308,20 @@
         final boolean allowedByDpm = (dpmFlags
                 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
 
-        final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
-                0,
-                mCurrentUserId) != 0;
-        final boolean remoteInputDpm = (dpmFlags
-                & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
-
-
         setShowLockscreenNotifications(show && allowedByDpm);
-        setLockScreenAllowRemoteInput(remoteInput && remoteInputDpm);
+
+        if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
+            final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
+                    0,
+                    mCurrentUserId) != 0;
+            final boolean remoteInputDpm =
+                    (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
+
+            setLockScreenAllowRemoteInput(remoteInput && remoteInputDpm);
+        } else {
+            setLockScreenAllowRemoteInput(false);
+        }
     }
 
     protected abstract void setAreThereNotifications();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 28a6851..f09eae8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -27,6 +27,7 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Build;
+import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
@@ -37,11 +38,11 @@
 import android.view.View;
 import android.view.ViewStub;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Chronometer;
 import android.widget.ImageView;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.R;
@@ -50,6 +51,7 @@
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.StackScrollState;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 import com.android.systemui.statusbar.stack.StackViewState;
@@ -140,15 +142,17 @@
         @Override
         public void onClick(View v) {
             if (!mShowingPublic && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
+                mGroupExpansionChanging = true;
                 final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
                 boolean nowExpanded = mGroupManager.toggleGroupExpansion(mStatusBarNotification);
                 mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
-                mGroupExpansionChanging = true;
-                updateBackgroundForGroupState();
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
                         nowExpanded);
                 logExpansionEvent(true /* userAction */, wasExpanded);
             } else {
+                if (v.isAccessibilityFocused()) {
+                    mPrivateLayout.setFocusOnVisibilityChange();
+                }
                 boolean nowExpanded;
                 if (isPinned()) {
                     nowExpanded = !mExpandedWhenPinned;
@@ -181,6 +185,10 @@
                 }
     };
     private OnClickListener mOnClickListener;
+    private boolean mHeadsupDisappearRunning;
+    private View mChildAfterViewWhenDismissed;
+    private View mGroupParentWhenDismissed;
+    private boolean mRefocusOnDismiss;
 
     public boolean isGroupExpansionChanging() {
         if (isChildInGroup()) {
@@ -717,8 +725,19 @@
         }
     }
 
-    public void setDismissed(boolean dismissed) {
+    public void setDismissed(boolean dismissed, boolean fromAccessibility) {
         mDismissed = dismissed;
+        mGroupParentWhenDismissed = mNotificationParent;
+        mRefocusOnDismiss = fromAccessibility;
+        mChildAfterViewWhenDismissed = null;
+        if (isChildInGroup()) {
+            List<ExpandableNotificationRow> notificationChildren =
+                    mNotificationParent.getNotificationChildren();
+            int i = notificationChildren.indexOf(this);
+            if (i != -1 && i < notificationChildren.size() - 1) {
+                mChildAfterViewWhenDismissed = notificationChildren.get(i + 1);
+            }
+        }
     }
 
     public boolean isDismissed() {
@@ -741,15 +760,25 @@
         mRemoved = true;
 
         mPrivateLayout.setRemoved();
-        if (mChildrenContainer != null) {
-            mChildrenContainer.setRemoved();
-        }
     }
 
     public NotificationChildrenContainer getChildrenContainer() {
         return mChildrenContainer;
     }
 
+    public void setHeadsupDisappearRunning(boolean running) {
+        mHeadsupDisappearRunning = running;
+        mPrivateLayout.setHeadsupDisappearRunning(running);
+    }
+
+    public View getChildAfterViewWhenDismissed() {
+        return mChildAfterViewWhenDismissed;
+    }
+
+    public View getGroupParentWhenDismissed() {
+        return mGroupParentWhenDismissed;
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -1147,8 +1176,8 @@
             return getMinHeight();
         } else if (mIsSummaryWithChildren && !mOnKeyguard) {
             return mChildrenContainer.getIntrinsicHeight();
-        } else if (mIsHeadsUp) {
-            if (isPinned()) {
+        } else if (mIsHeadsUp || mHeadsupDisappearRunning) {
+            if (isPinned() || mHeadsupDisappearRunning) {
                 return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
             } else if (isExpanded()) {
                 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
@@ -1274,6 +1303,10 @@
         if (!animated) {
             mPublicLayout.animate().cancel();
             mPrivateLayout.animate().cancel();
+            if (mChildrenContainer != null) {
+                mChildrenContainer.animate().cancel();
+                mChildrenContainer.setAlpha(1f);
+            }
             mPublicLayout.setAlpha(1f);
             mPrivateLayout.setAlpha(1f);
             mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
@@ -1326,8 +1359,11 @@
 
     private void updateClearability() {
         // public versions cannot be dismissed
-        mVetoButton.setVisibility(isClearable() && (!mShowingPublic
-                || !mSensitiveHiddenInGeneral) ? View.VISIBLE : View.GONE);
+        mVetoButton.setVisibility(canViewBeDismissed() ? View.VISIBLE : View.GONE);
+    }
+
+    private boolean canViewBeDismissed() {
+        return isClearable() && (!mShowingPublic || !mSensitiveHiddenInGeneral);
     }
 
     public void makeActionsVisibile() {
@@ -1343,6 +1379,7 @@
         if (mChildrenContainer != null) {
             mChildrenContainer.setChildrenExpanded(expanded);
         }
+        updateBackgroundForGroupState();
         updateClickAndFocus();
     }
 
@@ -1568,6 +1605,32 @@
         }
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfoInternal(info);
+        if (canViewBeDismissed()) {
+            info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_DISMISS);
+        }
+    }
+
+    @Override
+    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+        if (super.performAccessibilityActionInternal(action, arguments)) {
+            return true;
+        }
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_DISMISS:
+                NotificationStackScrollLayout.performDismiss(this, mGroupManager,
+                        true /* fromAccessibility */);
+                return true;
+        }
+        return false;
+    }
+
+    public boolean shouldRefocusOnDismiss() {
+        return mRefocusOnDismiss || isAccessibilityFocused();
+    }
+
     public interface OnExpandClickListener {
         void onExpandClicked(NotificationData.Entry clickedEntry, boolean nowExpanded);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 9211562..016e1f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.AlertDialog;
 import android.app.AppGlobals;
 import android.app.Dialog;
@@ -45,15 +47,18 @@
 import android.view.KeyboardShortcutInfo;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.AccessibilityDelegate;
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import com.android.internal.app.AssistUtils;
+import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 
@@ -63,6 +68,7 @@
 import java.util.List;
 
 import static android.content.Context.LAYOUT_INFLATER_SERVICE;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
 
 /**
@@ -112,7 +118,7 @@
     private KeyCharacterMap mKeyCharacterMap;
 
     private KeyboardShortcuts(Context context) {
-        this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
+        this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault_Light);
         this.mPackageManager = AppGlobals.getPackageManager();
         loadResources(context);
     }
@@ -582,7 +588,7 @@
                     R.layout.keyboard_shortcuts_category_title, keyboardShortcutsLayout, false);
             categoryTitle.setText(group.getLabel());
             categoryTitle.setTextColor(group.isSystemGroup()
-                    ? mContext.getColor(R.color.ksh_system_group_color)
+                    ? Utils.getColorAccent(mContext)
                     : mContext.getColor(R.color.ksh_application_group_color));
             keyboardShortcutsLayout.addView(categoryTitle);
 
@@ -591,7 +597,7 @@
             final int itemsSize = group.getItems().size();
             for (int j = 0; j < itemsSize; j++) {
                 KeyboardShortcutInfo info = group.getItems().get(j);
-                List<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info);
+                List<StringDrawableContainer> shortcutKeys = getHumanReadableShortcutKeys(info);
                 if (shortcutKeys == null) {
                     // Ignore shortcuts we can't display keys for.
                     Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping.");
@@ -621,25 +627,33 @@
                         .findViewById(R.id.keyboard_shortcuts_item_container);
                 final int shortcutKeysSize = shortcutKeys.size();
                 for (int k = 0; k < shortcutKeysSize; k++) {
-                    StringOrDrawable shortcutRepresentation = shortcutKeys.get(k);
-                    if (shortcutRepresentation.drawable != null) {
+                    StringDrawableContainer shortcutRepresentation = shortcutKeys.get(k);
+                    if (shortcutRepresentation.mDrawable != null) {
                         ImageView shortcutKeyIconView = (ImageView) inflater.inflate(
                                 R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer,
                                 false);
                         Bitmap bitmap = Bitmap.createBitmap(shortcutKeyIconItemHeightWidth,
                                 shortcutKeyIconItemHeightWidth, Bitmap.Config.ARGB_8888);
                         Canvas canvas = new Canvas(bitmap);
-                        shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(),
+                        shortcutRepresentation.mDrawable.setBounds(0, 0, canvas.getWidth(),
                                 canvas.getHeight());
-                        shortcutRepresentation.drawable.draw(canvas);
+                        shortcutRepresentation.mDrawable.draw(canvas);
                         shortcutKeyIconView.setImageBitmap(bitmap);
+                        shortcutKeyIconView.setImportantForAccessibility(
+                                IMPORTANT_FOR_ACCESSIBILITY_YES);
+                        shortcutKeyIconView.setAccessibilityDelegate(
+                                new ShortcutKeyAccessibilityDelegate(
+                                        shortcutRepresentation.mString));
                         shortcutItemsContainer.addView(shortcutKeyIconView);
-                    } else if (shortcutRepresentation.string != null) {
+                    } else if (shortcutRepresentation.mString != null) {
                         TextView shortcutKeyTextView = (TextView) inflater.inflate(
                                 R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer,
                                 false);
                         shortcutKeyTextView.setMinimumWidth(shortcutKeyTextItemMinWidth);
-                        shortcutKeyTextView.setText(shortcutRepresentation.string);
+                        shortcutKeyTextView.setText(shortcutRepresentation.mString);
+                        shortcutKeyTextView.setAccessibilityDelegate(
+                                new ShortcutKeyAccessibilityDelegate(
+                                        shortcutRepresentation.mString));
                         shortcutItemsContainer.addView(shortcutKeyTextView);
                     }
                 }
@@ -655,19 +669,20 @@
         }
     }
 
-    private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
-        List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info);
+    private List<StringDrawableContainer> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+        List<StringDrawableContainer> shortcutKeys = getHumanReadableModifiers(info);
         if (shortcutKeys == null) {
             return null;
         }
-        String displayLabelString = null;
-        Drawable displayLabelDrawable = null;
+        String shortcutKeyString = null;
+        Drawable shortcutKeyDrawable = null;
         if (info.getBaseCharacter() > Character.MIN_VALUE) {
-            displayLabelString = String.valueOf(info.getBaseCharacter());
+            shortcutKeyString = String.valueOf(info.getBaseCharacter());
         } else if (mSpecialCharacterDrawables.get(info.getKeycode()) != null) {
-            displayLabelDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+            shortcutKeyDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+            shortcutKeyString = mSpecialCharacterNames.get(info.getKeycode());
         } else if (mSpecialCharacterNames.get(info.getKeycode()) != null) {
-            displayLabelString = mSpecialCharacterNames.get(info.getKeycode());
+            shortcutKeyString = mSpecialCharacterNames.get(info.getKeycode());
         } else {
             // Special case for shortcuts with no base key or keycode.
             if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) {
@@ -675,22 +690,23 @@
             }
             char displayLabel = mKeyCharacterMap.getDisplayLabel(info.getKeycode());
             if (displayLabel != 0) {
-                displayLabelString = String.valueOf(displayLabel);
+                shortcutKeyString = String.valueOf(displayLabel);
             } else {
                 return null;
             }
         }
 
-        if (displayLabelDrawable != null) {
-            shortcutKeys.add(new StringOrDrawable(displayLabelDrawable));
-        } else if (displayLabelString != null) {
-            shortcutKeys.add(new StringOrDrawable(displayLabelString.toUpperCase()));
+        if (shortcutKeyString != null) {
+            shortcutKeys.add(new StringDrawableContainer(shortcutKeyString, shortcutKeyDrawable));
+        } else {
+            Log.w(TAG, "Keyboard Shortcut does not have a text representation, skipping.");
         }
+
         return shortcutKeys;
     }
 
-    private List<StringOrDrawable> getHumanReadableModifiers(KeyboardShortcutInfo info) {
-        final List<StringOrDrawable> shortcutKeys = new ArrayList<>();
+    private List<StringDrawableContainer> getHumanReadableModifiers(KeyboardShortcutInfo info) {
+        final List<StringDrawableContainer> shortcutKeys = new ArrayList<>();
         int modifiers = info.getModifiers();
         if (modifiers == 0) {
             return shortcutKeys;
@@ -698,13 +714,9 @@
         for(int i = 0; i < mModifierNames.size(); ++i) {
             final int supportedModifier = mModifierNames.keyAt(i);
             if ((modifiers & supportedModifier) != 0) {
-                if (mModifierDrawables.get(supportedModifier) != null) {
-                    shortcutKeys.add(new StringOrDrawable(
-                            mModifierDrawables.get(supportedModifier)));
-                } else {
-                    shortcutKeys.add(new StringOrDrawable(
-                            mModifierNames.get(supportedModifier).toUpperCase()));
-                }
+                shortcutKeys.add(new StringDrawableContainer(
+                        mModifierNames.get(supportedModifier),
+                        mModifierDrawables.get(supportedModifier)));
                 modifiers &= ~supportedModifier;
             }
         }
@@ -715,16 +727,31 @@
         return shortcutKeys;
     }
 
-    private static final class StringOrDrawable {
-        public String string;
-        public Drawable drawable;
+    private final class ShortcutKeyAccessibilityDelegate extends AccessibilityDelegate {
+        private String mContentDescription;
 
-        public StringOrDrawable(String string) {
-            this.string = string;
+        ShortcutKeyAccessibilityDelegate(String contentDescription) {
+            mContentDescription = contentDescription;
         }
 
-        public StringOrDrawable(Drawable drawable) {
-            this.drawable = drawable;
+        @Override
+        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+            super.onInitializeAccessibilityNodeInfo(host, info);
+            if (mContentDescription != null) {
+                info.setContentDescription(mContentDescription.toLowerCase());
+            }
+        }
+    }
+
+    private static final class StringDrawableContainer {
+        @NonNull
+        public String mString;
+        @Nullable
+        public Drawable mDrawable;
+
+        StringDrawableContainer(String string, Drawable drawable) {
+            mString = string;
+            mDrawable = drawable;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index a11263a..9fd09d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -29,6 +29,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 
 import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.R;
@@ -117,6 +118,8 @@
     private PendingIntent mPreviousHeadsUpRemoteInputIntent;
 
     private int mContentHeightAtAnimationStart = UNDEFINED;
+    private boolean mFocusOnVisibilityChange;
+    private boolean mHeadsupDisappearRunning;
 
 
     public NotificationContentView(Context context, AttributeSet attrs) {
@@ -395,6 +398,19 @@
         }
     }
 
+    private void focusExpandButtonIfNecessary() {
+        if (mFocusOnVisibilityChange) {
+            NotificationHeaderView header = getVisibleNotificationHeader();
+            if (header != null) {
+                ImageView expandButton = header.getExpandButton();
+                if (expandButton != null) {
+                    expandButton.requestAccessibilityFocus();
+                }
+            }
+            mFocusOnVisibilityChange = false;
+        }
+    }
+
     public void setContentHeight(int contentHeight) {
         mContentHeight = Math.max(Math.min(contentHeight, getHeight()), getMinHeight());
         selectLayout(mAnimate /* animate */, false /* force */);
@@ -431,7 +447,8 @@
             boolean transitioningBetweenHunAndExpanded =
                     isTransitioningFromTo(VISIBLE_TYPE_HEADSUP, VISIBLE_TYPE_EXPANDED) ||
                     isTransitioningFromTo(VISIBLE_TYPE_EXPANDED, VISIBLE_TYPE_HEADSUP);
-            boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED) && mIsHeadsUp;
+            boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED)
+                    && (mIsHeadsUp || mHeadsupDisappearRunning);
             if (transitioningBetweenHunAndExpanded || pinned) {
                 return Math.min(mHeadsUpChild.getHeight(), mExpandedChild.getHeight());
             }
@@ -584,7 +601,8 @@
             updateContentTransformation();
         } else {
             int visibleType = calculateVisibleType();
-            if (visibleType != mVisibleType || force) {
+            boolean changedType = visibleType != mVisibleType;
+            if (changedType || force) {
                 View visibleView = getViewForVisibleType(visibleType);
                 if (visibleView != null) {
                     visibleView.setVisibility(VISIBLE);
@@ -604,6 +622,9 @@
                     updateViewVisibilities(visibleType);
                 }
                 mVisibleType = visibleType;
+                if (changedType) {
+                    focusExpandButtonIfNecessary();
+                }
                 updateBackgroundColor(animate);
             }
         }
@@ -811,7 +832,7 @@
             return VISIBLE_TYPE_SINGLELINE;
         }
 
-        if (mIsHeadsUp && mHeadsUpChild != null) {
+        if ((mIsHeadsUp || mHeadsupDisappearRunning) && mHeadsUpChild != null) {
             if (viewHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
                 return VISIBLE_TYPE_HEADSUP;
             } else {
@@ -1133,4 +1154,13 @@
             mContentHeightAtAnimationStart = UNDEFINED;
         }
     }
+
+    public void setHeadsupDisappearRunning(boolean headsupDisappearRunning) {
+        mHeadsupDisappearRunning = headsupDisappearRunning;
+        selectLayout(false /* animate */, true /* force */);
+    }
+
+    public void setFocusOnVisibilityChange() {
+        mFocusOnVisibilityChange = true;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 5bbca15..f0195d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -264,7 +264,7 @@
     }
 
     private void bindSlider(final View importanceSlider, final boolean systemApp) {
-        mActiveSliderTint = loadColorStateList(R.color.notification_guts_slider_color);
+        mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
         mInactiveSliderTint = loadColorStateList(R.color.notification_guts_disabled_slider_color);
 
         mImportanceSummary = ((TextView) importanceSlider.findViewById(R.id.summary));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index a2ad46a..74caa53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -237,6 +237,14 @@
         super.onDetachedFromWindow();
     }
 
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+
+        // Re-run all checks against the tint area for all icons
+        applyIconTint();
+    }
+
     // From SecurityController.
     @Override
     public void onStateChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 9ecff18d..204ab7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -213,18 +213,18 @@
         return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary();
     }
 
-    public boolean isOnlyChildInSuppressedGroup(StatusBarNotification sbn) {
-        return isGroupSuppressed(sbn.getGroupKey())
-                && isOnlyChild(sbn);
-    }
-
     private boolean isOnlyChild(StatusBarNotification sbn) {
         return !sbn.getNotification().isGroupSummary()
                 && getTotalNumberOfChildren(sbn) == 1;
     }
 
     public boolean isOnlyChildInGroup(StatusBarNotification sbn) {
-        return isOnlyChild(sbn) && getLogicalGroupSummary(sbn) != null;
+        if (!isOnlyChild(sbn)) {
+            return false;
+        }
+        ExpandableNotificationRow logicalGroupSummary = getLogicalGroupSummary(sbn);
+        return logicalGroupSummary != null
+                && !logicalGroupSummary.getStatusBarNotification().equals(sbn);
     }
 
     private int getTotalNumberOfChildren(StatusBarNotification sbn) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index ae1e5d0..011ec22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -30,6 +30,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
+import android.service.quicksettings.Tile;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
@@ -403,10 +404,11 @@
             String tileSpec = previousTiles.get(i);
             if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
             if (!newTiles.contains(tileSpec)) {
-                Intent intent = new Intent().setComponent(
-                        CustomTile.getComponentFromSpec(tileSpec));
+                ComponentName component = CustomTile.getComponentFromSpec(tileSpec);
+                Intent intent = new Intent().setComponent(component);
                 TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
-                        mContext, intent, new UserHandle(ActivityManager.getCurrentUser()));
+                        mContext, mServices, new Tile(component), intent,
+                        new UserHandle(ActivityManager.getCurrentUser()));
                 lifecycleManager.onStopListening();
                 lifecycleManager.onTileRemoved();
                 lifecycleManager.flushMessagesAndUnbind();
@@ -416,10 +418,11 @@
             String tileSpec = newTiles.get(i);
             if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
             if (!previousTiles.contains(tileSpec)) {
-                Intent intent = new Intent().setComponent(
-                        CustomTile.getComponentFromSpec(tileSpec));
+                ComponentName component = CustomTile.getComponentFromSpec(tileSpec);
+                Intent intent = new Intent().setComponent(component);
                 TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
-                        mContext, intent, new UserHandle(ActivityManager.getCurrentUser()));
+                        mContext, mServices, new Tile(component), intent,
+                        new UserHandle(ActivityManager.getCurrentUser()));
                 lifecycleManager.onTileAdded();
                 lifecycleManager.flushMessagesAndUnbind();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
deleted file mode 100644
index 72eafd8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ /dev/null
@@ -1,842 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Outline;
-import android.graphics.Rect;
-import android.graphics.drawable.Animatable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
-import android.util.AttributeSet;
-import android.util.MathUtils;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewOutlineProvider;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.Switch;
-import android.widget.TextView;
-import android.widget.Toast;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.systemui.BatteryMeterView;
-import com.android.systemui.FontSizeUtils;
-import com.android.systemui.R;
-import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSPanel.Callback;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.QSTile.DetailAdapter;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.tuner.TunerService;
-
-import java.text.NumberFormat;
-
-/**
- * The view to manage the header area in the expanded status bar.
- */
-public class StatusBarHeaderView extends BaseStatusBarHeader implements View.OnClickListener,
-        BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback,
-        EmergencyListener {
-
-    private boolean mExpanded;
-    private boolean mListening;
-
-    private ViewGroup mSystemIconsContainer;
-    private View mSystemIconsSuperContainer;
-    private View mDateGroup;
-    private View mClock;
-    private TextView mTime;
-    private TextView mAmPm;
-    private MultiUserSwitch mMultiUserSwitch;
-    private ImageView mMultiUserAvatar;
-    private TextView mDateCollapsed;
-    private TextView mDateExpanded;
-    private LinearLayout mSystemIcons;
-    private View mSignalCluster;
-    private SettingsButton mSettingsButton;
-    private View mSettingsContainer;
-    private View mQsDetailHeader;
-    private TextView mQsDetailHeaderTitle;
-    private Switch mQsDetailHeaderSwitch;
-    private ImageView mQsDetailHeaderProgress;
-    private TextView mEmergencyCallsOnly;
-    private TextView mBatteryLevel;
-    private TextView mAlarmStatus;
-
-    private boolean mShowEmergencyCallsOnly;
-    private boolean mAlarmShowing;
-    private AlarmManager.AlarmClockInfo mNextAlarm;
-
-    private int mCollapsedHeight;
-    private int mExpandedHeight;
-
-    private int mMultiUserExpandedMargin;
-    private int mMultiUserCollapsedMargin;
-
-    private int mClockMarginBottomExpanded;
-    private int mClockMarginBottomCollapsed;
-    private int mMultiUserSwitchWidthCollapsed;
-    private int mMultiUserSwitchWidthExpanded;
-
-    private int mClockCollapsedSize;
-    private int mClockExpandedSize;
-
-    /**
-     * In collapsed QS, the clock and avatar are scaled down a bit post-layout to allow for a nice
-     * transition. These values determine that factor.
-     */
-    private float mClockCollapsedScaleFactor;
-    private float mAvatarCollapsedScaleFactor;
-
-    private ActivityStarter mActivityStarter;
-    private BatteryController mBatteryController;
-    private NextAlarmController mNextAlarmController;
-    private QSPanel mQSPanel;
-
-    private final Rect mClipBounds = new Rect();
-
-    private boolean mCaptureValues;
-    private boolean mSignalClusterDetached;
-    private final LayoutValues mCollapsedValues = new LayoutValues();
-    private final LayoutValues mExpandedValues = new LayoutValues();
-    private final LayoutValues mCurrentValues = new LayoutValues();
-
-    private float mCurrentT;
-    private boolean mShowingDetail;
-    private boolean mDetailTransitioning;
-
-    private boolean mAllowExpand = true;
-
-    public StatusBarHeaderView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mSystemIconsSuperContainer = findViewById(R.id.system_icons_super_container);
-        mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container);
-        mSystemIconsSuperContainer.setOnClickListener(this);
-        mDateGroup = findViewById(R.id.date_group);
-        mClock = findViewById(R.id.clock);
-        mTime = (TextView) findViewById(R.id.time_view);
-        mAmPm = (TextView) findViewById(R.id.am_pm_view);
-        mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
-        mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
-        mDateCollapsed = (TextView) findViewById(R.id.date_collapsed);
-        mDateExpanded = (TextView) findViewById(R.id.date_expanded);
-        mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
-        mSettingsContainer = findViewById(R.id.settings_button_container);
-        mSettingsButton.setOnClickListener(this);
-        mQsDetailHeader = findViewById(R.id.qs_detail_header);
-        mQsDetailHeader.setAlpha(0);
-        mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
-        mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
-        mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
-        mEmergencyCallsOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
-        mBatteryLevel = (TextView) findViewById(R.id.battery_level);
-        mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
-        mAlarmStatus.setOnClickListener(this);
-        mSignalCluster = findViewById(R.id.signal_cluster);
-        mSystemIcons = (LinearLayout) findViewById(R.id.system_icons);
-        loadDimens();
-        updateVisibilities();
-        updateClockScale();
-        updateAvatarScale();
-        addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
-            @Override
-            public void onLayoutChange(View v, int left, int top, int right,
-                    int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
-                if ((right - left) != (oldRight - oldLeft)) {
-                    // width changed, update clipping
-                    setClipping(getHeight());
-                }
-                boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-                mTime.setPivotX(rtl ? mTime.getWidth() : 0);
-                mTime.setPivotY(mTime.getBaseline());
-                updateAmPmTranslation();
-            }
-        });
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                outline.setRect(mClipBounds);
-            }
-        });
-        requestCaptureValues();
-
-        // RenderThread is doing more harm than good when touching the header (to expand quick
-        // settings), so disable it for this view
-        ((RippleDrawable) getBackground()).setForceSoftware(true);
-        ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
-        ((RippleDrawable) mSystemIconsSuperContainer.getBackground()).setForceSoftware(true);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        super.onLayout(changed, l, t, r, b);
-        if (mCaptureValues) {
-            if (mExpanded) {
-                captureLayoutValues(mExpandedValues);
-            } else {
-                captureLayoutValues(mCollapsedValues);
-            }
-            mCaptureValues = false;
-            updateLayoutValues(mCurrentT);
-        }
-        mAlarmStatus.setX(mDateGroup.getLeft() + mDateCollapsed.getRight());
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        FontSizeUtils.updateFontSize(mBatteryLevel, R.dimen.battery_level_text_size);
-        FontSizeUtils.updateFontSize(mEmergencyCallsOnly,
-                R.dimen.qs_emergency_calls_only_text_size);
-        FontSizeUtils.updateFontSize(mDateCollapsed, R.dimen.qs_date_collapsed_size);
-        FontSizeUtils.updateFontSize(mDateExpanded, R.dimen.qs_date_collapsed_size);
-        FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
-        FontSizeUtils.updateFontSize(this, android.R.id.title, R.dimen.qs_detail_header_text_size);
-        FontSizeUtils.updateFontSize(this, android.R.id.toggle, R.dimen.qs_detail_header_text_size);
-        FontSizeUtils.updateFontSize(mAmPm, R.dimen.qs_time_collapsed_size);
-        FontSizeUtils.updateFontSize(this, R.id.empty_time_view, R.dimen.qs_time_expanded_size);
-
-        mEmergencyCallsOnly.setText(com.android.internal.R.string.emergency_calls_only);
-
-        mClockCollapsedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size);
-        mClockExpandedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
-        mClockCollapsedScaleFactor = (float) mClockCollapsedSize / (float) mClockExpandedSize;
-
-        updateClockScale();
-        updateClockCollapsedMargin();
-    }
-
-    private void updateClockCollapsedMargin() {
-        Resources res = getResources();
-        int padding = res.getDimensionPixelSize(R.dimen.clock_collapsed_bottom_margin);
-        int largePadding = res.getDimensionPixelSize(
-                R.dimen.clock_collapsed_bottom_margin_large_text);
-        float largeFactor = (MathUtils.constrain(getResources().getConfiguration().fontScale, 1.0f,
-                FontSizeUtils.LARGE_TEXT_SCALE) - 1f) / (FontSizeUtils.LARGE_TEXT_SCALE - 1f);
-        mClockMarginBottomCollapsed = Math.round((1 - largeFactor) * padding + largeFactor * largePadding);
-        requestLayout();
-    }
-
-    private void requestCaptureValues() {
-        mCaptureValues = true;
-        requestLayout();
-    }
-
-    private void loadDimens() {
-        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
-        mExpandedHeight = getResources().getDimensionPixelSize(
-                R.dimen.status_bar_header_height_expanded);
-        mMultiUserExpandedMargin =
-                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
-        mMultiUserCollapsedMargin =
-                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_collapsed_margin);
-        mClockMarginBottomExpanded =
-                getResources().getDimensionPixelSize(R.dimen.clock_expanded_bottom_margin);
-        updateClockCollapsedMargin();
-        mMultiUserSwitchWidthCollapsed =
-                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_collapsed);
-        mMultiUserSwitchWidthExpanded =
-                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_expanded);
-        mAvatarCollapsedScaleFactor =
-                getResources().getDimensionPixelSize(R.dimen.multi_user_avatar_collapsed_size)
-                / (float) mMultiUserAvatar.getLayoutParams().width;
-        mClockCollapsedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size);
-        mClockExpandedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
-        mClockCollapsedScaleFactor = (float) mClockCollapsedSize / (float) mClockExpandedSize;
-
-    }
-
-    public void setActivityStarter(ActivityStarter activityStarter) {
-        mActivityStarter = activityStarter;
-    }
-
-    public void setBatteryController(BatteryController batteryController) {
-        mBatteryController = batteryController;
-        ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
-    }
-
-    public void setNextAlarmController(NextAlarmController nextAlarmController) {
-        mNextAlarmController = nextAlarmController;
-    }
-
-    public int getCollapsedHeight() {
-        return mCollapsedHeight;
-    }
-
-    public int getExpandedHeight() {
-        return mAllowExpand ? mExpandedHeight : mCollapsedHeight;
-    }
-
-    public void setListening(boolean listening) {
-        if (listening == mListening) {
-            return;
-        }
-        mListening = listening;
-        updateListeners();
-    }
-
-    public void setExpanded(boolean expanded) {
-        if (!mAllowExpand) {
-            expanded = false;
-        }
-        boolean changed = expanded != mExpanded;
-        mExpanded = expanded;
-        if (changed) {
-            updateEverything();
-        }
-    }
-
-    public void updateEverything() {
-        updateHeights();
-        updateVisibilities();
-        updateSystemIconsLayoutParams();
-        updateClickTargets();
-        updateMultiUserSwitch();
-        updateClockScale();
-        updateAvatarScale();
-        updateClockLp();
-        requestCaptureValues();
-    }
-
-    private void updateHeights() {
-        int height = mExpanded ? mExpandedHeight : mCollapsedHeight;
-        ViewGroup.LayoutParams lp = getLayoutParams();
-        if (lp.height != height) {
-            lp.height = height;
-            setLayoutParams(lp);
-        }
-    }
-
-    private void updateVisibilities() {
-        mDateCollapsed.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
-        mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE);
-        mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
-        mSettingsContainer.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
-        mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE);
-        if (mSignalCluster != null) {
-            updateSignalClusterDetachment();
-        }
-        mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE);
-        mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
-        mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
-                TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
-    }
-
-    private void updateSignalClusterDetachment() {
-        boolean detached = mExpanded;
-        if (detached != mSignalClusterDetached) {
-            if (detached) {
-                getOverlay().add(mSignalCluster);
-            } else {
-                reattachSignalCluster();
-            }
-        }
-        mSignalClusterDetached = detached;
-    }
-
-    private void reattachSignalCluster() {
-        getOverlay().remove(mSignalCluster);
-        mSystemIcons.addView(mSignalCluster, 1);
-    }
-
-    private void updateSystemIconsLayoutParams() {
-        RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams();
-        int rule = mExpanded
-                ? mSettingsContainer.getId()
-                : mMultiUserSwitch.getId();
-        if (rule != lp.getRules()[RelativeLayout.START_OF]) {
-            lp.addRule(RelativeLayout.START_OF, rule);
-            mSystemIconsSuperContainer.setLayoutParams(lp);
-        }
-    }
-
-    private void updateListeners() {
-        if (mListening) {
-            mBatteryController.addStateChangedCallback(this);
-            mNextAlarmController.addStateChangedCallback(this);
-        } else {
-            mBatteryController.removeStateChangedCallback(this);
-            mNextAlarmController.removeStateChangedCallback(this);
-        }
-    }
-
-    private void updateAvatarScale() {
-        if (mExpanded) {
-            mMultiUserAvatar.setScaleX(1f);
-            mMultiUserAvatar.setScaleY(1f);
-        } else {
-            mMultiUserAvatar.setScaleX(mAvatarCollapsedScaleFactor);
-            mMultiUserAvatar.setScaleY(mAvatarCollapsedScaleFactor);
-        }
-    }
-
-    private void updateClockScale() {
-        mTime.setTextSize(TypedValue.COMPLEX_UNIT_PX, mExpanded
-                ? mClockExpandedSize
-                : mClockCollapsedSize);
-        mTime.setScaleX(1f);
-        mTime.setScaleY(1f);
-        updateAmPmTranslation();
-    }
-
-    private void updateAmPmTranslation() {
-        boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-        mAmPm.setTranslationX((rtl ? 1 : -1) * mTime.getWidth() * (1 - mTime.getScaleX()));
-    }
-
-    @Override
-    public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
-        String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
-        mBatteryLevel.setText(percentage);
-    }
-
-    @Override
-    public void onPowerSaveChanged(boolean isPowerSave) {
-        // could not care less
-    }
-
-    @Override
-    public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
-        mNextAlarm = nextAlarm;
-        if (nextAlarm != null) {
-            mAlarmStatus.setText(KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm));
-        }
-        mAlarmShowing = nextAlarm != null;
-        updateEverything();
-        requestCaptureValues();
-    }
-
-    private void updateClickTargets() {
-        mMultiUserSwitch.setClickable(mExpanded);
-        mMultiUserSwitch.setFocusable(mExpanded);
-        mSystemIconsSuperContainer.setClickable(mExpanded);
-        mSystemIconsSuperContainer.setFocusable(mExpanded);
-        mAlarmStatus.setClickable(mNextAlarm != null && mNextAlarm.getShowIntent() != null);
-    }
-
-    private void updateClockLp() {
-        int marginBottom = mExpanded
-                ? mClockMarginBottomExpanded
-                : mClockMarginBottomCollapsed;
-        LayoutParams lp = (LayoutParams) mDateGroup.getLayoutParams();
-        if (marginBottom != lp.bottomMargin) {
-            lp.bottomMargin = marginBottom;
-            mDateGroup.setLayoutParams(lp);
-        }
-    }
-
-    private void updateMultiUserSwitch() {
-        int marginEnd;
-        int width;
-        if (mExpanded) {
-            marginEnd = mMultiUserExpandedMargin;
-            width = mMultiUserSwitchWidthExpanded;
-        } else {
-            marginEnd = mMultiUserCollapsedMargin;
-            width = mMultiUserSwitchWidthCollapsed;
-        }
-        MarginLayoutParams lp = (MarginLayoutParams) mMultiUserSwitch.getLayoutParams();
-        if (marginEnd != lp.getMarginEnd() || lp.width != width) {
-            lp.setMarginEnd(marginEnd);
-            lp.width = width;
-            mMultiUserSwitch.setLayoutParams(lp);
-        }
-    }
-
-    public void setExpansion(float t) {
-        if (!mExpanded) {
-            t = 0f;
-        }
-        mCurrentT = t;
-        float height = mCollapsedHeight + t * (mExpandedHeight - mCollapsedHeight);
-        if (height < mCollapsedHeight) {
-            height = mCollapsedHeight;
-        }
-        if (height > mExpandedHeight) {
-            height = mExpandedHeight;
-        }
-        setClipping(height);
-        updateLayoutValues(t);
-    }
-
-    private void updateLayoutValues(float t) {
-        if (mCaptureValues) {
-            return;
-        }
-        mCurrentValues.interpoloate(mCollapsedValues, mExpandedValues, t);
-        applyLayoutValues(mCurrentValues);
-    }
-
-    private void setClipping(float height) {
-        mClipBounds.set(getPaddingLeft(), 0, getWidth() - getPaddingRight(), (int) height);
-        setClipBounds(mClipBounds);
-        invalidateOutline();
-    }
-
-    public void setUserInfoController(UserInfoController userInfoController) {
-        userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
-            @Override
-            public void onUserInfoChanged(String name, Drawable picture) {
-                mMultiUserAvatar.setImageDrawable(picture);
-            }
-        });
-    }
-
-    @Override
-    public void setCallback(Callback qsPanelCallback) {
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (v == mSettingsButton) {
-            if (mSettingsButton.isTunerClick()) {
-                if (TunerService.isTunerEnabled(mContext)) {
-                    TunerService.showResetRequest(mContext, new Runnable() {
-                        @Override
-                        public void run() {
-                            // Relaunch settings so that the tuner disappears.
-                            startSettingsActivity();
-                        }
-                    });
-                } else {
-                    Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
-                    TunerService.setTunerEnabled(mContext, true);
-                }
-            }
-            startSettingsActivity();
-        } else if (v == mSystemIconsSuperContainer) {
-            startBatteryActivity();
-        } else if (v == mAlarmStatus && mNextAlarm != null) {
-            PendingIntent showIntent = mNextAlarm.getShowIntent();
-            if (showIntent != null) {
-                mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
-            }
-        }
-    }
-
-    private void startSettingsActivity() {
-        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
-                true /* dismissShade */);
-    }
-
-    private void startBatteryActivity() {
-        mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY),
-                true /* dismissShade */);
-    }
-
-    public void setQSPanel(QSPanel qsp) {
-        mQSPanel = qsp;
-        if (mQSPanel != null) {
-            mQSPanel.setCallback(mQsPanelCallback);
-        }
-        mMultiUserSwitch.setQsPanel(qsp);
-    }
-
-    @Override
-    public boolean shouldDelayChildPressedState() {
-        return true;
-    }
-
-    @Override
-    public void setEmergencyCallsOnly(boolean show) {
-        boolean changed = show != mShowEmergencyCallsOnly;
-        if (changed) {
-            mShowEmergencyCallsOnly = show;
-            if (mExpanded) {
-                updateEverything();
-                requestCaptureValues();
-            }
-        }
-    }
-
-    @Override
-    protected void dispatchSetPressed(boolean pressed) {
-        // We don't want that everything lights up when we click on the header, so block the request
-        // here.
-    }
-
-    private void captureLayoutValues(LayoutValues target) {
-        target.timeScale = mExpanded ? 1f : mClockCollapsedScaleFactor;
-        target.clockY = mClock.getBottom();
-        target.dateY = mDateGroup.getTop();
-        target.emergencyCallsOnlyAlpha = getAlphaForVisibility(mEmergencyCallsOnly);
-        target.alarmStatusAlpha = getAlphaForVisibility(mAlarmStatus);
-        target.dateCollapsedAlpha = getAlphaForVisibility(mDateCollapsed);
-        target.dateExpandedAlpha = getAlphaForVisibility(mDateExpanded);
-        target.avatarScale = mMultiUserAvatar.getScaleX();
-        target.avatarX = mMultiUserSwitch.getLeft() + mMultiUserAvatar.getLeft();
-        target.avatarY = mMultiUserSwitch.getTop() + mMultiUserAvatar.getTop();
-        if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
-            target.batteryX = mSystemIconsSuperContainer.getLeft()
-                    + mSystemIconsContainer.getRight();
-        } else {
-            target.batteryX = mSystemIconsSuperContainer.getLeft()
-                    + mSystemIconsContainer.getLeft();
-        }
-        target.batteryY = mSystemIconsSuperContainer.getTop() + mSystemIconsContainer.getTop();
-        target.batteryLevelAlpha = getAlphaForVisibility(mBatteryLevel);
-        target.settingsAlpha = getAlphaForVisibility(mSettingsContainer);
-        target.settingsTranslation = mExpanded
-                ? 0
-                : mMultiUserSwitch.getLeft() - mSettingsContainer.getLeft();
-        target.signalClusterAlpha = mSignalClusterDetached ? 0f : 1f;
-        target.settingsRotation = !mExpanded ? 90f : 0f;
-    }
-
-    private float getAlphaForVisibility(View v) {
-        return v == null || v.getVisibility() == View.VISIBLE ? 1f : 0f;
-    }
-
-    private void applyAlpha(View v, float alpha) {
-        if (v == null || v.getVisibility() == View.GONE) {
-            return;
-        }
-        if (alpha == 0f) {
-            v.setVisibility(View.INVISIBLE);
-        } else {
-            v.setVisibility(View.VISIBLE);
-            v.setAlpha(alpha);
-        }
-    }
-
-    private void applyLayoutValues(LayoutValues values) {
-        mTime.setScaleX(values.timeScale);
-        mTime.setScaleY(values.timeScale);
-        mClock.setY(values.clockY - mClock.getHeight());
-        mDateGroup.setY(values.dateY);
-        mAlarmStatus.setY(values.dateY - mAlarmStatus.getPaddingTop());
-        mMultiUserAvatar.setScaleX(values.avatarScale);
-        mMultiUserAvatar.setScaleY(values.avatarScale);
-        mMultiUserAvatar.setX(values.avatarX - mMultiUserSwitch.getLeft());
-        mMultiUserAvatar.setY(values.avatarY - mMultiUserSwitch.getTop());
-        if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
-            mSystemIconsSuperContainer.setX(values.batteryX - mSystemIconsContainer.getRight());
-        } else {
-            mSystemIconsSuperContainer.setX(values.batteryX - mSystemIconsContainer.getLeft());
-        }
-        mSystemIconsSuperContainer.setY(values.batteryY - mSystemIconsContainer.getTop());
-        if (mSignalCluster != null && mExpanded) {
-            if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
-                mSignalCluster.setX(mSystemIconsSuperContainer.getX()
-                        - mSignalCluster.getWidth());
-            } else {
-                mSignalCluster.setX(mSystemIconsSuperContainer.getX()
-                        + mSystemIconsSuperContainer.getWidth());
-            }
-            mSignalCluster.setY(
-                    mSystemIconsSuperContainer.getY() + mSystemIconsSuperContainer.getHeight()/2
-                            - mSignalCluster.getHeight()/2);
-        } else if (mSignalCluster != null) {
-            mSignalCluster.setTranslationX(0f);
-            mSignalCluster.setTranslationY(0f);
-        }
-        if (!mSettingsButton.isAnimating()) {
-            mSettingsContainer.setTranslationY(mSystemIconsSuperContainer.getTranslationY());
-            mSettingsContainer.setTranslationX(values.settingsTranslation);
-            mSettingsButton.setRotation(values.settingsRotation);
-        }
-        applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha);
-        if (!mShowingDetail && !mDetailTransitioning) {
-            // Otherwise it needs to stay invisible
-            applyAlpha(mAlarmStatus, values.alarmStatusAlpha);
-        }
-        applyAlpha(mDateCollapsed, values.dateCollapsedAlpha);
-        applyAlpha(mDateExpanded, values.dateExpandedAlpha);
-        applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
-        applyAlpha(mSettingsContainer, values.settingsAlpha);
-        applyAlpha(mSignalCluster, values.signalClusterAlpha);
-        if (!mExpanded) {
-            mTime.setScaleX(1f);
-            mTime.setScaleY(1f);
-        }
-        updateAmPmTranslation();
-    }
-
-    /**
-     * Captures all layout values (position, visibility) for a certain state. This is used for
-     * animations.
-     */
-    private static final class LayoutValues {
-
-        float dateExpandedAlpha;
-        float dateCollapsedAlpha;
-        float emergencyCallsOnlyAlpha;
-        float alarmStatusAlpha;
-        float timeScale = 1f;
-        float clockY;
-        float dateY;
-        float avatarScale;
-        float avatarX;
-        float avatarY;
-        float batteryX;
-        float batteryY;
-        float batteryLevelAlpha;
-        float settingsAlpha;
-        float settingsTranslation;
-        float signalClusterAlpha;
-        float settingsRotation;
-
-        public void interpoloate(LayoutValues v1, LayoutValues v2, float t) {
-            timeScale = v1.timeScale * (1 - t) + v2.timeScale * t;
-            clockY = v1.clockY * (1 - t) + v2.clockY * t;
-            dateY = v1.dateY * (1 - t) + v2.dateY * t;
-            avatarScale = v1.avatarScale * (1 - t) + v2.avatarScale * t;
-            avatarX = v1.avatarX * (1 - t) + v2.avatarX * t;
-            avatarY = v1.avatarY * (1 - t) + v2.avatarY * t;
-            batteryX = v1.batteryX * (1 - t) + v2.batteryX * t;
-            batteryY = v1.batteryY * (1 - t) + v2.batteryY * t;
-            settingsTranslation = v1.settingsTranslation * (1 - t) + v2.settingsTranslation * t;
-
-            float t1 = Math.max(0, t - 0.5f) * 2;
-            settingsRotation = v1.settingsRotation * (1 - t1) + v2.settingsRotation * t1;
-            emergencyCallsOnlyAlpha =
-                    v1.emergencyCallsOnlyAlpha * (1 - t1) + v2.emergencyCallsOnlyAlpha * t1;
-
-            float t2 = Math.min(1, 2 * t);
-            signalClusterAlpha = v1.signalClusterAlpha * (1 - t2) + v2.signalClusterAlpha * t2;
-
-            float t3 = Math.max(0, t - 0.7f) / 0.3f;
-            batteryLevelAlpha = v1.batteryLevelAlpha * (1 - t3) + v2.batteryLevelAlpha * t3;
-            settingsAlpha = v1.settingsAlpha * (1 - t3) + v2.settingsAlpha * t3;
-            dateExpandedAlpha = v1.dateExpandedAlpha * (1 - t3) + v2.dateExpandedAlpha * t3;
-            dateCollapsedAlpha = v1.dateCollapsedAlpha * (1 - t3) + v2.dateCollapsedAlpha * t3;
-            alarmStatusAlpha = v1.alarmStatusAlpha * (1 - t3) + v2.alarmStatusAlpha * t3;
-        }
-    }
-
-    private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
-        private boolean mScanState;
-
-        @Override
-        public void onToggleStateChanged(final boolean state) {
-            post(new Runnable() {
-                @Override
-                public void run() {
-                    handleToggleStateChanged(state);
-                }
-            });
-        }
-
-        @Override
-        public void onShowingDetail(final DetailAdapter detail, int x, int y) {
-            mDetailTransitioning = true;
-            post(new Runnable() {
-                @Override
-                public void run() {
-                    handleShowingDetail(detail);
-                }
-            });
-        }
-
-        @Override
-        public void onScanStateChanged(final boolean state) {
-            post(new Runnable() {
-                @Override
-                public void run() {
-                    handleScanStateChanged(state);
-                }
-            });
-        }
-
-        private void handleToggleStateChanged(boolean state) {
-            mQsDetailHeaderSwitch.setChecked(state);
-        }
-
-        private void handleScanStateChanged(boolean state) {
-            if (mScanState == state) return;
-            mScanState = state;
-            final Animatable anim = (Animatable) mQsDetailHeaderProgress.getDrawable();
-            if (state) {
-                mQsDetailHeaderProgress.animate().alpha(1f);
-                anim.start();
-            } else {
-                mQsDetailHeaderProgress.animate().alpha(0f);
-                anim.stop();
-            }
-        }
-
-        private void handleShowingDetail(final QSTile.DetailAdapter detail) {
-            final boolean showingDetail = detail != null;
-            transition(mClock, !showingDetail);
-            transition(mDateGroup, !showingDetail);
-            if (mAlarmShowing) {
-                transition(mAlarmStatus, !showingDetail);
-            }
-            transition(mQsDetailHeader, showingDetail);
-            mShowingDetail = showingDetail;
-            if (showingDetail) {
-                mQsDetailHeaderTitle.setText(detail.getTitle());
-                final Boolean toggleState = detail.getToggleState();
-                if (toggleState == null) {
-                    mQsDetailHeaderSwitch.setVisibility(INVISIBLE);
-                    mQsDetailHeader.setClickable(false);
-                } else {
-                    mQsDetailHeaderSwitch.setVisibility(VISIBLE);
-                    mQsDetailHeaderSwitch.setChecked(toggleState);
-                    mQsDetailHeader.setClickable(true);
-                    mQsDetailHeader.setOnClickListener(new OnClickListener() {
-                        @Override
-                        public void onClick(View v) {
-                            boolean checked = !mQsDetailHeaderSwitch.isChecked();
-                            mQsDetailHeaderSwitch.setChecked(checked);
-                            detail.setToggleState(checked);
-                        }
-                    });
-                }
-            } else {
-                mQsDetailHeader.setClickable(false);
-            }
-        }
-
-        private void transition(final View v, final boolean in) {
-            if (in) {
-                v.bringToFront();
-                v.setVisibility(VISIBLE);
-            }
-            if (v.hasOverlappingRendering()) {
-                v.animate().withLayer();
-            }
-            v.animate()
-                    .alpha(in ? 1 : 0)
-                    .withEndAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            if (!in) {
-                                v.setVisibility(INVISIBLE);
-                            }
-                            mDetailTransitioning = false;
-                        }
-                    })
-                    .start();
-        }
-    };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 6439bea..014cc49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -40,7 +40,6 @@
     private static final String TAG = "BluetoothController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     private final LocalBluetoothManager mLocalBluetoothManager;
     private final UserManager mUserManager;
     private final int mCurrentUser;
@@ -78,7 +77,7 @@
         pw.print("  mEnabled="); pw.println(mEnabled);
         pw.print("  mConnectionState="); pw.println(stateToString(mConnectionState));
         pw.print("  mLastDevice="); pw.println(mLastDevice);
-        pw.print("  mCallbacks.size="); pw.println(mCallbacks.size());
+        pw.print("  mCallbacks.size="); pw.println(mHandler.mCallbacks.size());
         pw.println("  Bluetooth Devices:");
         for (CachedBluetoothDevice device :
                 mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) {
@@ -106,13 +105,13 @@
 
     @Override
     public void addStateChangedCallback(Callback cb) {
-        mCallbacks.add(cb);
+        mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
         mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
     }
 
     @Override
     public void removeStateChangedCallback(Callback cb) {
-        mCallbacks.remove(cb);
+        mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget();
     }
 
     @Override
@@ -236,8 +235,12 @@
     }
 
     private final class H extends Handler {
+        private final ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>();
+
         private static final int MSG_PAIRED_DEVICES_CHANGED = 1;
         private static final int MSG_STATE_CHANGED = 2;
+        private static final int MSG_ADD_CALLBACK = 3;
+        private static final int MSG_REMOVE_CALLBACK = 4;
 
         @Override
         public void handleMessage(Message msg) {
@@ -248,6 +251,12 @@
                 case MSG_STATE_CHANGED:
                     fireStateChange();
                     break;
+                case MSG_ADD_CALLBACK:
+                    mCallbacks.add((BluetoothController.Callback) msg.obj);
+                    break;
+                case MSG_REMOVE_CALLBACK:
+                    mCallbacks.remove((BluetoothController.Callback) msg.obj);
+                    break;
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 7704a07..a2289c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -21,6 +21,7 @@
 import android.app.RemoteInput;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ShortcutManager;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -132,6 +133,15 @@
         mEditText.mShowImeOnInputConnection = false;
         mController.remoteInputSent(mEntry);
 
+        // Tell ShortcutManager that this package has been "activated".  ShortcutManager
+        // will reset the throttling for this package.
+        // Strictly speaking, the intent receiver may be different from the notification publisher,
+        // but that's an edge case, and also because we can't always know which package will receive
+        // an intent, so we just reset for the publisher.
+        getContext().getSystemService(ShortcutManager.class).onApplicationActive(
+                mEntry.notification.getPackageName(),
+                mEntry.notification.getUser().getIdentifier());
+
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_SEND,
                 mEntry.notification.getPackageName());
         try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 415b7a1..89d2712 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -51,6 +51,7 @@
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.systemui.GuestResumeSessionReceiver;
 import com.android.systemui.R;
+import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUISecondaryUserService;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.tiles.UserDetailView;
@@ -523,7 +524,7 @@
         private void showLogoutNotification(int userId) {
             PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
                     0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
-            Notification notification = new Notification.Builder(mContext)
+            Notification.Builder builder = new Notification.Builder(mContext)
                     .setVisibility(Notification.VISIBILITY_SECRET)
                     .setPriority(Notification.PRIORITY_MIN)
                     .setSmallIcon(R.drawable.ic_person)
@@ -534,10 +535,10 @@
                     .setShowWhen(false)
                     .addAction(R.drawable.ic_delete,
                             mContext.getString(R.string.user_logout_notification_action),
-                            logoutPI)
-                    .build();
+                            logoutPI);
+            SystemUI.overrideNotificationAppName(mContext, builder);
             NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER, ID_LOGOUT_USER,
-                    notification, new UserHandle(userId));
+                    builder.build(), new UserHandle(userId));
         }
     };
 
@@ -547,7 +548,7 @@
         PendingIntent removeGuestPI = canSwitchUsers ? PendingIntent.getBroadcastAsUser(mContext,
                 0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM) : null;
 
-        Notification notification = new Notification.Builder(mContext)
+        Notification.Builder builder = new Notification.Builder(mContext)
                 .setVisibility(Notification.VISIBILITY_SECRET)
                 .setPriority(Notification.PRIORITY_MIN)
                 .setSmallIcon(R.drawable.ic_person)
@@ -557,10 +558,10 @@
                 .setShowWhen(false)
                 .addAction(R.drawable.ic_delete,
                         mContext.getString(R.string.guest_notification_remove_action),
-                        removeGuestPI)
-                .build();
+                        removeGuestPI);
+        SystemUI.overrideNotificationAppName(mContext, builder);
         NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
-                notification, new UserHandle(guestUserId));
+                builder.build(), new UserHandle(guestUserId));
     }
 
     private final Runnable mUnpauseRefreshUsers = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index ba191cd..3c9373b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -856,14 +856,6 @@
                 mNotificationParent.getNotificationColor());
     }
 
-    public void setRemoved() {
-        int childCount = mChildren.size();
-        for (int i = 0; i < childCount; i++) {
-            ExpandableNotificationRow child = mChildren.get(i);
-            child.setRemoved();
-        }
-    }
-
     public int getPositionInLinearLayout(View childInGroup) {
         int position = mNotificationHeaderMargin + mNotificatonTopPadding;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 7c391fb..7de3879 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -769,7 +769,7 @@
                 mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey());
             }
         }
-        performDismiss(v);
+        performDismiss(v, mGroupManager, false /* fromAccessibility */);
 
         mFalsingManager.onNotificationDismissed();
         if (mFalsingManager.shouldEnforceBouncer()) {
@@ -778,17 +778,18 @@
         }
     }
 
-    private void performDismiss(View v) {
+    public static void performDismiss(View v, NotificationGroupManager groupManager,
+            boolean fromAccessibility) {
         if (v instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            if (mGroupManager.isOnlyChildInSuppressedGroup(row.getStatusBarNotification())) {
+            if (groupManager.isOnlyChildInGroup(row.getStatusBarNotification())) {
                 ExpandableNotificationRow groupSummary =
-                        mGroupManager.getLogicalGroupSummary(row.getStatusBarNotification());
+                        groupManager.getLogicalGroupSummary(row.getStatusBarNotification());
                 if (groupSummary.isClearable()) {
-                    performDismiss(groupSummary);
+                    performDismiss(groupSummary, groupManager, fromAccessibility);
                 }
             }
-            row.setDismissed(true);
+            row.setDismissed(true, fromAccessibility);
         }
         final View veto = v.findViewById(R.id.veto);
         if (veto != null && veto.getVisibility() != View.GONE) {
@@ -1960,8 +1961,7 @@
                 // we're ending up at the same location as we are now, lets just skip the animation
                 bottom = finalBottom;
             } else {
-                bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()
-                        - lastView.getExtraBottomPadding());
+                bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight());
                 bottom = Math.min(bottom, getHeight());
             }
         } else {
@@ -2265,6 +2265,27 @@
 
         // Make sure the clipRect we might have set is removed
         expandableView.setClipTopAmount(0);
+
+        focusNextViewIfFocused(child);
+    }
+
+    private void focusNextViewIfFocused(View view) {
+        if (view instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+            if (row.shouldRefocusOnDismiss()) {
+                View nextView = row.getChildAfterViewWhenDismissed();
+                if (nextView == null) {
+                    View groupParentWhenDismissed = row.getGroupParentWhenDismissed();
+                    nextView = getFirstChildBelowTranlsationY(groupParentWhenDismissed != null
+                            ? groupParentWhenDismissed.getTranslationY()
+                            : view.getTranslationY());
+                }
+                if (nextView != null) {
+                    nextView.requestAccessibilityFocus();
+                }
+            }
+        }
+
     }
 
     private boolean isChildInGroup(View child) {
@@ -3668,6 +3689,9 @@
         if (mAnimationsEnabled) {
             mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp));
             mNeedsAnimation = true;
+            if (!mIsExpanded && !isHeadsUp) {
+                row.setHeadsupDisappearRunning(true);
+            }
             requestChildrenUpdate();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 7ac0d80..5bebbca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -733,6 +733,7 @@
             animator.setStartDelay(delay);
         }
         animator.addListener(getGlobalAnimationFinishedListener());
+        final boolean isHeadsUpDisappear = mHeadsUpDisappearChildren.contains(child);
         // remove the tag when the animation is finished
         animator.addListener(new AnimatorListenerAdapter() {
             @Override
@@ -741,6 +742,9 @@
                 child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
                 child.setTag(TAG_START_TRANSLATION_Y, null);
                 child.setTag(TAG_END_TRANSLATION_Y, null);
+                if (isHeadsUpDisappear) {
+                    ((ExpandableNotificationRow) child).setHeadsupDisappearRunning(false);
+                }
             }
         });
         startAnimator(animator);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 36dd727..97d5e10 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -198,7 +198,7 @@
                         rec.getNickname());
                 final CharSequence text = mContext.getString(R.string.ext_media_missing_message);
 
-                final Notification notif = new Notification.Builder(mContext)
+                Notification.Builder builder = new Notification.Builder(mContext)
                         .setSmallIcon(R.drawable.ic_sd_card_48dp)
                         .setColor(mContext.getColor(R.color.system_notification_accent_color))
                         .setContentTitle(title)
@@ -208,10 +208,11 @@
                         .setVisibility(Notification.VISIBILITY_PUBLIC)
                         .setLocalOnly(true)
                         .setCategory(Notification.CATEGORY_SYSTEM)
-                        .setDeleteIntent(buildSnoozeIntent(fsUuid))
-                        .build();
+                        .setDeleteIntent(buildSnoozeIntent(fsUuid));
+                SystemUI.overrideNotificationAppName(mContext, builder);
 
-                mNotificationManager.notifyAsUser(fsUuid, PRIVATE_ID, notif, UserHandle.ALL);
+                mNotificationManager.notifyAsUser(fsUuid, PRIVATE_ID, builder
+                        .build(), UserHandle.ALL);
             }
         }
     }
@@ -224,7 +225,7 @@
             final CharSequence text = mContext.getString(
                     R.string.ext_media_unsupported_notification_message, disk.getDescription());
 
-            final Notification notif = new Notification.Builder(mContext)
+            Notification.Builder builder = new Notification.Builder(mContext)
                     .setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE))
                     .setColor(mContext.getColor(R.color.system_notification_accent_color))
                     .setContentTitle(title)
@@ -233,10 +234,11 @@
                     .setStyle(new Notification.BigTextStyle().bigText(text))
                     .setVisibility(Notification.VISIBILITY_PUBLIC)
                     .setLocalOnly(true)
-                    .setCategory(Notification.CATEGORY_ERROR)
-                    .build();
+                    .setCategory(Notification.CATEGORY_ERROR);
+            SystemUI.overrideNotificationAppName(mContext, builder);
 
-            mNotificationManager.notifyAsUser(disk.getId(), DISK_ID, notif, UserHandle.ALL);
+            mNotificationManager.notifyAsUser(disk.getId(), DISK_ID, builder.build(),
+                    UserHandle.ALL);
 
         } else {
             // Yay, we have volumes!
@@ -471,7 +473,7 @@
             intent = buildWizardMigratePendingIntent(move);
         }
 
-        final Notification notif = new Notification.Builder(mContext)
+        Notification.Builder builder = new Notification.Builder(mContext)
                 .setSmallIcon(R.drawable.ic_sd_card_48dp)
                 .setColor(mContext.getColor(R.color.system_notification_accent_color))
                 .setContentTitle(title)
@@ -483,10 +485,11 @@
                 .setCategory(Notification.CATEGORY_PROGRESS)
                 .setPriority(Notification.PRIORITY_LOW)
                 .setProgress(100, status, false)
-                .setOngoing(true)
-                .build();
+                .setOngoing(true);
+        SystemUI.overrideNotificationAppName(mContext, builder);
 
-        mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, notif, UserHandle.ALL);
+        mNotificationManager.notifyAsUser(move.packageName, MOVE_ID,
+                builder.build(), UserHandle.ALL);
     }
 
     private void onMoveFinished(MoveInfo move, int status) {
@@ -520,7 +523,7 @@
             intent = null;
         }
 
-        final Notification notif = new Notification.Builder(mContext)
+        Notification.Builder builder = new Notification.Builder(mContext)
                 .setSmallIcon(R.drawable.ic_sd_card_48dp)
                 .setColor(mContext.getColor(R.color.system_notification_accent_color))
                 .setContentTitle(title)
@@ -531,10 +534,11 @@
                 .setLocalOnly(true)
                 .setCategory(Notification.CATEGORY_SYSTEM)
                 .setPriority(Notification.PRIORITY_LOW)
-                .setAutoCancel(true)
-                .build();
+                .setAutoCancel(true);
+        SystemUI.overrideNotificationAppName(mContext, builder);
 
-        mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, notif, UserHandle.ALL);
+        mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, builder.build(),
+                UserHandle.ALL);
     }
 
     private int getSmallIcon(DiskInfo disk, int state) {
@@ -555,7 +559,7 @@
 
     private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
             CharSequence text) {
-        return new Notification.Builder(mContext)
+        Notification.Builder builder = new Notification.Builder(mContext)
                 .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
                 .setColor(mContext.getColor(R.color.system_notification_accent_color))
                 .setContentTitle(title)
@@ -563,6 +567,8 @@
                 .setStyle(new Notification.BigTextStyle().bigText(text))
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
                 .setLocalOnly(true);
+        overrideNotificationAppName(mContext, builder);
+        return builder;
     }
 
     private PendingIntent buildInitPendingIntent(DiskInfo disk) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 1973e05..5b558a6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -68,6 +68,7 @@
 import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
 
+import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.tuner.TunerService;
@@ -152,7 +153,7 @@
         mKeyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
         mAccessibilityMgr = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
-        mActiveSliderTint = loadColorStateList(R.color.system_accent_color);
+        mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
         mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
 
         initDialog();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 2688813..c820302 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -228,22 +228,23 @@
             }
             final Intent intent =  new Intent(Receiver.DISABLE)
                     .putExtra(Receiver.EXTRA_COMPONENT, component);
+            Notification.Builder builder = new Notification.Builder(mContext)
+                    .setSmallIcon(R.drawable.ic_volume_media)
+                    .setWhen(0)
+                    .setShowWhen(false)
+                    .setOngoing(true)
+                    .setContentTitle(mContext.getString(
+                            R.string.volumeui_notification_title, getAppLabel(component)))
+                    .setContentText(mContext.getString(R.string.volumeui_notification_text))
+                    .setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent,
+                            PendingIntent.FLAG_UPDATE_CURRENT))
+                    .setPriority(Notification.PRIORITY_MIN)
+                    .setVisibility(Notification.VISIBILITY_PUBLIC)
+                    .setColor(mContext.getColor(
+                            com.android.internal.R.color.system_notification_accent_color));
+            overrideNotificationAppName(mContext, builder);
             mNotificationManager.notify(R.id.notification_volumeui,
-                    new Notification.Builder(mContext)
-                            .setSmallIcon(R.drawable.ic_volume_media)
-                            .setWhen(0)
-                            .setShowWhen(false)
-                            .setOngoing(true)
-                            .setContentTitle(mContext.getString(
-                                    R.string.volumeui_notification_title, getAppLabel(component)))
-                            .setContentText(mContext.getString(R.string.volumeui_notification_text))
-                            .setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent,
-                                    PendingIntent.FLAG_UPDATE_CURRENT))
-                            .setPriority(Notification.PRIORITY_MIN)
-                            .setVisibility(Notification.VISIBILITY_PUBLIC)
-                            .setColor(mContext.getColor(
-                                    com.android.internal.R.color.system_notification_accent_color))
-                            .build());
+                    builder.build());
         }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
index a30f507..c93377a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
@@ -36,6 +36,8 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import org.mockito.Mockito;
+
 @SmallTest
 public class TileLifecycleManagerTests extends AndroidTestCase {
     public static final String TILE_UPDATE_BROADCAST = "com.android.systemui.tests.TILE_UPDATE";
@@ -54,8 +56,11 @@
         mThread = new HandlerThread("TestThread");
         mThread.start();
         mHandler = new Handler(mThread.getLooper());
+        ComponentName component = new ComponentName(mContext, FakeTileService.class);
         mStateManager = new TileLifecycleManager(mHandler, getContext(),
-                new Intent(mContext, FakeTileService.class), new UserHandle(UserHandle.myUserId()));
+                Mockito.mock(IQSService.class), new Tile(component),
+                new Intent().setComponent(component),
+                new UserHandle(UserHandle.myUserId()));
         mCallbacks.clear();
         getContext().registerReceiver(mReceiver, new IntentFilter(TILE_UPDATE_BROADCAST));
     }
@@ -251,16 +256,6 @@
         @Override
         public IBinder onBind(Intent intent) {
             return new IQSTileService.Stub() {
-
-                @Override
-                public void setQSService(IQSService service) {
-
-                }
-
-                @Override
-                public void setQSTile(Tile tile) throws RemoteException {
-                }
-
                 @Override
                 public void onTileAdded() throws RemoteException {
                     sendCallback("onTileAdded");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
index 94c98d6..de3864d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
@@ -17,6 +17,7 @@
 
 import android.content.ComponentName;
 import android.os.Looper;
+import android.service.quicksettings.Tile;
 import android.test.suitebuilder.annotation.SmallTest;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.QSTileHost;
@@ -109,7 +110,7 @@
         }
 
         @Override
-        protected TileServiceManager onCreateTileService(ComponentName component) {
+        protected TileServiceManager onCreateTileService(ComponentName component, Tile qsTile) {
             TileServiceManager manager = Mockito.mock(TileServiceManager.class);
             mManagers.add(manager);
             return manager;
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 5527a41..a82d55f 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2323,6 +2323,41 @@
     // Deletion helper encountered an error during photo and video deletion.
     ACTION_DELETION_HELPER_PHOTOS_VIDEOS_DELETION_FAIL = 473;
 
+    // OPEN: Settings (root page if there are multiple tabs)
+    // CATEGORY: SETTINGS
+    DASHBOARD_CONTAINER = 474;
+
+    // OPEN: Settings -> SUPPORT TAB
+    // CATEGORY: SETTINGS
+    SUPPORT_FRAGMENT = 475;
+
+    // ACTION: Settings -> Select summary tab.
+    ACTION_SELECT_SUMMARY=476;
+
+    // ACTION: Settings -> Select support tab.
+    ACTION_SELECT_SUPPORT_FRAGMENT = 477;
+
+    // ACTION: Settings -> Support -> Tips & tricks
+    ACTION_SUPPORT_TIPS_AND_TRICKS = 478;
+
+    // ACTION: Settings -> Support -> Help & feedback
+    ACTION_SUPPORT_HELP_AND_FEEDBACK = 479;
+
+    // ACTION: Settings -> Support -> Sign in
+    ACTION_SUPPORT_SIGN_IN = 480;
+
+    // ACTION: Settings -> Support -> Phone
+    ACTION_SUPPORT_PHONE = 481;
+
+    // ACTION: Settings -> Support -> Chat
+    ACTION_SUPPORT_CHAT = 482;
+
+    // ACTION: Settings -> Support -> Phone/Chat -> Disclaimer Cancel
+    ACTION_SUPPORT_DISCLAIMER_CANCEL = 483;
+
+    // ACTION: Settings -> Support -> Phone/Chat -> Disclaimer OK
+    ACTION_SUPPORT_DISCLAIMER_OK = 484;
+
     // ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 04a0990..feceb14 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -20,6 +20,7 @@
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
+import android.annotation.UserIdInt;
 import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
@@ -67,6 +68,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AtomicFile;
@@ -650,7 +652,7 @@
     }
 
     private void ensureGroupStateLoadedLocked(int userId, boolean enforceUserUnlockingOrUnlocked) {
-        if (enforceUserUnlockingOrUnlocked && !mUserManager.isUserUnlockingOrUnlocked(userId)) {
+        if (enforceUserUnlockingOrUnlocked && !isUserRunningAndUnlocked(userId)) {
             throw new IllegalStateException(
                     "User " + userId + " must be unlocked for widgets to be available");
         }
@@ -695,6 +697,10 @@
         loadGroupStateLocked(newProfileIds);
     }
 
+    private boolean isUserRunningAndUnlocked(@UserIdInt int userId) {
+        return mUserManager.isUserRunning(userId) && StorageManager.isUserKeyUnlocked(userId);
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
@@ -3381,7 +3387,7 @@
             if (userInfo != null && userInfo.isManagedProfile()) {
                 UserInfo parentInfo = mUserManager.getProfileParent(userId);
                 if (parentInfo != null
-                        && !mUserManager.isUserUnlockingOrUnlocked(parentInfo.getUserHandle())) {
+                        && !isUserRunningAndUnlocked(parentInfo.getUserHandle().getIdentifier())) {
                     return true;
                 }
             }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 334b228..eea771d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2356,7 +2356,8 @@
             mConnecting = true;
             mConnectedAgent = null;
             try {
-                if (mActivityManager.bindBackupAgent(app, mode)) {
+                if (mActivityManager.bindBackupAgent(app.packageName, mode,
+                        UserHandle.USER_OWNER)) {
                     Slog.d(TAG, "awaiting agent for " + app);
 
                     // success; wait for the agent to arrive
@@ -9597,6 +9598,15 @@
         return list;
     }
 
+    public String[] getTransportWhitelist() {
+        // No permission check, intentionally.
+        String[] whitelist = new String[mTransportWhitelist.size()];
+        for (int i = mTransportWhitelist.size() - 1; i >= 0; i--) {
+            whitelist[i] = mTransportWhitelist.valueAt(i).flattenToShortString();
+        }
+        return whitelist;
+    }
+
     // Select which transport to use for the next backup operation.
     public String selectBackupTransport(String transport) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index e745263..312b878 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -275,6 +275,12 @@
     }
 
     @Override
+    public String[] getTransportWhitelist() {
+        BackupManagerService svc = mService;
+        return (svc != null) ? svc.getTransportWhitelist() : null;
+    }
+
+    @Override
     public String selectBackupTransport(String transport) throws RemoteException {
         BackupManagerService svc = mService;
         return (svc != null) ? svc.selectBackupTransport(transport) : null;
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 400c4a7..312553a 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -3074,9 +3074,6 @@
                 if (alarm.workSource != null && alarm.workSource.size() > 0) {
                     for (int wi=0; wi<alarm.workSource.size(); wi++) {
                         final String wsName = alarm.workSource.getName(wi);
-                        if (wsName == null) {
-                            Slog.w(TAG, "Null worksource name for alarm " + alarm);
-                        }
                         ActivityManagerNative.noteWakeupAlarm(
                                 alarm.operation, alarm.workSource.get(wi),
                                 (wsName != null) ? wsName : alarm.packageName,
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 71964d1..baa0bbe 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1171,8 +1171,27 @@
                     }
                     mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
                     mEnable = true;
+
+                    // Use service interface to get the exact state
+                    try {
+                        mBluetoothLock.readLock().lock();
+                        if (mBluetooth != null) {
+                            int state = mBluetooth.getState();
+                            if (state == BluetoothAdapter.STATE_BLE_ON) {
+                                Slog.w(TAG, "BT is in BLE_ON State");
+                                mBluetooth.onLeServiceUp();
+                                break;
+                            }
+                        }
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "", e);
+                    } finally {
+                        mBluetoothLock.readLock().unlock();
+                    }
+
+                    mQuietEnable = (msg.arg1 == 1);
                     if (mBluetooth == null) {
-                        handleEnable(msg.arg1 == 1);
+                        handleEnable(mQuietEnable);
                     } else {
                         //
                         // We need to wait until transitioned to STATE_OFF and
@@ -1190,7 +1209,6 @@
                         // on the order of (2 * SERVICE_RESTART_TIME_MS).
                         //
                         waitForOnOff(false, true);
-                        mQuietEnable = (msg.arg1 == 1);
                         Message restartMsg = mHandler.obtainMessage(
                                 MESSAGE_RESTART_BLUETOOTH_SERVICE);
                         mHandler.sendMessageDelayed(restartMsg,
@@ -1353,17 +1371,30 @@
                     // handle error state transition case from TURNING_ON to OFF
                     // unbind and rebind bluetooth service and enable bluetooth
                     if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) &&
-                        (newState == BluetoothAdapter.STATE_OFF) &&
-                        (mBluetooth != null) && mEnable) {
+                            (newState == BluetoothAdapter.STATE_OFF) &&
+                            (mBluetooth != null) && mEnable) {
                         recoverBluetoothServiceFromError();
                     }
                     if ((prevState == BluetoothAdapter.STATE_TURNING_ON) &&
-                        (newState == BluetoothAdapter.STATE_BLE_ON) &&
-                        (mBluetooth != null) && mEnable) {
+                            (newState == BluetoothAdapter.STATE_BLE_ON) &&
+                            (mBluetooth != null) && mEnable) {
                         recoverBluetoothServiceFromError();
                     }
+                    // If we tried to enable BT while BT was in the process of shutting down,
+                    // wait for the BT process to fully tear down and then force a restart
+                    // here.  This is a bit of a hack (b/29363429).
+                    if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) &&
+                            (newState == BluetoothAdapter.STATE_OFF)) {
+                        if (mEnable) {
+                            Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
+                            waitForOnOff(false, true);
+                            Message restartMsg = mHandler.obtainMessage(
+                                    MESSAGE_RESTART_BLUETOOTH_SERVICE);
+                            mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS);
+                        }
+                    }
                     if (newState == BluetoothAdapter.STATE_ON ||
-                        newState == BluetoothAdapter.STATE_BLE_ON) {
+                            newState == BluetoothAdapter.STATE_BLE_ON) {
                         // bluetooth is working, reset the counter
                         if (mErrorRecoveryRetryCounter != 0) {
                             Slog.w(TAG, "bluetooth is recovered from error");
@@ -1406,7 +1437,7 @@
                     // Send BT state broadcast to update
                     // the BT icon correctly
                     if ((mState == BluetoothAdapter.STATE_TURNING_ON) ||
-                        (mState == BluetoothAdapter.STATE_ON)) {
+                            (mState == BluetoothAdapter.STATE_ON)) {
                         bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
                                                     BluetoothAdapter.STATE_TURNING_OFF);
                         mState = BluetoothAdapter.STATE_TURNING_OFF;
@@ -1639,8 +1670,8 @@
         boolean isStandardBroadcast = true;
         if (prevState != newState) {
             //Notify all proxy objects first of adapter state change
-            if (newState == BluetoothAdapter.STATE_BLE_ON
-                   || newState == BluetoothAdapter.STATE_OFF) {
+            if (newState == BluetoothAdapter.STATE_BLE_ON ||
+                    newState == BluetoothAdapter.STATE_OFF) {
                 boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
                    && newState == BluetoothAdapter.STATE_BLE_ON);
 
@@ -1685,13 +1716,13 @@
                 sendBluetoothStateCallback(isUp);
                 sendBleStateChanged(prevState, newState);
 
-            } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON
-                || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) {
+            } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON ||
+                    newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) {
                 sendBleStateChanged(prevState, newState);
                 isStandardBroadcast = false;
 
-            } else if (newState == BluetoothAdapter.STATE_TURNING_ON
-                || newState == BluetoothAdapter.STATE_TURNING_OFF) {
+            } else if (newState == BluetoothAdapter.STATE_TURNING_ON ||
+                    newState == BluetoothAdapter.STATE_TURNING_OFF) {
                 sendBleStateChanged(prevState, newState);
             }
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index be440ed..e65b50c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3431,10 +3431,6 @@
                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
                 return false;
             }
-            // If the current VPN package is the same as the new one, this is a no-op
-            if (TextUtils.equals(packageName, vpn.getAlwaysOnPackage())) {
-                return true;
-            }
             if (!vpn.setAlwaysOnPackage(packageName, lockdown)) {
                 return false;
             }
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index bb966f7..afed5ef 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -212,7 +212,6 @@
 
     private int mActiveIdleOpCount;
     private PowerManager.WakeLock mActiveIdleWakeLock;
-    private IBinder mDownloadServiceActive;
     private boolean mJobsActive;
     private boolean mAlarmsActive;
     private boolean mReportedMaintenanceActivity;
@@ -607,7 +606,7 @@
          * This is the minimum amount of time that we will stay in maintenance mode after
          * a light doze.  We have this minimum to allow various things to respond to switching
          * in to maintenance mode and scheduling their work -- otherwise we may
-         * see there is nothing to do (no jobs or downloads pending) and go out of maintenance
+         * see there is nothing to do (no jobs pending) and go out of maintenance
          * mode immediately.
          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
          * @see #KEY_MIN_LIGHT_MAINTENANCE_TIME
@@ -618,7 +617,7 @@
          * This is the minimum amount of time that we will stay in maintenance mode after
          * a full doze.  We have this minimum to allow various things to respond to switching
          * in to maintenance mode and scheduling their work -- otherwise we may
-         * see there is nothing to do (no jobs or downloads pending) and go out of maintenance
+         * see there is nothing to do (no jobs pending) and go out of maintenance
          * mode immediately.
          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
          * @see #KEY_MIN_DEEP_MAINTENANCE_TIME
@@ -1220,28 +1219,6 @@
             }
         }
 
-        @Override public void downloadServiceActive(IBinder token) {
-            getContext().enforceCallingOrSelfPermission(
-                    "android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS", null);
-            long ident = Binder.clearCallingIdentity();
-            try {
-                DeviceIdleController.this.downloadServiceActive(token);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        @Override public void downloadServiceInactive() {
-            getContext().enforceCallingOrSelfPermission(
-                    "android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS", null);
-            long ident = Binder.clearCallingIdentity();
-            try {
-                DeviceIdleController.this.downloadServiceInactive();
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
         @Override public boolean registerMaintenanceActivityListener(
                 IMaintenanceActivityListener listener) {
             return DeviceIdleController.this.registerMaintenanceActivityListener(listener);
@@ -2086,30 +2063,6 @@
         }
     }
 
-    void downloadServiceActive(IBinder token) {
-        synchronized (this) {
-            mDownloadServiceActive = token;
-            reportMaintenanceActivityIfNeededLocked();
-            try {
-                token.linkToDeath(new IBinder.DeathRecipient() {
-                    @Override public void binderDied() {
-                        downloadServiceInactive();
-                    }
-                }, 0);
-            } catch (RemoteException e) {
-                mDownloadServiceActive = null;
-            }
-        }
-    }
-
-    void downloadServiceInactive() {
-        synchronized (this) {
-            mDownloadServiceActive = null;
-            reportMaintenanceActivityIfNeededLocked();
-            exitMaintenanceEarlyIfNeededLocked();
-        }
-    }
-
     void setJobsActive(boolean active) {
         synchronized (this) {
             mJobsActive = active;
@@ -2143,7 +2096,7 @@
     }
 
     void reportMaintenanceActivityIfNeededLocked() {
-        boolean active = mJobsActive | (mDownloadServiceActive != null);
+        boolean active = mJobsActive;
         if (active == mReportedMaintenanceActivity) {
             return;
         }
@@ -2154,8 +2107,7 @@
     }
 
     boolean isOpsInactiveLocked() {
-        return mActiveIdleOpCount <= 0 && mDownloadServiceActive == null
-                && !mJobsActive && !mAlarmsActive;
+        return mActiveIdleOpCount <= 0 && !mJobsActive && !mAlarmsActive;
     }
 
     void exitMaintenanceEarlyIfNeededLocked() {
@@ -3053,9 +3005,6 @@
             if (mAlarmsActive) {
                 pw.print("  mAlarmsActive="); pw.println(mAlarmsActive);
             }
-            if (mDownloadServiceActive != null) {
-                pw.print("  mDownloadServiceActive="); pw.println(mDownloadServiceActive);
-            }
         }
     }
 
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index eeb20bf..d64fe32 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -423,6 +423,9 @@
             if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
                 // Notify keystore that a new user was added.
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                if (userHandle > UserHandle.USER_SYSTEM) {
+                    removeUser(userHandle, /* unknownUser= */ true);
+                }
                 final KeyStore ks = KeyStore.getInstance();
                 final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
                 final int parentHandle = parentInfo != null ? parentInfo.id : -1;
@@ -433,7 +436,7 @@
             } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 if (userHandle > 0) {
-                    removeUser(userHandle);
+                    removeUser(userHandle, /* unknownUser= */ false);
                 }
             }
         }
@@ -617,6 +620,7 @@
 
     @Override
     public boolean getSeparateProfileChallengeEnabled(int userId) throws RemoteException {
+        checkReadPermission(SEPARATE_PROFILE_CHALLENGE_KEY, userId);
         synchronized (mSeparateChallengeLock) {
             return getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
         }
@@ -625,6 +629,7 @@
     @Override
     public void setSeparateProfileChallengeEnabled(int userId, boolean enabled,
             String managedUserPassword) throws RemoteException {
+        checkWritePermission(userId);
         synchronized (mSeparateChallengeLock) {
             setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
             if (enabled) {
@@ -672,7 +677,6 @@
     @Override
     public long getLong(String key, long defaultValue, int userId) throws RemoteException {
         checkReadPermission(key, userId);
-
         String value = getStringUnchecked(key, null, userId);
         return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
     }
@@ -680,7 +684,6 @@
     @Override
     public String getString(String key, String defaultValue, int userId) throws RemoteException {
         checkReadPermission(key, userId);
-
         return getStringUnchecked(key, defaultValue, userId);
     }
 
@@ -899,7 +902,7 @@
         }
     }
 
-    public void setLockPatternInternal(String pattern, String savedCredential, int userId)
+    private void setLockPatternInternal(String pattern, String savedCredential, int userId)
             throws RemoteException {
         byte[] currentHandle = getCurrentHandle(userId);
 
@@ -962,7 +965,7 @@
         }
     }
 
-    public void setLockPasswordInternal(String password, String savedCredential, int userId)
+    private void setLockPasswordInternal(String password, String savedCredential, int userId)
             throws RemoteException {
         byte[] currentHandle = getCurrentHandle(userId);
         if (password == null) {
@@ -1156,6 +1159,7 @@
 
     @Override
     public void resetKeyStore(int userId) throws RemoteException {
+        checkWritePermission(userId);
         if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
         int managedUserId = -1;
         String managedUserDecryptedPassword = null;
@@ -1464,7 +1468,7 @@
         return false;
     }
 
-    private void removeUser(int userId) {
+    private void removeUser(int userId, boolean unknownUser) {
         mStorage.removeUser(userId);
         mStrongAuth.removeUser(userId);
 
@@ -1479,7 +1483,7 @@
         } catch (RemoteException ex) {
             Slog.w(TAG, "unable to clear GK secure user id");
         }
-        if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+        if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) {
             removeKeystoreProfileKey(userId);
         }
     }
@@ -1558,6 +1562,7 @@
             LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
             LockPatternUtils.PASSWORD_HISTORY_KEY,
             LockPatternUtils.PASSWORD_TYPE_KEY,
+            SEPARATE_PROFILE_CHALLENGE_KEY
     };
 
     private static final String[] SETTINGS_TO_BACKUP = new String[] {
@@ -1588,7 +1593,7 @@
         }
 
         final IBinder service =
-            ServiceManager.getService("android.service.gatekeeper.IGateKeeperService");
+            ServiceManager.getService(Context.GATEKEEPER_SERVICE);
         if (service != null) {
             service.linkToDeath(new GateKeeperDiedRecipient(), 0);
             mGateKeeperService = IGateKeeperService.Stub.asInterface(service);
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 1e0b693..e233b1c 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -466,12 +466,13 @@
             enforceOemUnlockWritePermission();
             enforceIsAdmin();
 
-            // Do not allow oem unlock modification if it has been disallowed.
-            if (Settings.Global.getInt(getContext().getContentResolver(),
-                    Settings.Global.OEM_UNLOCK_DISALLOWED, 0) == 1) {
-                throw new SecurityException("OEM unlock has been disallowed.");
-            }
             if (enabled) {
+                // Do not allow oem unlock to be enabled if it has been disallowed.
+                if (Settings.Global.getInt(getContext().getContentResolver(),
+                        Settings.Global.OEM_UNLOCK_DISALLOWED, 0) == 1) {
+                    throw new SecurityException(
+                            "OEM unlock has been disallowed by OEM_UNLOCK_DISALLOWED.");
+                }
                 enforceFactoryResetAllowed();
             }
             synchronized (mLock) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 4084542..f7bd04b 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3425,7 +3425,7 @@
     /** {@hide} */
     @NonNull
     public AccountAndUser[] getAllAccounts() {
-        final List<UserInfo> users = getUserManager().getUsers();
+        final List<UserInfo> users = getUserManager().getUsers(true);
         final int[] userIds = new int[users.size()];
         for (int i = 0; i < userIds.length; i++) {
             userIds[i] = users.get(i).id;
@@ -3538,7 +3538,7 @@
 
     @Override
     public void addSharedAccountsFromParentUser(int parentUserId, int userId) {
-        checkManageUsersPermission("addSharedAccountsFromParentUser");
+        checkManageOrCreateUsersPermission("addSharedAccountsFromParentUser");
         Account[] accounts = getAccountsAsUser(null, parentUserId, mContext.getOpPackageName());
         for (Account account : accounts) {
             addSharedAccountAsUser(account, userId);
@@ -5092,6 +5092,16 @@
         }
     }
 
+    private static void checkManageOrCreateUsersPermission(String message) {
+        if (ActivityManager.checkComponentPermission(android.Manifest.permission.MANAGE_USERS,
+                Binder.getCallingUid(), -1, true) != PackageManager.PERMISSION_GRANTED &&
+                ActivityManager.checkComponentPermission(android.Manifest.permission.CREATE_USERS,
+                        Binder.getCallingUid(), -1, true) != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("You need MANAGE_USERS or CREATE_USERS permission to: "
+                    + message);
+        }
+    }
+
     private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType,
             int callerUid) {
         if (callerUid == Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index dcd9b0c..7986629 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1443,6 +1443,12 @@
             boolean allowCancel) {
         boolean canceled = false;
 
+        if (mAm.isShuttingDownLocked()) {
+            Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortName
+                    + " - system is shutting down");
+            return false;
+        }
+
         ServiceMap smap = getServiceMap(r.userId);
         if (smap.mServicesByName.get(r.name) != r) {
             ServiceRecord cur = smap.mServicesByName.get(r.name);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 63f122b..0480b19 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -273,6 +273,10 @@
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
+import static android.os.Process.PROC_CHAR;
+import static android.os.Process.PROC_OUT_LONG;
+import static android.os.Process.PROC_PARENS;
+import static android.os.Process.PROC_SPACE_TERM;
 import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
 import static android.provider.Settings.Global.DEBUG_APP;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
@@ -2292,11 +2296,8 @@
                 final ActivityRecord r = (ActivityRecord) msg.obj;
                 final boolean needsVrMode = r != null && r.requestedVrComponent != null;
                 if (needsVrMode) {
-                    VrManagerInternal vrService =
-                            LocalServices.getService(VrManagerInternal.class);
-                    boolean enable = msg.arg1 == 1;
-                    vrService.setVrMode(enable, r.requestedVrComponent, r.userId,
-                            r.info.getComponentName());
+                    applyVrMode(msg.arg1 == 1, r.requestedVrComponent, r.userId,
+                            r.info.getComponentName(), false);
                 }
             } break;
             }
@@ -3084,6 +3085,17 @@
                 mHandler.obtainMessage(VR_MODE_APPLY_IF_NEEDED_MSG, enable ? 1 : 0, 0, r));
     }
 
+    private void applyVrMode(boolean enabled, ComponentName packageName, int userId,
+            ComponentName callingPackage, boolean immediate) {
+        VrManagerInternal vrService =
+                LocalServices.getService(VrManagerInternal.class);
+        if (immediate) {
+            vrService.setVrModeImmediate(enabled, packageName, userId, callingPackage);
+        } else {
+            vrService.setVrMode(enabled, packageName, userId, callingPackage);
+        }
+    }
+
     final void showAskCompatModeDialogLocked(ActivityRecord r) {
         Message msg = Message.obtain();
         msg.what = SHOW_COMPAT_MODE_DIALOG_UI_MSG;
@@ -3484,13 +3496,11 @@
 
         // app launch boost for big.little configurations
         // use cpusets to migrate freshly launched tasks to big cores
-        synchronized(ActivityManagerService.this) {
-            nativeMigrateToBoost();
-            mIsBoosted = true;
-            mBoostStartTime = SystemClock.uptimeMillis();
-            Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
-            mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);
-        }
+        nativeMigrateToBoost();
+        mIsBoosted = true;
+        mBoostStartTime = SystemClock.uptimeMillis();
+        Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
+        mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);
 
         // We don't have to do anything more if:
         // (1) There is an existing application record; and
@@ -3503,7 +3513,7 @@
                 + " thread=" + (app != null ? app.thread : null)
                 + " pid=" + (app != null ? app.pid : -1));
         if (app != null && app.pid > 0) {
-            if (!knownToBeDead || app.thread == null) {
+            if ((!knownToBeDead && !app.killed) || app.thread == null) {
                 // We already have the app running, or are waiting for it to
                 // come up (we have a pid but not yet its thread), so keep it.
                 if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
@@ -6378,7 +6388,7 @@
         EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
 
         app.makeActive(thread, mProcessStats);
-        app.curAdj = app.setAdj = ProcessList.INVALID_ADJ;
+        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
         app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
         app.forcingToForeground = null;
         updateProcessForegroundLocked(app, false, false);
@@ -9226,9 +9236,6 @@
                         // sense, so turn off auto-remove.
                         intent.addFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
                     }
-                } else if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
-                    // Must be a new task.
-                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 }
                 if (!comp.equals(mLastAddedTaskComponent) || callingUid != mLastAddedTaskUid) {
                     mLastAddedTaskActivity = null;
@@ -10501,6 +10508,30 @@
         }
     }
 
+    private static final int[] PROCESS_STATE_STATS_FORMAT = new int[] {
+            PROC_SPACE_TERM,
+            PROC_SPACE_TERM|PROC_PARENS,
+            PROC_SPACE_TERM|PROC_CHAR|PROC_OUT_LONG,        // 3: process state
+    };
+
+    private final long[] mProcessStateStatsLongs = new long[1];
+
+    boolean isProcessAliveLocked(ProcessRecord proc) {
+        if (proc.procStatFile == null) {
+            proc.procStatFile = "/proc/" + proc.pid + "/stat";
+        }
+        mProcessStateStatsLongs[0] = 0;
+        if (!Process.readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
+                mProcessStateStatsLongs, null)) {
+            if (DEBUG_OOM_ADJ) Slog.d(TAG, "UNABLE TO RETRIEVE STATE FOR " + proc.procStatFile);
+            return false;
+        }
+        final long state = mProcessStateStatsLongs[0];
+        if (DEBUG_OOM_ADJ) Slog.d(TAG, "RETRIEVED STATE FOR " + proc.procStatFile + ": "
+                + (char)state);
+        return state != 'Z' && state != 'X' && state != 'x' && state != 'K';
+    }
+
     private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
             String name, IBinder token, boolean stable, int userId) {
         ContentProviderRecord cpr;
@@ -10545,7 +10576,7 @@
                 }
             }
 
-            boolean providerRunning = cpr != null;
+            boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
             if (providerRunning) {
                 cpi = cpr.info;
                 String msg;
@@ -10587,35 +10618,44 @@
                     }
                 }
 
-                if (cpr.proc != null) {
-                    checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
-                    boolean success = updateOomAdjLocked(cpr.proc);
-                    maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
-                    checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
-                    if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
-                    // NOTE: there is still a race here where a signal could be
-                    // pending on the process even though we managed to update its
-                    // adj level.  Not sure what to do about this, but at least
-                    // the race is now smaller.
-                    if (!success) {
-                        // Uh oh...  it looks like the provider's process
-                        // has been killed on us.  We need to wait for a new
-                        // process to be started, and make sure its death
-                        // doesn't kill our process.
-                        Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
-                                + " is crashing; detaching " + r);
-                        boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
-                        checkTime(startTime, "getContentProviderImpl: before appDied");
-                        appDiedLocked(cpr.proc);
-                        checkTime(startTime, "getContentProviderImpl: after appDied");
-                        if (!lastRef) {
-                            // This wasn't the last ref our process had on
-                            // the provider...  we have now been killed, bail.
-                            return null;
-                        }
-                        providerRunning = false;
-                        conn = null;
+                checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
+                final int verifiedAdj = cpr.proc.verifiedAdj;
+                boolean success = updateOomAdjLocked(cpr.proc);
+                // XXX things have changed so updateOomAdjLocked doesn't actually tell us
+                // if the process has been successfully adjusted.  So to reduce races with
+                // it, we will check whether the process still exists.  Note that this doesn't
+                // completely get rid of races with LMK killing the process, but should make
+                // them much smaller.
+                if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
+                    success = false;
+                }
+                maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
+                checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
+                if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
+                // NOTE: there is still a race here where a signal could be
+                // pending on the process even though we managed to update its
+                // adj level.  Not sure what to do about this, but at least
+                // the race is now smaller.
+                if (!success) {
+                    // Uh oh...  it looks like the provider's process
+                    // has been killed on us.  We need to wait for a new
+                    // process to be started, and make sure its death
+                    // doesn't kill our process.
+                    Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
+                            + " is crashing; detaching " + r);
+                    boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
+                    checkTime(startTime, "getContentProviderImpl: before appDied");
+                    appDiedLocked(cpr.proc);
+                    checkTime(startTime, "getContentProviderImpl: after appDied");
+                    if (!lastRef) {
+                        // This wasn't the last ref our process had on
+                        // the provider...  we have now been killed, bail.
+                        return null;
                     }
+                    providerRunning = false;
+                    conn = null;
+                } else {
+                    cpr.proc.verifiedAdj = cpr.proc.setAdj;
                 }
 
                 Binder.restoreCallingIdentity(origId);
@@ -10759,7 +10799,7 @@
                         checkTime(startTime, "getContentProviderImpl: looking for process record");
                         ProcessRecord proc = getProcessRecordLocked(
                                 cpi.processName, cpr.appInfo.uid, false);
-                        if (proc != null && proc.thread != null) {
+                        if (proc != null && proc.thread != null && !proc.killed) {
                             if (DEBUG_PROVIDER) Slog.d(TAG_PROVIDER,
                                     "Installing in existing process " + proc);
                             if (!proc.pubProviders.containsKey(cpi.name)) {
@@ -11468,11 +11508,15 @@
 
     // Actually is sleeping or shutting down or whatever else in the future
     // is an inactive state.
-    public boolean isSleepingOrShuttingDown() {
-        return isSleeping() || mShuttingDown;
+    boolean isSleepingOrShuttingDownLocked() {
+        return isSleepingLocked() || mShuttingDown;
     }
 
-    public boolean isSleeping() {
+    boolean isShuttingDownLocked() {
+        return mShuttingDown;
+    }
+
+    boolean isSleepingLocked() {
         return mSleeping;
     }
 
@@ -12842,7 +12886,7 @@
                     proc.notCachedSinceIdle = true;
                     proc.initialIdlePss = 0;
                     proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, true,
-                            mTestPssMode, isSleeping(), now);
+                            mTestPssMode, isSleepingLocked(), now);
                 }
             }
 
@@ -16560,7 +16604,8 @@
                         && capp.pid != MY_PID) {
                     capp.kill("depends on provider "
                             + cpr.name.flattenToShortString()
-                            + " in dying proc " + (proc != null ? proc.processName : "??"), true);
+                            + " in dying proc " + (proc != null ? proc.processName : "??")
+                            + " (adj " + (proc != null ? proc.setAdj : "??") + ")", true);
                 }
             } else if (capp.thread != null && conn.provider.provider != null) {
                 try {
@@ -17033,11 +17078,22 @@
     // Cause the target app to be launched if necessary and its backup agent
     // instantiated.  The backup agent will invoke backupAgentCreated() on the
     // activity manager to announce its creation.
-    public boolean bindBackupAgent(ApplicationInfo app, int backupMode) {
-        if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
-                "bindBackupAgent: app=" + app + " mode=" + backupMode);
+    public boolean bindBackupAgent(String packageName, int backupMode, int userId) {
+        if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode);
         enforceCallingPermission("android.permission.CONFIRM_FULL_BACKUP", "bindBackupAgent");
 
+        IPackageManager pm = AppGlobals.getPackageManager();
+        ApplicationInfo app = null;
+        try {
+            app = pm.getApplicationInfo(packageName, 0, userId);
+        } catch (RemoteException e) {
+            // can't happen; package manager is process-local
+        }
+        if (app == null) {
+            Slog.w(TAG, "Unable to bind backup agent for " + packageName);
+            return false;
+        }
+
         synchronized(this) {
             // !!! TODO: currently no check here that we're already bound
             BatteryStatsImpl.Uid.Pkg.Serv ss = null;
@@ -17846,6 +17902,19 @@
                     // Apps should use JobScehduler to monitor for media provider changes.
                     Slog.w(TAG, action + " no longer allowed; dropping from "
                             + UserHandle.formatUid(callingUid));
+                    if (resultTo != null) {
+                        final BroadcastQueue queue = broadcastQueueForIntent(intent);
+                        try {
+                            queue.performReceiveLocked(callerApp, resultTo, intent,
+                                    Activity.RESULT_CANCELED, null, null,
+                                    false, false, userId);
+                        } catch (RemoteException e) {
+                            Slog.w(TAG, "Failure ["
+                                    + queue.mQueueName + "] sending broadcast result of "
+                                    + intent, e);
+
+                        }
+                    }
                     // Lie; we don't want to crash the app.
                     return ActivityManager.BROADCAST_SUCCESS;
             }
@@ -19739,7 +19808,7 @@
             if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
                 app.pssProcState = app.setProcState;
                 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
-                        mTestPssMode, isSleeping(), now);
+                        mTestPssMode, isSleepingLocked(), now);
                 mPendingPssProcesses.add(app);
             }
         }
@@ -19787,7 +19856,7 @@
             }
         }
         return !processingBroadcasts
-                && (isSleeping() || mStackSupervisor.allResumedActivitiesIdle());
+                && (isSleepingLocked() || mStackSupervisor.allResumedActivitiesIdle());
     }
 
     /**
@@ -19997,6 +20066,7 @@
                     "Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": "
                     + app.adjType);
             app.setAdj = app.curAdj;
+            app.verifiedAdj = ProcessList.INVALID_ADJ;
         }
 
         if (app.setSchedGroup != app.curSchedGroup) {
@@ -20078,7 +20148,7 @@
             }
             app.lastStateTime = now;
             app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
-                    mTestPssMode, isSleeping(), now);
+                    mTestPssMode, isSleepingLocked(), now);
             if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
                     + ProcessList.makeProcStateString(app.setProcState) + " to "
                     + ProcessList.makeProcStateString(app.curProcState) + " next pss in "
@@ -20089,7 +20159,7 @@
                     mTestPssMode)))) {
                 requestPssLocked(app, app.setProcState);
                 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
-                        mTestPssMode, isSleeping(), now);
+                        mTestPssMode, isSleepingLocked(), now);
             } else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
                     "Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
         }
@@ -20615,7 +20685,7 @@
         }
         mLastMemoryLevel = memFactor;
         mLastNumProcesses = mLruProcesses.size();
-        boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
+        boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now);
         final int trackerMemFactor = mProcessStats.getMemFactorLocked();
         if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
             if (mLowRamStartTime == 0) {
@@ -21420,11 +21490,25 @@
         public SleepToken acquireSleepToken(String tag) {
             Preconditions.checkNotNull(tag);
 
+            ComponentName requestedVrService = null;
+            ComponentName callingVrActivity = null;
+            int userId = -1;
+            synchronized (ActivityManagerService.this) {
+                if (mFocusedActivity != null) {
+                    requestedVrService = mFocusedActivity.requestedVrComponent;
+                    callingVrActivity = mFocusedActivity.info.getComponentName();
+                    userId = mFocusedActivity.userId;
+                }
+            }
+
+            if (requestedVrService != null) {
+                applyVrMode(false, requestedVrService, userId, callingVrActivity, true);
+            }
+
             synchronized (ActivityManagerService.this) {
                 SleepTokenImpl token = new SleepTokenImpl(tag);
                 mSleepTokens.add(token);
                 updateSleepIfNeededLocked();
-                applyVrModeIfNeededLocked(mFocusedActivity, false);
                 return token;
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 3ccac9e..6510cb4 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -444,10 +444,17 @@
             return;
         }
         try {
+            // Make sure fontScale is always equal to global. For fullscreen apps, config is
+            // the shared EMPTY config, which has default fontScale of 1.0. We don't want it
+            // to be applied as an override config.
+            Configuration overrideConfig = new Configuration(config);
+            overrideConfig.fontScale = service.mConfiguration.fontScale;
+
             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + " " +
-                    "reportToActivity=" + reportToActivity + " and config: " + config);
+                    "reportToActivity=" + reportToActivity + " and config: " + overrideConfig);
+
             app.thread.scheduleActivityConfigurationChanged(
-                    appToken, new Configuration(config), reportToActivity);
+                    appToken, overrideConfig, reportToActivity);
         } catch (RemoteException e) {
             // If process died, whatever.
         }
@@ -931,7 +938,7 @@
         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
         boolean unsent = true;
         if ((state == ActivityState.RESUMED
-                || (service.isSleeping() && task.stack != null
+                || (service.isSleepingLocked() && task.stack != null
                     && task.stack.topRunningActivityLocked() == this))
                 && app != null && app.thread != null) {
             try {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d83a750..d55dcd0 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -825,7 +825,8 @@
      * is the same as the given activity.  Returns null if no such activity
      * is found.
      */
-    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
+    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
+                                      boolean compareIntentFilters) {
         ComponentName cls = intent.getComponent();
         if (info.targetActivity != null) {
             cls = new ComponentName(info.packageName, info.targetActivity);
@@ -843,8 +844,16 @@
                 if (notCurrentUserTask && (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) == 0) {
                     continue;
                 }
-                if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) {
-                    return r;
+                if (!r.finishing && r.userId == userId) {
+                    if (compareIntentFilters) {
+                        if (r.intent.filterEquals(intent)) {
+                            return r;
+                        }
+                    } else {
+                        if (r.intent.getComponent().equals(cls)) {
+                            return r;
+                        }
+                    }
                 }
             }
         }
@@ -1075,7 +1084,7 @@
         if (mPausingActivity != null) {
             Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
                     + " state=" + mPausingActivity.state);
-            if (!mService.isSleeping()) {
+            if (!mService.isSleepingLocked()) {
                 // Avoid recursion among check for sleep and complete pause during sleeping.
                 // Because activity will be paused immediately after resume, just let pause
                 // be completed by the order of activity paused from clients.
@@ -1139,7 +1148,7 @@
 
         // If we are not going to sleep, we want to ensure the device is
         // awake until the next activity is started.
-        if (!uiSleeping && !mService.isSleepingOrShuttingDown()) {
+        if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
             mStackSupervisor.acquireLaunchWakelock();
         }
 
@@ -1292,7 +1301,7 @@
                     // We don't need to schedule another stop, we only need to let it happen.
                     prev.state = ActivityState.STOPPING;
                 } else if ((!prev.visible && !hasVisibleBehindActivity())
-                        || mService.isSleepingOrShuttingDown()) {
+                        || mService.isSleepingOrShuttingDownLocked()) {
                     // If we were visible then resumeTopActivities will release resources before
                     // stopping.
                     addToStopping(prev, true /* immediate */);
@@ -1310,7 +1319,7 @@
 
         if (resumeNext) {
             final ActivityStack topStack = mStackSupervisor.getFocusedStack();
-            if (!mService.isSleepingOrShuttingDown()) {
+            if (!mService.isSleepingOrShuttingDownLocked()) {
                 mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
             } else {
                 mStackSupervisor.checkReadyForSleepLocked();
@@ -2195,7 +2204,7 @@
 
         // If we are sleeping, and there is no resumed activity, and the top
         // activity is paused, well that is the state we want.
-        if (mService.isSleepingOrShuttingDown()
+        if (mService.isSleepingOrShuttingDownLocked()
                 && mLastPausedActivity == next
                 && mStackSupervisor.allPausedActivitiesComplete()) {
             // Make sure we have executed any pending transitions, since there
@@ -2277,7 +2286,7 @@
         // If the most recent activity was noHistory but was only stopped rather
         // than stopped+finished because the device went to sleep, we need to make
         // sure to finish it as we're making a new activity topmost.
-        if (mService.isSleeping() && mLastNoHistoryActivity != null &&
+        if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&
                 !mLastNoHistoryActivity.finishing) {
             if (DEBUG_STATES) Slog.d(TAG_STATES,
                     "no-history finish of " + mLastNoHistoryActivity + " on new resume");
@@ -3211,7 +3220,7 @@
         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
             if (!r.finishing) {
-                if (!mService.isSleeping()) {
+                if (!mService.isSleepingLocked()) {
                     if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r);
                     if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
                             "stop-no-history", false)) {
@@ -3243,7 +3252,7 @@
                 EventLogTags.writeAmStopActivity(
                         r.userId, System.identityHashCode(r), r.shortComponentName);
                 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
-                if (mService.isSleepingOrShuttingDown()) {
+                if (mService.isSleepingOrShuttingDownLocked()) {
                     r.setSleeping(true);
                 }
                 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
@@ -4447,7 +4456,7 @@
             }
         }
         if (updatedConfig) {
-            // Ensure the resumed state of the focus activity if we updated the confiugaration of
+            // Ensure the resumed state of the focus activity if we updated the configuration of
             // any activity.
             mStackSupervisor.resumeFocusedStackTopActivityLocked();
         }
@@ -4467,6 +4476,15 @@
             return true;
         }
 
+        // TODO: We could probably make the condition below just check that the activity state is
+        // stopped, but also checking the sleep state for now to reduce change impact late in
+        // development cycle.
+        if (mService.isSleepingOrShuttingDownLocked() && r.state == ActivityState.STOPPED) {
+            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+                    "Skipping config check (stopped while sleeping): " + r);
+            return true;
+        }
+
         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                 "Ensuring correct configuration: " + r);
 
@@ -5177,7 +5195,8 @@
                 r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                 (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, r.info.configChanges,
                 task.voiceSession != null, r.mLaunchTaskBehind, bounds, task.mOverrideConfig,
-                task.mResizeMode, r.isAlwaysFocusable(), task.isHomeTask());
+                task.mResizeMode, r.isAlwaysFocusable(), task.isHomeTask(),
+                r.appInfo.targetSdkVersion);
         r.taskConfigOverride = task.mOverrideConfig;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f78fa8d..aaeaa7e 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2620,11 +2620,13 @@
         return mTmpFindTaskResult.r;
     }
 
-    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
+    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
+                                      boolean compareIntentFilters) {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info);
+                final ActivityRecord ar = stacks.get(stackNdx)
+                        .findActivityLocked(intent, info, compareIntentFilters);
                 if (ar != null) {
                     return ar;
                 }
@@ -2709,7 +2711,7 @@
     }
 
     void checkReadyForSleepLocked() {
-        if (!mService.isSleepingOrShuttingDown()) {
+        if (!mService.isSleepingOrShuttingDownLocked()) {
             // Do not care.
             return;
         }
@@ -3052,7 +3054,7 @@
                     mWindowManager.setAppVisibility(s.appToken, false);
                 }
             }
-            if ((!waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
+            if ((!waitingVisible || mService.isSleepingOrShuttingDownLocked()) && remove) {
                 if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s);
                 if (stops == null) {
                     stops = new ArrayList<>();
@@ -3776,7 +3778,7 @@
                 } break;
                 case SLEEP_TIMEOUT_MSG: {
                     synchronized (mService) {
-                        if (mService.isSleepingOrShuttingDown()) {
+                        if (mService.isSleepingOrShuttingDownLocked()) {
                             Slog.w(TAG, "Sleep timeout!  Sleeping now.");
                             mSleepTimeout = true;
                             checkReadyForSleepLocked();
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index a2c2040..f26e47e 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -186,9 +186,13 @@
         if (mActivityOptions == null) {
             mActivityOptions = ActivityOptions.makeBasic();
         }
-        // Showing credential confirmation activity in home task to avoid stopping multi-windowed
-        // mode after showing the full-screen credential confirmation activity.
-        mActivityOptions.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
+
+        ActivityRecord homeActivityRecord = mSupervisor.getHomeActivity();
+        if (homeActivityRecord != null && homeActivityRecord.task != null) {
+            // Showing credential confirmation activity in home task to avoid stopping multi-windowed
+            // mode after showing the full-screen credential confirmation activity.
+            mActivityOptions.setLaunchTaskId(homeActivityRecord.task.taskId);
+        }
 
         final UserInfo parent = mUserManager.getProfileParent(mUserId);
         mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, parent.id);
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 793f411..7ef7dfb 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1438,11 +1438,11 @@
             if (mLaunchSingleInstance) {
                 // There can be one and only one instance of single instance activity in the
                 // history, and it is always in its own unique task, so we do a special search.
-               intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info);
+               intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
             } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
                 // For the launch adjacent case we only want to put the activity in an existing
                 // task if the activity already exists in the history.
-                intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info);
+                intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, true);
             } else {
                 // Otherwise find the best task to put the activity in.
                 intentActivity = mSupervisor.findTaskLocked(mStartActivity);
@@ -1494,14 +1494,23 @@
                                 intentActivity.task, mNoAnimation, mOptions,
                                 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
                         mMovedToFront = true;
-                    } else if ((launchStack.mStackId == DOCKED_STACK_ID
-                            || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID)
-                            && (mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
-                        // If we want to launch adjacent and mTargetStack is not the computed
-                        // launch stack - move task to top of computed stack.
-                        mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
-                                launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
-                                ANIMATE);
+                    } else if (launchStack.mStackId == DOCKED_STACK_ID
+                            || launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
+                        if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
+                            // If we want to launch adjacent and mTargetStack is not the computed
+                            // launch stack - move task to top of computed stack.
+                            mSupervisor.moveTaskToStackLocked(intentActivity.task.taskId,
+                                    launchStack.mStackId, ON_TOP, FORCE_FOCUS, "launchToSide",
+                                    ANIMATE);
+                        } else {
+                            // TODO: This should be reevaluated in MW v2.
+                            // We choose to move task to front instead of launching it adjacent
+                            // when specific stack was requested explicitly and it appeared to be
+                            // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
+                            mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation,
+                                    mOptions, mStartActivity.appTimeTracker,
+                                    "bringToFrontInsteadOfAdjacentLaunch");
+                        }
                         mMovedToFront = true;
                     }
                     mOptions = null;
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 88645c1e..a279290 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -456,7 +456,7 @@
         }
     }
 
-    private void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
+    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
             Intent intent, int resultCode, String data, Bundle extras,
             boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
         // Send the intent to the receiver asynchronously using one-way binder calls.
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 691fd2a..8911a3e 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -75,6 +75,7 @@
     ProcessState baseProcessTracker;
     BatteryStatsImpl.Uid.Proc curProcBatteryStats;
     int pid;                    // The process of this application; 0 if none
+    String procStatFile;        // path to /proc/<pid>/stat
     int[] gids;                 // The gids this process was launched with
     String requiredAbi;         // The ABI this process was launched with
     String instructionSet;      // The instruction set this process was launched with
@@ -93,6 +94,7 @@
     int setRawAdj;              // Last set OOM unlimited adjustment for this process
     int curAdj;                 // Current OOM adjustment for this process
     int setAdj;                 // Last set OOM adjustment for this process
+    int verifiedAdj;            // The last adjustment that was verified as actually being set
     int curSchedGroup;          // Currently desired scheduling class
     int setSchedGroup;          // Last set to background scheduling class
     int trimMemoryLevel;        // Last selected memory trimming level
@@ -441,7 +443,7 @@
         pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode));
         maxAdj = ProcessList.UNKNOWN_ADJ;
         curRawAdj = setRawAdj = ProcessList.INVALID_ADJ;
-        curAdj = setAdj = ProcessList.INVALID_ADJ;
+        curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;
         persistent = false;
         removed = false;
         lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
@@ -449,6 +451,7 @@
 
     public void setPid(int _pid) {
         pid = _pid;
+        procStatFile = null;
         shortStringName = null;
         stringName = null;
     }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index ebacc71..ede3bda 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -259,28 +259,39 @@
      *
      * @param packageName the package to designate as always-on VPN supplier.
      * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
+     * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
      */
     public synchronized boolean setAlwaysOnPackage(String packageName, boolean lockdown) {
         enforceControlPermissionOrInternalCaller();
+        if (VpnConfig.LEGACY_VPN.equals(packageName)) {
+            Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
+            return false;
+        }
 
-        // Disconnect current VPN.
-        prepareInternal(VpnConfig.LEGACY_VPN);
-
-        // Pre-authorize new always-on VPN package.
         if (packageName != null) {
+            // Pre-authorize new always-on VPN package.
             if (!setPackageAuthorization(packageName, true)) {
                 return false;
             }
-            prepareInternal(packageName);
+            mAlwaysOn = true;
+        } else {
+            packageName = VpnConfig.LEGACY_VPN;
+            mAlwaysOn = false;
         }
 
-        mAlwaysOn = (packageName != null);
         mLockdown = (mAlwaysOn && lockdown);
+        if (!isCurrentPreparedPackage(packageName)) {
+            prepareInternal(packageName);
+        }
         maybeRegisterPackageChangeReceiverLocked(packageName);
         setVpnForcedLocked(mLockdown);
         return true;
     }
 
+    private static boolean isNullOrLegacyVpn(String packageName) {
+        return packageName == null || VpnConfig.LEGACY_VPN.equals(packageName);
+    }
+
     private void unregisterPackageChangeReceiverLocked() {
         // register previous intent filter
         if (mIsPackageIntentReceiverRegistered) {
@@ -293,7 +304,7 @@
         // Unregister IntentFilter listening for previous always-on package change
         unregisterPackageChangeReceiverLocked();
 
-        if (packageName != null) {
+        if (!isNullOrLegacyVpn(packageName)) {
             mIsPackageIntentReceiverRegistered = true;
 
             IntentFilter intentFilter = new IntentFilter();
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 9220aa3..01b2393 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -394,18 +394,9 @@
             for (int i=0; i<numCalls; i++) {
                 ObserverCall oc = calls.get(i);
                 try {
-                    // If the uri does not belong to the same user as the observer: we must add
-                    // the userId to the uri. Otherewise the observer would think the uri belongs
-                    // to his user.
-                    final Uri tempUri;
-                    if (oc.mObserverUserId != userHandle) {
-                        tempUri = ContentProvider.maybeAddUserId(uri, userHandle);
-                    } else {
-                        tempUri = uri;
-                    }
-                    oc.mObserver.onChange(oc.mSelfChange, tempUri, userHandle);
+                    oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
                     if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
-                            + tempUri);
+                            + uri);
                 } catch (RemoteException ex) {
                     synchronized (mRootNode) {
                         Log.w(TAG, "Found dead observer, removing");
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 493fc4a..39ddc3a 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1355,7 +1355,11 @@
             operation.extras.remove(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF);
         }
 
-        if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)) {
+        if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
+                && !syncResult.syncAlreadyInProgress) {
+            // syncAlreadyInProgress flag is set by AbstractThreadedSyncAdapter. The sync adapter
+            // has no way of knowing that a sync error occured. So we DO retry if the error is
+            // syncAlreadyInProgress.
             if (isLoggable) {
                 Log.d(TAG, "not retrying sync operation because SYNC_EXTRAS_DO_NOT_RETRY was specified "
                         + operation);
@@ -2445,6 +2449,10 @@
             if (op.isPeriodic) {
                 scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
             } else {
+                // mSyncJobService.callJobFinished is async, so cancel the job to ensure we don't
+                // find the this job in the pending jobs list while looking for duplicates
+                // before scheduling it at a later time.
+                getJobScheduler().cancel(op.jobId);
                 scheduleSyncOperationH(op, delay);
             }
         }
@@ -2886,6 +2894,14 @@
             String historyMessage;
             int downstreamActivity;
             int upstreamActivity;
+
+            if (!syncOperation.isPeriodic) {
+                // mSyncJobService.jobFinidhed is async, we need to ensure that this job is
+                // removed from JobScheduler's pending jobs list before moving forward and
+                // potentially rescheduling all pending jobs to respect new backoff values.
+                getJobScheduler().cancel(syncOperation.jobId);
+            }
+
             if (syncResult != null) {
                 if (isLoggable) {
                     Slog.v(TAG, "runSyncFinishedOrCanceled [finished]: "
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 1f6616e..a783fa2 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -20,6 +20,7 @@
 
 import com.android.internal.util.DumpUtils;
 import com.android.server.FgThread;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
 import android.Manifest;
@@ -32,6 +33,8 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ServiceInfo;
+import android.database.ContentObserver;
+import android.hardware.input.InputManagerInternal;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
@@ -111,11 +114,16 @@
             mContext.registerReceiver(new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
+                    writePulseGestureEnabled();
                     synchronized (mLock) {
                         stopDreamLocked(false /*immediate*/);
                     }
                 }
             }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.DOZE_ENABLED), false,
+                    mDozeEnabledObserver, UserHandle.USER_ALL);
+            writePulseGestureEnabled();
         }
     }
 
@@ -414,6 +422,12 @@
         }
     }
 
+    private void writePulseGestureEnabled() {
+        ComponentName name = getDozeComponent();
+        boolean dozeEnabled = validateDream(name);
+        LocalServices.getService(InputManagerInternal.class).setPulseGestureEnabled(dozeEnabled);
+    }
+
     private static String componentsToString(ComponentName[] componentNames) {
         StringBuilder names = new StringBuilder();
         if (componentNames != null) {
@@ -450,6 +464,13 @@
         }
     };
 
+    private final ContentObserver mDozeEnabledObserver = new ContentObserver(null) {
+        @Override
+        public void onChange(boolean selfChange) {
+            writePulseGestureEnabled();
+        }
+    };
+
     /**
      * Handler for asynchronous operations performed by the dream manager.
      * Ensures operations to {@link DreamController} are single-threaded.
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index aa1d73f..74095ac 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -18,7 +18,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Build;
 import android.os.LocaleList;
+import android.util.Log;
 import android.view.Display;
 import com.android.internal.inputmethod.InputMethodSubtypeHandle;
 import com.android.internal.os.SomeArgs;
@@ -98,8 +100,11 @@
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -109,6 +114,7 @@
 import java.util.List;
 import java.util.Locale;
 
+import libcore.io.IoUtils;
 import libcore.io.Streams;
 import libcore.util.Objects;
 
@@ -136,6 +142,8 @@
     private final Context mContext;
     private final InputManagerHandler mHandler;
 
+    private final File mDoubleTouchGestureEnableFile;
+
     private WindowManagerCallbacks mWindowManagerCallbacks;
     private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
     private boolean mSystemReady;
@@ -301,6 +309,11 @@
                 + mUseDevInputEventForAudioJack);
         mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
 
+        String doubleTouchGestureEnablePath = context.getResources().getString(
+                R.string.config_doubleTouchGestureEnableFile);
+        mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
+            new File(doubleTouchGestureEnablePath);
+
         LocalServices.addService(InputManagerInternal.class, new LocalService());
     }
 
@@ -2279,5 +2292,20 @@
         public void toggleCapsLock(int deviceId) {
             nativeToggleCapsLock(mPtr, deviceId);
         }
+
+        @Override
+        public void setPulseGestureEnabled(boolean enabled) {
+            if (mDoubleTouchGestureEnableFile != null) {
+                FileWriter writer = null;
+                try {
+                    writer = new FileWriter(mDoubleTouchGestureEnableFile);
+                    writer.write(enabled ? "1" : "0");
+                } catch (IOException e) {
+                    Log.wtf(TAG, "Unable to setPulseGestureEnabled", e);
+                } finally {
+                    IoUtils.closeQuietly(writer);
+                }
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 27b3aa2..8589de1 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -692,8 +692,13 @@
         boolean active = mPendingJobs.size() > 0;
         if (mPendingJobs.size() <= 0) {
             for (int i=0; i<mActiveServices.size(); i++) {
-                JobServiceContext jsc = mActiveServices.get(i);
-                if (jsc.getRunningJob() != null) {
+                final JobServiceContext jsc = mActiveServices.get(i);
+                final JobStatus job = jsc.getRunningJob();
+                if (job != null
+                        && (job.getJob().getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) == 0
+                        && !job.dozeWhitelisted) {
+                    // We will report active if we have a job running and it is not an exception
+                    // due to being in the foreground or whitelisted.
                     active = true;
                     break;
                 }
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index a23af35..2dbecbd 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -142,8 +142,11 @@
                 UserHandle.formatUid(pw, jobStatus.getSourceUid());
                 pw.print(": ");
                 pw.print(jobStatus.getSourcePackageName());
-                pw.print(", runnable=");
-                pw.println((jobStatus.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0);
+                if ((jobStatus.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0) {
+                    pw.println(" RUNNABLE");
+                } else {
+                    pw.println(" WAITING");
+                }
             }
         });
     }
diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index bf1297f..f7706d7 100644
--- a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -157,8 +157,9 @@
     }
 
     private void updateTaskStateLocked(JobStatus task) {
-        boolean enableTask = !mDeviceIdleMode || isWhitelistedLocked(task);
-        task.setDeviceNotDozingConstraintSatisfied(enableTask);
+        final boolean whitelisted = isWhitelistedLocked(task);
+        final boolean enableTask = !mDeviceIdleMode || whitelisted;
+        task.setDeviceNotDozingConstraintSatisfied(enableTask, whitelisted);
     }
 
     @Override
@@ -186,9 +187,13 @@
                 UserHandle.formatUid(pw, jobStatus.getSourceUid());
                 pw.print(": ");
                 pw.print(jobStatus.getSourcePackageName());
-                pw.print(", runnable=");
-                pw.println((jobStatus.satisfiedConstraints
-                        & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0);
+                pw.print((jobStatus.satisfiedConstraints
+                        & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0
+                                ? " RUNNABLE" : " WAITING");
+                if (jobStatus.dozeWhitelisted) {
+                    pw.print(" WHITELISTED");
+                }
+                pw.println();
             }
         });
     }
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index ded7a2f..552c990 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -103,6 +103,9 @@
     final int requiredConstraints;
     int satisfiedConstraints = 0;
 
+    // Set to true if doze constraint was satisfied due to app being whitelisted.
+    public boolean dozeWhitelisted;
+
     // These are filled in by controllers when preparing for execution.
     public ArraySet<Uri> changedUris;
     public ArraySet<String> changedAuthorities;
@@ -403,7 +406,8 @@
         return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
     }
 
-    boolean setDeviceNotDozingConstraintSatisfied(boolean state) {
+    boolean setDeviceNotDozingConstraintSatisfied(boolean state, boolean whitelisted) {
+        dozeWhitelisted = whitelisted;
         return setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state);
     }
 
@@ -651,6 +655,9 @@
             pw.print(prefix); pw.print("Unsatisfied constraints:");
             dumpConstraints(pw, (requiredConstraints & ~satisfiedConstraints));
             pw.println();
+            if (dozeWhitelisted) {
+                pw.print(prefix); pw.println("Doze whitelisted: true");
+            }
         }
         if (changedAuthorities != null) {
             pw.print(prefix); pw.println("Changed authorities:");
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 6b916be..2fc14ec 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1192,7 +1192,7 @@
         }
 
         if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
-        if (mProviderRequest.reportLocation && !mDisableGps) {
+        if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
             // update client uids
             updateClientUids(mWorkSource);
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 67cd7c3..e396b77 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -89,6 +89,7 @@
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
@@ -162,6 +163,7 @@
 import android.util.Xml;
 
 import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.util.ArrayUtils;
@@ -187,6 +189,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -199,6 +203,26 @@
  * Derives active rules by combining a given policy with other system status,
  * and delivers to listeners, such as {@link ConnectivityManager}, for
  * enforcement.
+ *
+ * <p>
+ * This class uses 2-3 locks to synchronize state:
+ * <ul>
+ * <li>{@code mUidRulesFirstLock}: used to guard state related to individual UIDs (such as firewall
+ * rules).
+ * <li>{@code mNetworkPoliciesSecondLock}: used to guard state related to network interfaces (such
+ * as network policies).
+ * <li>{@code allLocks}: not a "real" lock, but an indication (through @GuardedBy) that all locks
+ * must be held.
+ * </ul>
+ *
+ * <p>
+ * As such, methods that require synchronization have the following prefixes:
+ * <ul>
+ * <li>{@code UL()}: require the "UID" lock ({@code mUidRulesFirstLock}).
+ * <li>{@code NL()}: require the "Network" lock ({@code mNetworkPoliciesSecondLock}).
+ * <li>{@code AL()}: require all locks, which must be obtained in order ({@code mUidRulesFirstLock}
+ * first, then {@code mNetworkPoliciesSecondLock}, then {@code mYetAnotherGuardThirdLock}, etc..
+ * </ul>
  */
 public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     static final String TAG = "NetworkPolicy";
@@ -282,13 +306,16 @@
     private PowerManagerInternal mPowerManagerInternal;
     private IDeviceIdleController mDeviceIdleController;
 
-    final Object mRulesLock = new Object();
+    // See main javadoc for instructions on how to use these locks.
+    final Object mUidRulesFirstLock = new Object();
+    final Object mNetworkPoliciesSecondLock = new Object();
 
-    volatile boolean mSystemReady;
-    volatile boolean mScreenOn;
-    volatile boolean mRestrictBackground;
-    volatile boolean mRestrictPower;
-    volatile boolean mDeviceIdleMode;
+    @GuardedBy("allLocks") volatile boolean mSystemReady;
+
+    @GuardedBy("mUidRulesFirstLock") volatile boolean mScreenOn;
+    @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground;
+    @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictPower;
+    @GuardedBy("mUidRulesFirstLock") volatile boolean mDeviceIdleMode;
 
     private final boolean mSuppressDefaultPolicy;
 
@@ -298,15 +325,19 @@
     final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>();
 
     /** Defined UID policies. */
-    final SparseIntArray mUidPolicy = new SparseIntArray();
+    @GuardedBy("mUidRulesFirstLock") final SparseIntArray mUidPolicy = new SparseIntArray();
     /** Currently derived rules for each UID. */
-    final SparseIntArray mUidRules = new SparseIntArray();
+    @GuardedBy("mUidRulesFirstLock") final SparseIntArray mUidRules = new SparseIntArray();
 
+    @GuardedBy("mUidRulesFirstLock")
     final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
+    @GuardedBy("mUidRulesFirstLock")
     final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+    @GuardedBy("mUidRulesFirstLock")
     final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
 
     /** Set of states for the child firewall chains. True if the chain is active. */
+    @GuardedBy("mUidRulesFirstLock")
     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
 
     /**
@@ -314,6 +345,7 @@
      * in power save mode, except device idle (doze) still applies.
      * TODO: An int array might be sufficient
      */
+    @GuardedBy("mUidRulesFirstLock")
     private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
 
     /**
@@ -321,18 +353,22 @@
      * in power save mode.
      * TODO: An int array might be sufficient
      */
+    @GuardedBy("mUidRulesFirstLock")
     private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
 
+    @GuardedBy("mUidRulesFirstLock")
     private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
 
     /**
      * UIDs that have been white-listed to avoid restricted background.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private final SparseBooleanArray mRestrictBackgroundWhitelistUids = new SparseBooleanArray();
 
     /**
      * UIDs that have been initially white-listed by system to avoid restricted background.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private final SparseBooleanArray mDefaultRestrictBackgroundWhitelistUids =
             new SparseBooleanArray();
 
@@ -340,18 +376,23 @@
      * UIDs that have been initially white-listed by system to avoid restricted background,
      * but later revoked by user.
      */
+    @GuardedBy("mUidRulesFirstLock")
     private final SparseBooleanArray mRestrictBackgroundWhitelistRevokedUids =
             new SparseBooleanArray();
 
     /** Set of ifaces that are metered. */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private ArraySet<String> mMeteredIfaces = new ArraySet<>();
     /** Set of over-limit templates that have been notified. */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<>();
 
     /** Set of currently active {@link Notification} tags. */
+    @GuardedBy("mNetworkPoliciesSecondLock")
     private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
 
     /** Foreground at UID granularity. */
+    @GuardedBy("mUidRulesFirstLock")
     final SparseIntArray mUidState = new SparseIntArray();
 
     /** Higher priority listener before general event dispatch */
@@ -362,6 +403,7 @@
 
     final Handler mHandler;
 
+    @GuardedBy("allLocks")
     private final AtomicFile mPolicyFile;
 
     private final AppOpsManager mAppOps;
@@ -426,7 +468,7 @@
         mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
     }
 
-    void updatePowerSaveWhitelistLocked() {
+    void updatePowerSaveWhitelistUL() {
         try {
             int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle();
             mPowerSaveWhitelistExceptIdleAppIds.clear();
@@ -452,19 +494,19 @@
      *
      * @return whether any uid has been added to {@link #mRestrictBackgroundWhitelistUids}.
      */
-    boolean addDefaultRestrictBackgroundWhitelistUidsLocked() {
+    boolean addDefaultRestrictBackgroundWhitelistUidsUL() {
         final List<UserInfo> users = mUserManager.getUsers();
         final int numberUsers = users.size();
 
         boolean changed = false;
         for (int i = 0; i < numberUsers; i++) {
             final UserInfo user = users.get(i);
-            changed = addDefaultRestrictBackgroundWhitelistUidsLocked(user.id) || changed;
+            changed = addDefaultRestrictBackgroundWhitelistUidsUL(user.id) || changed;
         }
         return changed;
     }
 
-    private boolean addDefaultRestrictBackgroundWhitelistUidsLocked(int userId) {
+    private boolean addDefaultRestrictBackgroundWhitelistUidsUL(int userId) {
         final SystemConfig sysConfig = SystemConfig.getInstance();
         final PackageManager pm = mContext.getPackageManager();
         final ArraySet<String> allowDataUsage = sysConfig.getAllowInDataUsageSave();
@@ -502,7 +544,7 @@
         return changed;
     }
 
-    void updatePowerSaveTempWhitelistLocked() {
+    void updatePowerSaveTempWhitelistUL() {
         try {
             // Clear the states of the current whitelist
             final int N = mPowerSaveTempWhitelistAppIds.size();
@@ -523,7 +565,7 @@
     /**
      * Remove unnecessary entries in the temp whitelist
      */
-    void purgePowerSaveTempWhitelistLocked() {
+    void purgePowerSaveTempWhitelistUL() {
         final int N = mPowerSaveTempWhitelistAppIds.size();
         for (int i = N - 1; i >= 0; i--) {
             if (mPowerSaveTempWhitelistAppIds.valueAt(i) == false) {
@@ -542,36 +584,38 @@
 
         mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
 
-        synchronized (mRulesLock) {
-            updatePowerSaveWhitelistLocked();
-            mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
-            mPowerManagerInternal.registerLowPowerModeObserver(
-                    new PowerManagerInternal.LowPowerModeListener() {
-                @Override
-                public void onLowPowerModeChanged(boolean enabled) {
-                    if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
-                    synchronized (mRulesLock) {
-                        if (mRestrictPower != enabled) {
-                            mRestrictPower = enabled;
-                            updateRulesForRestrictPowerLocked();
-                            updateRulesForGlobalChangeLocked(true);
+        synchronized (mUidRulesFirstLock) {
+            synchronized (mNetworkPoliciesSecondLock) {
+                updatePowerSaveWhitelistUL();
+                mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
+                mPowerManagerInternal.registerLowPowerModeObserver(
+                        new PowerManagerInternal.LowPowerModeListener() {
+                    @Override
+                    public void onLowPowerModeChanged(boolean enabled) {
+                        if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
+                        synchronized (mUidRulesFirstLock) {
+                            if (mRestrictPower != enabled) {
+                                mRestrictPower = enabled;
+                                updateRulesForRestrictPowerUL();
+                            }
                         }
                     }
+                });
+                mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
+
+                mSystemReady = true;
+
+                // read policy from disk
+                readPolicyAL();
+
+                if (addDefaultRestrictBackgroundWhitelistUidsUL()) {
+                    writePolicyAL();
                 }
-            });
-            mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
 
-            mSystemReady = true;
-
-            // read policy from disk
-            readPolicyLocked();
-
-            if (addDefaultRestrictBackgroundWhitelistUidsLocked()) {
-                writePolicyLocked();
+                setRestrictBackgroundUL(mRestrictBackground);
+                updateRulesForGlobalChangeAL(false);
+                updateNotificationsNL();
             }
-
-            updateRulesForGlobalChangeLocked(false);
-            updateNotificationsLocked();
         }
 
         updateScreenOn();
@@ -650,14 +694,14 @@
 
     final private IUidObserver mUidObserver = new IUidObserver.Stub() {
         @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
-            synchronized (mRulesLock) {
-                updateUidStateLocked(uid, procState);
+            synchronized (mUidRulesFirstLock) {
+                updateUidStateUL(uid, procState);
             }
         }
 
         @Override public void onUidGone(int uid) throws RemoteException {
-            synchronized (mRulesLock) {
-                removeUidStateLocked(uid);
+            synchronized (mUidRulesFirstLock) {
+                removeUidStateUL(uid);
             }
         }
 
@@ -672,9 +716,9 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
-            synchronized (mRulesLock) {
-                updatePowerSaveWhitelistLocked();
-                updateRulesForGlobalChangeLocked(false);
+            synchronized (mUidRulesFirstLock) {
+                updatePowerSaveWhitelistUL();
+                updateRulesForRestrictPowerUL();
             }
         }
     };
@@ -682,10 +726,10 @@
     final private Runnable mTempPowerSaveChangedCallback = new Runnable() {
         @Override
         public void run() {
-            synchronized (mRulesLock) {
-                updatePowerSaveTempWhitelistLocked();
-                updateRulesForTempWhitelistChangeLocked();
-                purgePowerSaveTempWhitelistLocked();
+            synchronized (mUidRulesFirstLock) {
+                updatePowerSaveTempWhitelistUL();
+                updateRulesForTempWhitelistChangeUL();
+                purgePowerSaveTempWhitelistUL();
             }
         }
     };
@@ -712,8 +756,8 @@
                 // update rules for UID, since it might be subject to
                 // global background data policy
                 if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
-                synchronized (mRulesLock) {
-                    updateRestrictionRulesForUidLocked(uid);
+                synchronized (mUidRulesFirstLock) {
+                    updateRestrictionRulesForUidUL(uid);
                 }
             }
         }
@@ -729,10 +773,12 @@
 
             // remove any policy and update rules to clean up
             if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
-            synchronized (mRulesLock) {
+            synchronized (mUidRulesFirstLock) {
                 mUidPolicy.delete(uid);
-                updateRestrictionRulesForUidLocked(uid);
-                writePolicyLocked();
+                updateRestrictionRulesForUidUL(uid);
+                synchronized (mNetworkPoliciesSecondLock) {
+                    writePolicyAL();
+                }
             }
         }
     };
@@ -750,16 +796,18 @@
             switch (action) {
                 case ACTION_USER_REMOVED:
                 case ACTION_USER_ADDED:
-                    synchronized (mRulesLock) {
+                    synchronized (mUidRulesFirstLock) {
                         // Remove any persistable state for the given user; both cleaning up after a
                         // USER_REMOVED, and one last sanity check during USER_ADDED
-                        removeUserStateLocked(userId, true);
+                        removeUserStateUL(userId, true);
                         if (action == ACTION_USER_ADDED) {
                             // Add apps that are whitelisted by default.
-                            addDefaultRestrictBackgroundWhitelistUidsLocked(userId);
+                            addDefaultRestrictBackgroundWhitelistUidsUL(userId);
                         }
                         // Update global restrict for that user
-                        updateRulesForGlobalChangeLocked(true);
+                        synchronized (mNetworkPoliciesSecondLock) {
+                            updateRulesForGlobalChangeAL(true);
+                        }
                     }
                     break;
             }
@@ -777,9 +825,9 @@
             // READ_NETWORK_USAGE_HISTORY permission above.
 
             maybeRefreshTrustedTime();
-            synchronized (mRulesLock) {
-                updateNetworkEnabledLocked();
-                updateNotificationsLocked();
+            synchronized (mNetworkPoliciesSecondLock) {
+                updateNetworkEnabledNL();
+                updateNotificationsNL();
             }
         }
     };
@@ -828,10 +876,12 @@
                         EXTRA_WIFI_CONFIGURATION);
                 if (config.SSID != null) {
                     final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(config.SSID);
-                    synchronized (mRulesLock) {
-                        if (mNetworkPolicy.containsKey(template)) {
-                            mNetworkPolicy.remove(template);
-                            writePolicyLocked();
+                    synchronized (mUidRulesFirstLock) {
+                        synchronized (mNetworkPoliciesSecondLock) {
+                            if (mNetworkPolicy.containsKey(template)) {
+                                mNetworkPolicy.remove(template);
+                                writePolicyAL();
+                            }
                         }
                     }
                 }
@@ -857,13 +907,13 @@
             final boolean meteredHint = info.getMeteredHint();
 
             final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(info.getSSID());
-            synchronized (mRulesLock) {
+            synchronized (mNetworkPoliciesSecondLock) {
                 NetworkPolicy policy = mNetworkPolicy.get(template);
                 if (policy == null && meteredHint) {
                     // policy doesn't exist, and AP is hinting that it's
                     // metered: create an inferred policy.
                     policy = newWifiPolicy(template, meteredHint);
-                    addNetworkPolicyLocked(policy);
+                    addNetworkPolicyNL(policy);
 
                 } else if (policy != null && policy.inferred) {
                     // policy exists, and was inferred: update its current
@@ -872,7 +922,7 @@
 
                     // since this is inferred for each wifi session, just update
                     // rules without persisting.
-                    updateNetworkRulesLocked();
+                    updateNetworkRulesNL();
                 }
             }
         }
@@ -904,8 +954,8 @@
      * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
      * to show visible notifications as needed.
      */
-    void updateNotificationsLocked() {
-        if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
+    void updateNotificationsNL() {
+        if (LOGV) Slog.v(TAG, "updateNotificationsNL()");
 
         // keep track of previously active notifications
         final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
@@ -931,11 +981,11 @@
                     enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
                 } else {
                     enqueueNotification(policy, TYPE_LIMIT, totalBytes);
-                    notifyOverLimitLocked(policy.template);
+                    notifyOverLimitNL(policy.template);
                 }
 
             } else {
-                notifyUnderLimitLocked(policy.template);
+                notifyUnderLimitNL(policy.template);
 
                 if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
                     enqueueNotification(policy, TYPE_WARNING, totalBytes);
@@ -983,14 +1033,14 @@
      * Notify that given {@link NetworkTemplate} is over
      * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
      */
-    private void notifyOverLimitLocked(NetworkTemplate template) {
+    private void notifyOverLimitNL(NetworkTemplate template) {
         if (!mOverLimitNotified.contains(template)) {
             mContext.startActivity(buildNetworkOverLimitIntent(template));
             mOverLimitNotified.add(template);
         }
     }
 
-    private void notifyUnderLimitLocked(NetworkTemplate template) {
+    private void notifyUnderLimitNL(NetworkTemplate template) {
         mOverLimitNotified.remove(template);
     }
 
@@ -1142,12 +1192,12 @@
             // permission above.
 
             maybeRefreshTrustedTime();
-            synchronized (mRulesLock) {
-                ensureActiveMobilePolicyLocked();
-                normalizePoliciesLocked();
-                updateNetworkEnabledLocked();
-                updateNetworkRulesLocked();
-                updateNotificationsLocked();
+            synchronized (mNetworkPoliciesSecondLock) {
+                ensureActiveMobilePolicyNL();
+                normalizePoliciesNL();
+                updateNetworkEnabledNL();
+                updateNetworkRulesNL();
+                updateNotificationsNL();
             }
         }
     };
@@ -1156,8 +1206,8 @@
      * Proactively control network data connections when they exceed
      * {@link NetworkPolicy#limitBytes}.
      */
-    void updateNetworkEnabledLocked() {
-        if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
+    void updateNetworkEnabledNL() {
+        if (LOGV) Slog.v(TAG, "updateNetworkEnabledNL()");
 
         // TODO: reset any policy-disabled networks when any policy is removed
         // completely, which is currently rare case.
@@ -1198,8 +1248,8 @@
      * {@link NetworkPolicy} that need to be enforced. When matches found, set
      * remaining quota based on usage cycle and historical stats.
      */
-    void updateNetworkRulesLocked() {
-        if (LOGV) Slog.v(TAG, "updateNetworkRulesLocked()");
+    void updateNetworkRulesNL() {
+        if (LOGV) Slog.v(TAG, "updateNetworkRulesNL()");
 
         final NetworkState[] states;
         try {
@@ -1349,8 +1399,8 @@
      * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
      * have at least a default mobile policy defined.
      */
-    private void ensureActiveMobilePolicyLocked() {
-        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
+    private void ensureActiveMobilePolicyNL() {
+        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyNL()");
         if (mSuppressDefaultPolicy) return;
 
         final TelephonyManager tele = TelephonyManager.from(mContext);
@@ -1359,11 +1409,11 @@
         final int[] subIds = sub.getActiveSubscriptionIdList();
         for (int subId : subIds) {
             final String subscriberId = tele.getSubscriberId(subId);
-            ensureActiveMobilePolicyLocked(subscriberId);
+            ensureActiveMobilePolicyNL(subscriberId);
         }
     }
 
-    private void ensureActiveMobilePolicyLocked(String subscriberId) {
+    private void ensureActiveMobilePolicyNL(String subscriberId) {
         // Poke around to see if we already have a policy
         final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
                 TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
@@ -1394,11 +1444,11 @@
         final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
         final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
                 warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
-        addNetworkPolicyLocked(policy);
+        addNetworkPolicyNL(policy);
     }
 
-    private void readPolicyLocked() {
-        if (LOGV) Slog.v(TAG, "readPolicyLocked()");
+    private void readPolicyAL() {
+        if (LOGV) Slog.v(TAG, "readPolicyAL()");
 
         // clear any existing policy and read from disk
         mNetworkPolicy.clear();
@@ -1498,7 +1548,7 @@
                         final int policy = readIntAttribute(in, ATTR_POLICY);
 
                         if (UserHandle.isApp(uid)) {
-                            setUidPolicyUncheckedLocked(uid, policy, false);
+                            setUidPolicyUncheckedUL(uid, policy, false);
                         } else {
                             Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
                         }
@@ -1510,7 +1560,7 @@
                         // app policy is deprecated so this is only used in pre system user split.
                         final int uid = UserHandle.getUid(UserHandle.USER_SYSTEM, appId);
                         if (UserHandle.isApp(uid)) {
-                            setUidPolicyUncheckedLocked(uid, policy, false);
+                            setUidPolicyUncheckedUL(uid, policy, false);
                         } else {
                             Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
                         }
@@ -1533,7 +1583,7 @@
 
         } catch (FileNotFoundException e) {
             // missing policy is okay, probably first boot
-            upgradeLegacyBackgroundData();
+            upgradeLegacyBackgroundDataUL();
         } catch (IOException e) {
             Log.wtf(TAG, "problem reading network policy", e);
         } catch (XmlPullParserException e) {
@@ -1547,7 +1597,7 @@
      * Upgrade legacy background data flags, notifying listeners of one last
      * change to always-true.
      */
-    private void upgradeLegacyBackgroundData() {
+    private void upgradeLegacyBackgroundDataUL() {
         mRestrictBackground = Settings.Secure.getInt(
                 mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
 
@@ -1559,8 +1609,8 @@
         }
     }
 
-    void writePolicyLocked() {
-        if (LOGV) Slog.v(TAG, "writePolicyLocked()");
+    void writePolicyAL() {
+        if (LOGV) Slog.v(TAG, "writePolicyAL()");
 
         FileOutputStream fos = null;
         try {
@@ -1657,13 +1707,12 @@
         if (!UserHandle.isApp(uid)) {
             throw new IllegalArgumentException("cannot apply policy to UID " + uid);
         }
-
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             final long token = Binder.clearCallingIdentity();
             try {
                 final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
                 if (oldPolicy != policy) {
-                    setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
+                    setUidPolicyUncheckedUL(uid, oldPolicy, policy, true);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -1679,11 +1728,11 @@
             throw new IllegalArgumentException("cannot apply policy to UID " + uid);
         }
 
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
             policy |= oldPolicy;
             if (oldPolicy != policy) {
-                setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
+                setUidPolicyUncheckedUL(uid, oldPolicy, policy, true);
             }
         }
     }
@@ -1696,17 +1745,17 @@
             throw new IllegalArgumentException("cannot apply policy to UID " + uid);
         }
 
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
             policy = oldPolicy & ~policy;
             if (oldPolicy != policy) {
-                setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
+                setUidPolicyUncheckedUL(uid, oldPolicy, policy, true);
             }
         }
     }
 
-    private void setUidPolicyUncheckedLocked(int uid, int oldPolicy, int policy, boolean persist) {
-        setUidPolicyUncheckedLocked(uid, policy, persist);
+    private void setUidPolicyUncheckedUL(int uid, int oldPolicy, int policy, boolean persist) {
+        setUidPolicyUncheckedUL(uid, policy, persist);
 
         final boolean isBlacklisted = policy == POLICY_REJECT_METERED_BACKGROUND;
         mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_BLACKLIST_CHANGED, uid,
@@ -1721,13 +1770,15 @@
         }
     }
 
-    private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {
+    private void setUidPolicyUncheckedUL(int uid, int policy, boolean persist) {
         mUidPolicy.put(uid, policy);
 
         // uid policy changed, recompute rules and persist policy.
-        updateRulesForDataUsageRestrictionsLocked(uid);
+        updateRulesForDataUsageRestrictionsUL(uid);
         if (persist) {
-            writePolicyLocked();
+            synchronized (mNetworkPoliciesSecondLock) {
+                writePolicyAL();
+            }
         }
     }
 
@@ -1735,7 +1786,7 @@
     public int getUidPolicy(int uid) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             return mUidPolicy.get(uid, POLICY_NONE);
         }
     }
@@ -1745,7 +1796,7 @@
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
         int[] uids = new int[0];
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             for (int i = 0; i < mUidPolicy.size(); i++) {
                 final int uid = mUidPolicy.keyAt(i);
                 final int uidPolicy = mUidPolicy.valueAt(i);
@@ -1761,9 +1812,9 @@
      * Removes any persistable state associated with given {@link UserHandle}, persisting
      * if any changes that are made.
      */
-    boolean removeUserStateLocked(int userId, boolean writePolicy) {
+    boolean removeUserStateUL(int userId, boolean writePolicy) {
 
-        if (LOGV) Slog.v(TAG, "removeUserStateLocked()");
+        if (LOGV) Slog.v(TAG, "removeUserStateUL()");
         boolean changed = false;
 
         // Remove entries from restricted background UID whitelist
@@ -1777,7 +1828,7 @@
 
         if (wlUids.length > 0) {
             for (int uid : wlUids) {
-                removeRestrictBackgroundWhitelistedUidLocked(uid, false, false);
+                removeRestrictBackgroundWhitelistedUidUL(uid, false, false);
             }
             changed = true;
         }
@@ -1806,11 +1857,11 @@
             }
             changed = true;
         }
-
-        updateRulesForGlobalChangeLocked(true);
-
-        if (writePolicy && changed) {
-            writePolicyLocked();
+        synchronized (mNetworkPoliciesSecondLock) {
+            updateRulesForGlobalChangeAL(true);
+            if (writePolicy && changed) {
+                writePolicyAL();
+            }
         }
         return changed;
     }
@@ -1845,19 +1896,21 @@
         final long token = Binder.clearCallingIdentity();
         try {
             maybeRefreshTrustedTime();
-            synchronized (mRulesLock) {
-                normalizePoliciesLocked(policies);
-                updateNetworkEnabledLocked();
-                updateNetworkRulesLocked();
-                updateNotificationsLocked();
-                writePolicyLocked();
+            synchronized (mUidRulesFirstLock) {
+                synchronized (mNetworkPoliciesSecondLock) {
+                    normalizePoliciesNL(policies);
+                    updateNetworkEnabledNL();
+                    updateNetworkRulesNL();
+                    updateNotificationsNL();
+                    writePolicyAL();
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(token);
         }
     }
 
-    void addNetworkPolicyLocked(NetworkPolicy policy) {
+    void addNetworkPolicyNL(NetworkPolicy policy) {
         NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
         policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy);
         setNetworkPolicies(policies);
@@ -1879,7 +1932,7 @@
             }
         }
 
-        synchronized (mRulesLock) {
+        synchronized (mNetworkPoliciesSecondLock) {
             final int size = mNetworkPolicy.size();
             final NetworkPolicy[] policies = new NetworkPolicy[size];
             for (int i = 0; i < size; i++) {
@@ -1889,11 +1942,11 @@
         }
     }
 
-    private void normalizePoliciesLocked() {
-        normalizePoliciesLocked(getNetworkPolicies(mContext.getOpPackageName()));
+    private void normalizePoliciesNL() {
+        normalizePoliciesNL(getNetworkPolicies(mContext.getOpPackageName()));
     }
 
-    private void normalizePoliciesLocked(NetworkPolicy[] policies) {
+    private void normalizePoliciesNL(NetworkPolicy[] policies) {
         final TelephonyManager tele = TelephonyManager.from(mContext);
         final String[] merged = tele.getMergedSubscriberIds();
 
@@ -1927,29 +1980,31 @@
     void performSnooze(NetworkTemplate template, int type) {
         maybeRefreshTrustedTime();
         final long currentTime = currentTimeMillis();
-        synchronized (mRulesLock) {
-            // find and snooze local policy that matches
-            final NetworkPolicy policy = mNetworkPolicy.get(template);
-            if (policy == null) {
-                throw new IllegalArgumentException("unable to find policy for " + template);
-            }
+        synchronized (mUidRulesFirstLock) {
+            synchronized (mNetworkPoliciesSecondLock) {
+                // find and snooze local policy that matches
+                final NetworkPolicy policy = mNetworkPolicy.get(template);
+                if (policy == null) {
+                    throw new IllegalArgumentException("unable to find policy for " + template);
+                }
 
-            switch (type) {
-                case TYPE_WARNING:
-                    policy.lastWarningSnooze = currentTime;
-                    break;
-                case TYPE_LIMIT:
-                    policy.lastLimitSnooze = currentTime;
-                    break;
-                default:
-                    throw new IllegalArgumentException("unexpected type");
-            }
+                switch (type) {
+                    case TYPE_WARNING:
+                        policy.lastWarningSnooze = currentTime;
+                        break;
+                    case TYPE_LIMIT:
+                        policy.lastLimitSnooze = currentTime;
+                        break;
+                    default:
+                        throw new IllegalArgumentException("unexpected type");
+                }
 
-            normalizePoliciesLocked();
-            updateNetworkEnabledLocked();
-            updateNetworkRulesLocked();
-            updateNotificationsLocked();
-            writePolicyLocked();
+                normalizePoliciesNL();
+                updateNetworkEnabledNL();
+                updateNetworkRulesNL();
+                updateNotificationsNL();
+                writePolicyAL();
+            }
         }
     }
 
@@ -1957,7 +2012,7 @@
     public void onTetheringChanged(String iface, boolean tethering) {
         // No need to enforce permission because setRestrictBackground() will do it.
         if (LOGD) Log.d(TAG, "onTetherStateChanged(" + iface + ", " + tethering + ")");
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             if (mRestrictBackground && tethering) {
                 Log.d(TAG, "Tethering on (" + iface +"); disable Data Saver");
                 setRestrictBackground(false);
@@ -1971,13 +2026,13 @@
         final long token = Binder.clearCallingIdentity();
         try {
             maybeRefreshTrustedTime();
-            synchronized (mRulesLock) {
+            synchronized (mUidRulesFirstLock) {
                 if (restrictBackground == mRestrictBackground) {
                     // Ideally, UI should never allow this scenario...
                     Slog.w(TAG, "setRestrictBackground: already " + restrictBackground);
                     return;
                 }
-                setRestrictBackgroundLocked(restrictBackground);
+                setRestrictBackgroundUL(restrictBackground);
             }
 
         } finally {
@@ -1988,26 +2043,28 @@
                 .sendToTarget();
     }
 
-    private void setRestrictBackgroundLocked(boolean restrictBackground) {
+    private void setRestrictBackgroundUL(boolean restrictBackground) {
         final boolean oldRestrictBackground = mRestrictBackground;
         mRestrictBackground = restrictBackground;
         // Must whitelist foreground apps before turning data saver mode on.
         // TODO: there is no need to iterate through all apps here, just those in the foreground,
         // so it could call AM to get the UIDs of such apps, and iterate through them instead.
-        updateRulesForRestrictBackgroundLocked();
+        updateRulesForAllAppsUL(TYPE_RESTRICT_BACKGROUND);
         try {
             if (!mNetworkManager.setDataSaverModeEnabled(mRestrictBackground)) {
                 Slog.e(TAG, "Could not change Data Saver Mode on NMS to " + mRestrictBackground);
                 mRestrictBackground = oldRestrictBackground;
                 // TODO: if it knew the foreground apps (see TODO above), it could call
-                // updateRulesForRestrictBackgroundLocked() again to restore state.
+                // updateRulesForRestrictBackgroundUL() again to restore state.
                 return;
             }
         } catch (RemoteException e) {
             // ignored; service lives in system_server
         }
-        updateNotificationsLocked();
-        writePolicyLocked();
+        synchronized (mNetworkPoliciesSecondLock) {
+            updateNotificationsNL();
+            writePolicyAL();
+        }
     }
 
     @Override
@@ -2015,7 +2072,8 @@
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
         final boolean oldStatus;
         final boolean needFirewallRules;
-        synchronized (mRulesLock) {
+        int changed;
+        synchronized (mUidRulesFirstLock) {
             oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
             if (oldStatus) {
                 if (LOGD) Slog.d(TAG, "uid " + uid + " is already whitelisted");
@@ -2032,12 +2090,14 @@
             }
             if (needFirewallRules) {
                 // Only update firewall rules if necessary...
-                updateRulesForDataUsageRestrictionsLocked(uid);
+                updateRulesForDataUsageRestrictionsUL(uid);
             }
             // ...but always persists the whitelist request.
-            writePolicyLocked();
+            synchronized (mNetworkPoliciesSecondLock) {
+                writePolicyAL();
+            }
+            changed = (mRestrictBackground && !oldStatus && needFirewallRules) ? 1 : 0;
         }
-        int changed = (mRestrictBackground && !oldStatus && needFirewallRules) ? 1 : 0;
         mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, changed,
                 Boolean.TRUE).sendToTarget();
     }
@@ -2046,8 +2106,8 @@
     public void removeRestrictBackgroundWhitelistedUid(int uid) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
         final boolean changed;
-        synchronized (mRulesLock) {
-            changed = removeRestrictBackgroundWhitelistedUidLocked(uid, false, true);
+        synchronized (mUidRulesFirstLock) {
+            changed = removeRestrictBackgroundWhitelistedUidUL(uid, false, true);
         }
         mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, changed ? 1 : 0,
                 Boolean.FALSE).sendToTarget();
@@ -2057,7 +2117,7 @@
      * Removes a uid from the restricted background whitelist, returning whether its current
      * {@link ConnectivityManager.RestrictBackgroundStatus} changed.
      */
-    private boolean removeRestrictBackgroundWhitelistedUidLocked(int uid, boolean uidDeleted,
+    private boolean removeRestrictBackgroundWhitelistedUidUL(int uid, boolean uidDeleted,
             boolean updateNow) {
         final boolean oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
         if (!oldStatus && !uidDeleted) {
@@ -2077,11 +2137,13 @@
         }
         if (needFirewallRules) {
             // Only update firewall rules if necessary...
-            updateRulesForDataUsageRestrictionsLocked(uid, uidDeleted);
+            updateRulesForDataUsageRestrictionsUL(uid, uidDeleted);
         }
         if (updateNow) {
             // ...but always persists the whitelist request.
-            writePolicyLocked();
+            synchronized (mNetworkPoliciesSecondLock) {
+                writePolicyAL();
+            }
         }
         // Status only changes if Data Saver is turned on (otherwise it is DISABLED, even if the
         // app was whitelisted before).
@@ -2091,7 +2153,7 @@
     @Override
     public int[] getRestrictBackgroundWhitelistedUids() {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             final int size = mRestrictBackgroundWhitelistUids.size();
             final int[] whitelist = new int[size];
             for (int i = 0; i < size; i++) {
@@ -2110,7 +2172,7 @@
         mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
         final int uid = Binder.getCallingUid();
 
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             // Must clear identity because getUidPolicy() is restricted to system.
             final long token = Binder.clearCallingIdentity();
             final int policy;
@@ -2136,7 +2198,7 @@
     public boolean getRestrictBackground() {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             return mRestrictBackground;
         }
     }
@@ -2145,13 +2207,13 @@
     public void setDeviceIdleMode(boolean enabled) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             if (mDeviceIdleMode != enabled) {
                 mDeviceIdleMode = enabled;
                 if (mSystemReady) {
                     // Device idle change means we need to rebuild rules for all
                     // known apps, so do a global refresh.
-                    updateRulesForGlobalChangeLocked(false);
+                    updateRulesForRestrictPowerUL();
                 }
                 if (enabled) {
                     EventLogTags.writeDeviceIdleOnPhase("net");
@@ -2162,7 +2224,7 @@
         }
     }
 
-    private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
+    private NetworkPolicy findPolicyForNetworkNL(NetworkIdentity ident) {
         for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
             NetworkPolicy policy = mNetworkPolicy.valueAt(i);
             if (policy.template.matches(ident)) {
@@ -2190,8 +2252,8 @@
         final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
 
         final NetworkPolicy policy;
-        synchronized (mRulesLock) {
-            policy = findPolicyForNetworkLocked(ident);
+        synchronized (mNetworkPoliciesSecondLock) {
+            policy = findPolicyForNetworkNL(ident);
         }
 
         if (policy == null || !policy.hasCycle()) {
@@ -2229,8 +2291,8 @@
         }
 
         final NetworkPolicy policy;
-        synchronized (mRulesLock) {
-            policy = findPolicyForNetworkLocked(ident);
+        synchronized (mNetworkPoliciesSecondLock) {
+            policy = findPolicyForNetworkNL(ident);
         }
 
         if (policy != null) {
@@ -2255,155 +2317,157 @@
             argSet.add(arg);
         }
 
-        synchronized (mRulesLock) {
-            if (argSet.contains("--unsnooze")) {
-                for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
-                    mNetworkPolicy.valueAt(i).clearSnooze();
+        synchronized (mUidRulesFirstLock) {
+            synchronized (mNetworkPoliciesSecondLock) {
+                if (argSet.contains("--unsnooze")) {
+                    for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
+                        mNetworkPolicy.valueAt(i).clearSnooze();
+                    }
+
+                    normalizePoliciesNL();
+                    updateNetworkEnabledNL();
+                    updateNetworkRulesNL();
+                    updateNotificationsNL();
+                    writePolicyAL();
+
+                    fout.println("Cleared snooze timestamps");
+                    return;
                 }
 
-                normalizePoliciesLocked();
-                updateNetworkEnabledLocked();
-                updateNetworkRulesLocked();
-                updateNotificationsLocked();
-                writePolicyLocked();
-
-                fout.println("Cleared snooze timestamps");
-                return;
-            }
-
-            fout.print("System ready: "); fout.println(mSystemReady);
-            fout.print("Restrict background: "); fout.println(mRestrictBackground);
-            fout.print("Restrict power: "); fout.println(mRestrictPower);
-            fout.print("Device idle: "); fout.println(mDeviceIdleMode);
-            fout.println("Network policies:");
-            fout.increaseIndent();
-            for (int i = 0; i < mNetworkPolicy.size(); i++) {
-                fout.println(mNetworkPolicy.valueAt(i).toString());
-            }
-            fout.decreaseIndent();
-
-            fout.print("Metered ifaces: "); fout.println(String.valueOf(mMeteredIfaces));
-
-            fout.println("Policy for UIDs:");
-            fout.increaseIndent();
-            int size = mUidPolicy.size();
-            for (int i = 0; i < size; i++) {
-                final int uid = mUidPolicy.keyAt(i);
-                final int policy = mUidPolicy.valueAt(i);
-                fout.print("UID=");
-                fout.print(uid);
-                fout.print(" policy=");
-                fout.print(DebugUtils.flagsToString(NetworkPolicyManager.class, "POLICY_", policy));
-                fout.println();
-            }
-            fout.decreaseIndent();
-
-            size = mPowerSaveWhitelistExceptIdleAppIds.size();
-            if (size > 0) {
-                fout.println("Power save whitelist (except idle) app ids:");
+                fout.print("System ready: "); fout.println(mSystemReady);
+                fout.print("Restrict background: "); fout.println(mRestrictBackground);
+                fout.print("Restrict power: "); fout.println(mRestrictPower);
+                fout.print("Device idle: "); fout.println(mDeviceIdleMode);
+                fout.println("Network policies:");
                 fout.increaseIndent();
+                for (int i = 0; i < mNetworkPolicy.size(); i++) {
+                    fout.println(mNetworkPolicy.valueAt(i).toString());
+                }
+                fout.decreaseIndent();
+
+                fout.print("Metered ifaces: "); fout.println(String.valueOf(mMeteredIfaces));
+
+                fout.println("Policy for UIDs:");
+                fout.increaseIndent();
+                int size = mUidPolicy.size();
                 for (int i = 0; i < size; i++) {
+                    final int uid = mUidPolicy.keyAt(i);
+                    final int policy = mUidPolicy.valueAt(i);
                     fout.print("UID=");
-                    fout.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
-                    fout.print(": ");
-                    fout.print(mPowerSaveWhitelistExceptIdleAppIds.valueAt(i));
+                    fout.print(uid);
+                    fout.print(" policy=");
+                    fout.print(DebugUtils.flagsToString(NetworkPolicyManager.class, "POLICY_", policy));
+                    fout.println();
+                }
+                fout.decreaseIndent();
+
+                size = mPowerSaveWhitelistExceptIdleAppIds.size();
+                if (size > 0) {
+                    fout.println("Power save whitelist (except idle) app ids:");
+                    fout.increaseIndent();
+                    for (int i = 0; i < size; i++) {
+                        fout.print("UID=");
+                        fout.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
+                        fout.print(": ");
+                        fout.print(mPowerSaveWhitelistExceptIdleAppIds.valueAt(i));
+                        fout.println();
+                    }
+                    fout.decreaseIndent();
+                }
+
+                size = mPowerSaveWhitelistAppIds.size();
+                if (size > 0) {
+                    fout.println("Power save whitelist app ids:");
+                    fout.increaseIndent();
+                    for (int i = 0; i < size; i++) {
+                        fout.print("UID=");
+                        fout.print(mPowerSaveWhitelistAppIds.keyAt(i));
+                        fout.print(": ");
+                        fout.print(mPowerSaveWhitelistAppIds.valueAt(i));
+                        fout.println();
+                    }
+                    fout.decreaseIndent();
+                }
+
+                size = mRestrictBackgroundWhitelistUids.size();
+                if (size > 0) {
+                    fout.println("Restrict background whitelist uids:");
+                    fout.increaseIndent();
+                    for (int i = 0; i < size; i++) {
+                        fout.print("UID=");
+                        fout.print(mRestrictBackgroundWhitelistUids.keyAt(i));
+                        fout.println();
+                    }
+                    fout.decreaseIndent();
+                }
+
+                size = mDefaultRestrictBackgroundWhitelistUids.size();
+                if (size > 0) {
+                    fout.println("Default restrict background whitelist uids:");
+                    fout.increaseIndent();
+                    for (int i = 0; i < size; i++) {
+                        fout.print("UID=");
+                        fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
+                        fout.println();
+                    }
+                    fout.decreaseIndent();
+                }
+
+                size = mRestrictBackgroundWhitelistRevokedUids.size();
+                if (size > 0) {
+                    fout.println("Default restrict background whitelist uids revoked by users:");
+                    fout.increaseIndent();
+                    for (int i = 0; i < size; i++) {
+                        fout.print("UID=");
+                        fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
+                        fout.println();
+                    }
+                    fout.decreaseIndent();
+                }
+
+                final SparseBooleanArray knownUids = new SparseBooleanArray();
+                collectKeys(mUidState, knownUids);
+                collectKeys(mUidRules, knownUids);
+
+                fout.println("Status for all known UIDs:");
+                fout.increaseIndent();
+                size = knownUids.size();
+                for (int i = 0; i < size; i++) {
+                    final int uid = knownUids.keyAt(i);
+                    fout.print("UID=");
+                    fout.print(uid);
+
+                    final int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+                    fout.print(" state=");
+                    fout.print(state);
+                    if (state <= ActivityManager.PROCESS_STATE_TOP) {
+                        fout.print(" (fg)");
+                    } else {
+                        fout.print(state <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+                                ? " (fg svc)" : " (bg)");
+                    }
+
+                    final int uidRules = mUidRules.get(uid, RULE_NONE);
+                    fout.print(" rules=");
+                    fout.print(uidRulesToString(uidRules));
+                    fout.println();
+                }
+                fout.decreaseIndent();
+
+                fout.println("Status for just UIDs with rules:");
+                fout.increaseIndent();
+                size = mUidRules.size();
+                for (int i = 0; i < size; i++) {
+                    final int uid = mUidRules.keyAt(i);
+                    fout.print("UID=");
+                    fout.print(uid);
+                    final int uidRules = mUidRules.get(uid, RULE_NONE);
+                    fout.print(" rules=");
+                    fout.print(uidRulesToString(uidRules));
                     fout.println();
                 }
                 fout.decreaseIndent();
             }
-
-            size = mPowerSaveWhitelistAppIds.size();
-            if (size > 0) {
-                fout.println("Power save whitelist app ids:");
-                fout.increaseIndent();
-                for (int i = 0; i < size; i++) {
-                    fout.print("UID=");
-                    fout.print(mPowerSaveWhitelistAppIds.keyAt(i));
-                    fout.print(": ");
-                    fout.print(mPowerSaveWhitelistAppIds.valueAt(i));
-                    fout.println();
-                }
-                fout.decreaseIndent();
-            }
-
-            size = mRestrictBackgroundWhitelistUids.size();
-            if (size > 0) {
-                fout.println("Restrict background whitelist uids:");
-                fout.increaseIndent();
-                for (int i = 0; i < size; i++) {
-                    fout.print("UID=");
-                    fout.print(mRestrictBackgroundWhitelistUids.keyAt(i));
-                    fout.println();
-                }
-                fout.decreaseIndent();
-            }
-
-            size = mDefaultRestrictBackgroundWhitelistUids.size();
-            if (size > 0) {
-                fout.println("Default restrict background whitelist uids:");
-                fout.increaseIndent();
-                for (int i = 0; i < size; i++) {
-                    fout.print("UID=");
-                    fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
-                    fout.println();
-                }
-                fout.decreaseIndent();
-            }
-
-            size = mRestrictBackgroundWhitelistRevokedUids.size();
-            if (size > 0) {
-                fout.println("Default restrict background whitelist uids revoked by users:");
-                fout.increaseIndent();
-                for (int i = 0; i < size; i++) {
-                    fout.print("UID=");
-                    fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
-                    fout.println();
-                }
-                fout.decreaseIndent();
-            }
-
-            final SparseBooleanArray knownUids = new SparseBooleanArray();
-            collectKeys(mUidState, knownUids);
-            collectKeys(mUidRules, knownUids);
-
-            fout.println("Status for all known UIDs:");
-            fout.increaseIndent();
-            size = knownUids.size();
-            for (int i = 0; i < size; i++) {
-                final int uid = knownUids.keyAt(i);
-                fout.print("UID=");
-                fout.print(uid);
-
-                final int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-                fout.print(" state=");
-                fout.print(state);
-                if (state <= ActivityManager.PROCESS_STATE_TOP) {
-                    fout.print(" (fg)");
-                } else {
-                    fout.print(state <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
-                            ? " (fg svc)" : " (bg)");
-                }
-
-                final int uidRules = mUidRules.get(uid, RULE_NONE);
-                fout.print(" rules=");
-                fout.print(uidRulesToString(uidRules));
-                fout.println();
-            }
-            fout.decreaseIndent();
-
-            fout.println("Status for just UIDs with rules:");
-            fout.increaseIndent();
-            size = mUidRules.size();
-            for (int i = 0; i < size; i++) {
-                final int uid = mUidRules.keyAt(i);
-                fout.print("UID=");
-                fout.print(uid);
-                final int uidRules = mUidRules.get(uid, RULE_NONE);
-                fout.print(" rules=");
-                fout.print(uidRulesToString(uidRules));
-                fout.println();
-            }
-            fout.decreaseIndent();
         }
     }
 
@@ -2418,74 +2482,74 @@
     public boolean isUidForeground(int uid) {
         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
 
-        synchronized (mRulesLock) {
-            return isUidForegroundLocked(uid);
+        synchronized (mUidRulesFirstLock) {
+            return isUidForegroundUL(uid);
         }
     }
 
-    private boolean isUidForegroundLocked(int uid) {
-        return isUidStateForegroundLocked(
+    private boolean isUidForegroundUL(int uid) {
+        return isUidStateForegroundUL(
                 mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
     }
 
-    private boolean isUidForegroundOnRestrictBackgroundLocked(int uid) {
+    private boolean isUidForegroundOnRestrictBackgroundUL(int uid) {
         final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
-        return isProcStateAllowedWhileOnRestrictBackgroundLocked(procState);
+        return isProcStateAllowedWhileOnRestrictBackground(procState);
     }
 
-    private boolean isUidForegroundOnRestrictPowerLocked(int uid) {
+    private boolean isUidForegroundOnRestrictPowerUL(int uid) {
         final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
         return isProcStateAllowedWhileIdleOrPowerSaveMode(procState);
     }
 
-    private boolean isUidStateForegroundLocked(int state) {
+    private boolean isUidStateForegroundUL(int state) {
         // only really in foreground when screen is also on
         return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
     }
 
     /**
      * Process state of UID changed; if needed, will trigger
-     * {@link #updateRulesForDataUsageRestrictionsLocked(int)} and
-     * {@link #updateRulesForPowerRestrictionsLocked(int)}
+     * {@link #updateRulesForDataUsageRestrictionsUL(int)} and
+     * {@link #updateRulesForPowerRestrictionsUL(int)}
      */
-    private void updateUidStateLocked(int uid, int uidState) {
+    private void updateUidStateUL(int uid, int uidState) {
         final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
         if (oldUidState != uidState) {
             // state changed, push updated rules
             mUidState.put(uid, uidState);
-            updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState, uidState);
+            updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, uidState);
             if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
                     != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
                 if (isUidIdle(uid)) {
-                    updateRuleForAppIdleLocked(uid);
+                    updateRuleForAppIdleUL(uid);
                 }
                 if (mDeviceIdleMode) {
-                    updateRuleForDeviceIdleLocked(uid);
+                    updateRuleForDeviceIdleUL(uid);
                 }
                 if (mRestrictPower) {
-                    updateRuleForRestrictPowerLocked(uid);
+                    updateRuleForRestrictPowerUL(uid);
                 }
-                updateRulesForPowerRestrictionsLocked(uid);
+                updateRulesForPowerRestrictionsUL(uid);
             }
-            updateNetworkStats(uid, isUidStateForegroundLocked(uidState));
+            updateNetworkStats(uid, isUidStateForegroundUL(uidState));
         }
     }
 
-    private void removeUidStateLocked(int uid) {
+    private void removeUidStateUL(int uid) {
         final int index = mUidState.indexOfKey(uid);
         if (index >= 0) {
             final int oldUidState = mUidState.valueAt(index);
             mUidState.removeAt(index);
             if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
-                updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState,
+                updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState,
                         ActivityManager.PROCESS_STATE_CACHED_EMPTY);
                 if (mDeviceIdleMode) {
-                    updateRuleForDeviceIdleLocked(uid);
+                    updateRuleForDeviceIdleUL(uid);
                 }
                 if (mRestrictPower) {
-                    updateRuleForRestrictPowerLocked(uid);
+                    updateRuleForRestrictPowerUL(uid);
                 }
-                updateRulesForPowerRestrictionsLocked(uid);
+                updateRulesForPowerRestrictionsUL(uid);
                 updateNetworkStats(uid, false);
             }
         }
@@ -2500,38 +2564,38 @@
         }
     }
 
-    private void updateRestrictBackgroundRulesOnUidStatusChangedLocked(int uid, int oldUidState,
+    private void updateRestrictBackgroundRulesOnUidStatusChangedUL(int uid, int oldUidState,
             int newUidState) {
         final boolean oldForeground =
-                isProcStateAllowedWhileOnRestrictBackgroundLocked(oldUidState);
+                isProcStateAllowedWhileOnRestrictBackground(oldUidState);
         final boolean newForeground =
-                isProcStateAllowedWhileOnRestrictBackgroundLocked(newUidState);
+                isProcStateAllowedWhileOnRestrictBackground(newUidState);
         if (oldForeground != newForeground) {
-            updateRulesForDataUsageRestrictionsLocked(uid);
+            updateRulesForDataUsageRestrictionsUL(uid);
         }
     }
 
     private void updateScreenOn() {
-        synchronized (mRulesLock) {
+        synchronized (mUidRulesFirstLock) {
             try {
                 mScreenOn = mPowerManager.isInteractive();
             } catch (RemoteException e) {
                 // ignored; service lives in system_server
             }
-            updateRulesForScreenLocked();
+            updateRulesForScreenUL();
         }
     }
 
     /**
      * Update rules that might be changed by {@link #mScreenOn} value.
      */
-    private void updateRulesForScreenLocked() {
+    private void updateRulesForScreenUL() {
         // only update rules for anyone with foreground activities
         final int size = mUidState.size();
         for (int i = 0; i < size; i++) {
             if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
                 final int uid = mUidState.keyAt(i);
-                updateRestrictionRulesForUidLocked(uid);
+                updateRestrictionRulesForUidUL(uid);
             }
         }
     }
@@ -2540,31 +2604,31 @@
         return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
     }
 
-    static boolean isProcStateAllowedWhileOnRestrictBackgroundLocked(int procState) {
+    static boolean isProcStateAllowedWhileOnRestrictBackground(int procState) {
         return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
     }
 
-    void updateRulesForRestrictPowerLocked() {
-        updateRulesForWhitelistedPowerSaveLocked(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
+    void updateRulesForPowerSaveUL() {
+        updateRulesForWhitelistedPowerSaveUL(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
                 mUidFirewallPowerSaveRules);
     }
 
-    void updateRuleForRestrictPowerLocked(int uid) {
-        updateRulesForWhitelistedPowerSaveLocked(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
+    void updateRuleForRestrictPowerUL(int uid) {
+        updateRulesForWhitelistedPowerSaveUL(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
     }
 
-    void updateRulesForDeviceIdleLocked() {
-        updateRulesForWhitelistedPowerSaveLocked(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
+    void updateRulesForDeviceIdleUL() {
+        updateRulesForWhitelistedPowerSaveUL(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
                 mUidFirewallDozableRules);
     }
 
-    void updateRuleForDeviceIdleLocked(int uid) {
-        updateRulesForWhitelistedPowerSaveLocked(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
+    void updateRuleForDeviceIdleUL(int uid) {
+        updateRulesForWhitelistedPowerSaveUL(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
     }
 
     // NOTE: since both fw_dozable and fw_powersave uses the same map
     // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
-    private void updateRulesForWhitelistedPowerSaveLocked(boolean enabled, int chain,
+    private void updateRulesForWhitelistedPowerSaveUL(boolean enabled, int chain,
             SparseIntArray rules) {
         if (enabled) {
             // Sync the whitelists before enabling the chain.  We don't care about the rules if
@@ -2595,23 +2659,19 @@
             setUidFirewallRules(chain, uidRules);
         }
 
-        enableFirewallChainLocked(chain, enabled);
+        enableFirewallChainUL(chain, enabled);
     }
 
-    private void updateRulesForNonMeteredNetworksLocked() {
-
-    }
-
-    private boolean isWhitelistedBatterySaverLocked(int uid) {
+    private boolean isWhitelistedBatterySaverUL(int uid) {
         final int appId = UserHandle.getAppId(uid);
         return mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId);
     }
 
     // NOTE: since both fw_dozable and fw_powersave uses the same map
     // (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
-    private void updateRulesForWhitelistedPowerSaveLocked(int uid, boolean enabled, int chain) {
+    private void updateRulesForWhitelistedPowerSaveUL(int uid, boolean enabled, int chain) {
         if (enabled) {
-            if (isWhitelistedBatterySaverLocked(uid)
+            if (isWhitelistedBatterySaverUL(uid)
                     || isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid))) {
                 setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
             } else {
@@ -2620,7 +2680,7 @@
         }
     }
 
-    void updateRulesForAppIdleLocked() {
+    void updateRulesForAppIdleUL() {
         final SparseIntArray uidRules = mUidFirewallStandbyRules;
         uidRules.clear();
 
@@ -2644,50 +2704,69 @@
         setUidFirewallRules(FIREWALL_CHAIN_STANDBY, uidRules);
     }
 
-    void updateRuleForAppIdleLocked(int uid) {
+    void updateRuleForAppIdleUL(int uid) {
         if (!isUidValidForBlacklistRules(uid)) return;
 
         int appId = UserHandle.getAppId(uid);
         if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)
-                && !isUidForegroundOnRestrictPowerLocked(uid)) {
+                && !isUidForegroundOnRestrictPowerUL(uid)) {
             setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
         } else {
             setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
         }
     }
 
-    void updateRulesForAppIdleParoleLocked() {
+    void updateRulesForAppIdleParoleUL() {
         boolean enableChain = !mUsageStats.isAppIdleParoleOn();
-        enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
+        enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, enableChain);
     }
 
     /**
      * Update rules that might be changed by {@link #mRestrictBackground},
      * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
      */
-    private void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
+    private void updateRulesForGlobalChangeAL(boolean restrictedNetworksChanged) {
         long start;
         if (LOGD) start = System.currentTimeMillis();
 
-        updateRulesForDeviceIdleLocked();
-        updateRulesForAppIdleLocked();
-        updateRulesForRestrictPowerLocked();
-        updateRulesForRestrictBackgroundLocked();
-        setRestrictBackgroundLocked(mRestrictBackground);
+        updateRulesForRestrictPowerUL();
+        updateRulesForRestrictBackgroundUL();
 
         // If the set of restricted networks may have changed, re-evaluate those.
         if (restrictedNetworksChanged) {
-            normalizePoliciesLocked();
-            updateNetworkRulesLocked();
+            normalizePoliciesNL();
+            updateNetworkRulesNL();
         }
         if (LOGD) {
             final long delta = System.currentTimeMillis() - start;
-            Slog.d(TAG, "updateRulesForGlobalChangeLocked(" + restrictedNetworksChanged + ") took "
+            Slog.d(TAG, "updateRulesForGlobalChangeAL(" + restrictedNetworksChanged + ") took "
                     + delta + "ms");
         }
     }
 
-    private void updateRulesForRestrictBackgroundLocked() {
+    private void updateRulesForRestrictPowerUL() {
+        updateRulesForDeviceIdleUL();
+        updateRulesForAppIdleUL();
+        updateRulesForPowerSaveUL();
+        updateRulesForAllAppsUL(TYPE_RESTRICT_POWER);
+    }
+
+    private void updateRulesForRestrictBackgroundUL() {
+        updateRulesForAllAppsUL(TYPE_RESTRICT_BACKGROUND);
+    }
+
+    private static final int TYPE_RESTRICT_BACKGROUND = 1;
+    private static final int TYPE_RESTRICT_POWER = 2;
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = false, value = {
+            TYPE_RESTRICT_BACKGROUND,
+            TYPE_RESTRICT_POWER,
+    })
+    public @interface RestrictType {
+    }
+
+    // TODO: refactor / consolidate all those updateXyz methods, there are way too many of them...
+    private void updateRulesForAllAppsUL(@RestrictType int type) {
         final PackageManager pm = mContext.getPackageManager();
 
         // update rules for all installed applications
@@ -2704,25 +2783,34 @@
             for (int j = 0; j < appsSize; j++) {
                 final ApplicationInfo app = apps.get(j);
                 final int uid = UserHandle.getUid(user.id, app.uid);
-                updateRulesForDataUsageRestrictionsLocked(uid);
-                updateRulesForPowerRestrictionsLocked(uid);
+                switch (type) {
+                    case TYPE_RESTRICT_BACKGROUND:
+                        updateRulesForDataUsageRestrictionsUL(uid);
+                        break;
+                    case TYPE_RESTRICT_POWER:
+                        updateRulesForPowerRestrictionsUL(uid);
+                        break;
+                    default:
+                        Slog.w(TAG, "Invalid type for updateRulesForAllApps: " + type);
+                }
             }
         }
     }
 
-    private void updateRulesForTempWhitelistChangeLocked() {
+    private void updateRulesForTempWhitelistChangeUL() {
         final List<UserInfo> users = mUserManager.getUsers();
         for (int i = 0; i < users.size(); i++) {
             final UserInfo user = users.get(i);
             for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
                 int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
                 int uid = UserHandle.getUid(user.id, appId);
+                updateRulesForRestrictPowerUL();
                 // Update external firewall rules.
-                updateRuleForAppIdleLocked(uid);
-                updateRuleForDeviceIdleLocked(uid);
-                updateRuleForRestrictPowerLocked(uid);
+                updateRuleForAppIdleUL(uid);
+                updateRuleForDeviceIdleUL(uid);
+                updateRuleForRestrictPowerUL(uid);
                 // Update internal rules.
-                updateRulesForPowerRestrictionsLocked(uid);
+                updateRulesForPowerRestrictionsUL(uid);
             }
         }
     }
@@ -2786,17 +2874,17 @@
      *
      * <p>This method changes both the external firewall rules and the internal state.
      */
-    private void updateRestrictionRulesForUidLocked(int uid) {
+    private void updateRestrictionRulesForUidUL(int uid) {
         // Methods below only changes the firewall rules for the power-related modes.
-        updateRuleForDeviceIdleLocked(uid);
-        updateRuleForAppIdleLocked(uid);
-        updateRuleForRestrictPowerLocked(uid);
+        updateRuleForDeviceIdleUL(uid);
+        updateRuleForAppIdleUL(uid);
+        updateRuleForRestrictPowerUL(uid);
 
         // Update internal state for power-related modes.
-        updateRulesForPowerRestrictionsLocked(uid);
+        updateRulesForPowerRestrictionsUL(uid);
 
         // Update firewall and internal rules for Data Saver Mode.
-        updateRulesForDataUsageRestrictionsLocked(uid);
+        updateRulesForDataUsageRestrictionsUL(uid);
     }
 
     /**
@@ -2818,7 +2906,7 @@
      * {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundWhitelistedUid(int)} /
      * {@link #removeRestrictBackgroundWhitelistedUid(int)} methods (for blacklist and whitelist
      * respectively): these methods set the proper internal state (blacklist / whitelist), then call
-     * this ({@link #updateRulesForDataUsageRestrictionsLocked(int)}) to propagate the rules to
+     * this ({@link #updateRulesForDataUsageRestrictionsUL(int)}) to propagate the rules to
      * {@link INetworkManagementService}, but this method should also be called in events (like
      * Data Saver Mode flips or UID state changes) that might affect the foreground app, since the
      * following rules should also be applied:
@@ -2838,15 +2926,15 @@
      * <p>The {@link #mUidRules} map is used to define the transtion of states of an UID.
      *
      */
-    private void updateRulesForDataUsageRestrictionsLocked(int uid) {
-        updateRulesForDataUsageRestrictionsLocked(uid, false);
+    private void updateRulesForDataUsageRestrictionsUL(int uid) {
+        updateRulesForDataUsageRestrictionsUL(uid, false);
     }
 
     /**
-     * Overloaded version of {@link #updateRulesForDataUsageRestrictionsLocked(int)} called when an
+     * Overloaded version of {@link #updateRulesForDataUsageRestrictionsUL(int)} called when an
      * app is removed - it ignores the UID validity check.
      */
-    private void updateRulesForDataUsageRestrictionsLocked(int uid, boolean uidDeleted) {
+    private void updateRulesForDataUsageRestrictionsUL(int uid, boolean uidDeleted) {
         if (!uidDeleted && !isUidValidForWhitelistRules(uid)) {
             if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
             return;
@@ -2854,7 +2942,7 @@
 
         final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
         final int oldUidRules = mUidRules.get(uid, RULE_NONE);
-        final boolean isForeground = isUidForegroundOnRestrictBackgroundLocked(uid);
+        final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);
 
         final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
         final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
@@ -2878,7 +2966,7 @@
         final int newUidRules = newRule | (oldUidRules & MASK_ALL_NETWORKS);
 
         if (LOGV) {
-            Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + ")"
+            Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
                     + ": isForeground=" +isForeground
                     + ", isBlacklisted=" + isBlacklisted
                     + ", isWhitelisted=" + isWhitelisted
@@ -2971,7 +3059,7 @@
      * <p>
      * <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}.
      */
-    private void updateRulesForPowerRestrictionsLocked(int uid) {
+    private void updateRulesForPowerRestrictionsUL(int uid) {
         if (!isUidValidForBlacklistRules(uid)) {
             if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
             return;
@@ -2981,9 +3069,9 @@
         final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
         final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
         final int oldUidRules = mUidRules.get(uid, RULE_NONE);
-        final boolean isForeground = isUidForegroundOnRestrictPowerLocked(uid);
+        final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
 
-        final boolean isWhitelisted = isWhitelistedBatterySaverLocked(uid);
+        final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid);
         final int oldRule = oldUidRules & MASK_ALL_NETWORKS;
         int newRule = RULE_NONE;
 
@@ -3002,7 +3090,7 @@
         final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
 
         if (LOGV) {
-            Log.v(TAG, "updateRulesForNonMeteredNetworksLocked(" + uid + ")"
+            Log.v(TAG, "updateRulesForNonMeteredNetworksUL(" + uid + ")"
                     + ", isIdle: " + isIdle
                     + ", mRestrictPower: " + mRestrictPower
                     + ", mDeviceIdleMode: " + mDeviceIdleMode
@@ -3047,9 +3135,9 @@
                 final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
                         PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
                 if (LOGV) Log.v(TAG, "onAppIdleStateChanged(): uid=" + uid + ", idle=" + idle);
-                synchronized (mRulesLock) {
-                    updateRuleForAppIdleLocked(uid);
-                    updateRulesForPowerRestrictionsLocked(uid);
+                synchronized (mUidRulesFirstLock) {
+                    updateRuleForAppIdleUL(uid);
+                    updateRulesForPowerRestrictionsUL(uid);
                 }
             } catch (NameNotFoundException nnfe) {
             }
@@ -3057,8 +3145,8 @@
 
         @Override
         public void onParoleStateChanged(boolean isParoleOn) {
-            synchronized (mRulesLock) {
-                updateRulesForAppIdleParoleLocked();
+            synchronized (mUidRulesFirstLock) {
+                updateRulesForAppIdleParoleUL();
             }
         }
     }
@@ -3143,7 +3231,7 @@
                     final String iface = (String) msg.obj;
 
                     maybeRefreshTrustedTime();
-                    synchronized (mRulesLock) {
+                    synchronized (mNetworkPoliciesSecondLock) {
                         if (mMeteredIfaces.contains(iface)) {
                             try {
                                 // force stats update to make sure we have
@@ -3153,8 +3241,8 @@
                                 // ignored; service lives in system_server
                             }
 
-                            updateNetworkEnabledLocked();
-                            updateNotificationsLocked();
+                            updateNetworkEnabledNL();
+                            updateNotificationsNL();
                         }
                     }
                     return true;
@@ -3354,7 +3442,7 @@
     /**
      * Add or remove a uid to the firewall blacklist for all network ifaces.
      */
-    private void enableFirewallChainLocked(int chain, boolean enable) {
+    private void enableFirewallChainUL(int chain, boolean enable) {
         if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
                 mFirewallChainStates.get(chain) == enable) {
             // All is the same, nothing to do.
@@ -3483,9 +3571,9 @@
         @Override
         public void onPackageRemoved(String packageName, int uid) {
             if (LOGV) Slog.v(TAG, "onPackageRemoved: " + packageName + " ->" + uid);
-            synchronized (mRulesLock) {
-                removeRestrictBackgroundWhitelistedUidLocked(uid, true, true);
-                updateRestrictionRulesForUidLocked(uid);
+            synchronized (mUidRulesFirstLock) {
+                removeRestrictBackgroundWhitelistedUidUL(uid, true, true);
+                updateRestrictionRulesForUidUL(uid);
             }
         }
     }
@@ -3494,11 +3582,13 @@
 
         @Override
         public void resetUserState(int userId) {
-            synchronized (mRulesLock) {
-                boolean changed = removeUserStateLocked(userId, false);
-                changed = addDefaultRestrictBackgroundWhitelistUidsLocked(userId) || changed;
+            synchronized (mUidRulesFirstLock) {
+                boolean changed = removeUserStateUL(userId, false);
+                changed = addDefaultRestrictBackgroundWhitelistUidsUL(userId) || changed;
                 if (changed) {
-                    writePolicyLocked();
+                    synchronized (mNetworkPoliciesSecondLock) {
+                        writePolicyAL();
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index ea36170..3360584 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -355,9 +355,10 @@
         @Override
         protected void recordSample(StatsContext statsContext) {
             // Recorder does not need to be locked in this context since only the handler
-            // thread will update it
+            // thread will update it. We pass a null VPN array because usage is aggregated by uid
+            // for this snapshot, so VPN traffic can't be reattributed to responsible apps.
             mRecorder.recordSnapshotLocked(statsContext.mXtSnapshot, statsContext.mActiveIfaces,
-                    statsContext.mVpnArray, statsContext.mCurrentTime);
+                    null /* vpnArray */, statsContext.mCurrentTime);
         }
 
         /**
@@ -396,7 +397,8 @@
         @Override
         protected void recordSample(StatsContext statsContext) {
             // Recorder does not need to be locked in this context since only the handler
-            // thread will update it
+            // thread will update it. We pass the VPN info so VPN traffic is reattributed to
+            // responsible apps.
             mRecorder.recordSnapshotLocked(statsContext.mUidSnapshot, statsContext.mActiveUidIfaces,
                     statsContext.mVpnArray, statsContext.mCurrentTime);
         }
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 04dc917..090a076 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -22,6 +22,7 @@
 import static android.text.format.DateUtils.YEAR_IN_MILLIS;
 import static com.android.internal.util.Preconditions.checkNotNull;
 
+import android.annotation.Nullable;
 import android.net.NetworkStats;
 import android.net.NetworkStats.NonMonotonicObserver;
 import android.net.NetworkStatsHistory;
@@ -199,9 +200,14 @@
      * Record any delta that occurred since last {@link NetworkStats} snapshot,
      * using the given {@link Map} to identify network interfaces. First
      * snapshot is considered bootstrap, and is not counted as delta.
+     *
+     * @param vpnArray Optional info about the currently active VPN, if any. This is used to
+     *                 redistribute traffic from the VPN app to the underlying responsible apps.
+     *                 This should always be set to null if the provided snapshot is aggregated
+     *                 across all UIDs (e.g. contains UID_ALL buckets), regardless of VPN state.
      */
     public void recordSnapshotLocked(NetworkStats snapshot,
-            Map<String, NetworkIdentitySet> ifaceIdent, VpnInfo[] vpnArray,
+            Map<String, NetworkIdentitySet> ifaceIdent, @Nullable VpnInfo[] vpnArray,
             long currentTimeMillis) {
         final HashSet<String> unknownIfaces = Sets.newHashSet();
 
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 8610fa1..23c111e 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1009,9 +1009,16 @@
         final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
         final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
 
+
+        // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
+        // can't be reattributed to responsible apps.
+        mDevRecorder.recordSnapshotLocked(
+                devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+        mXtRecorder.recordSnapshotLocked(
+                xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+
+        // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
         VpnInfo[] vpnArray = mConnManager.getAllVpnInfo();
-        mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, null, currentTime);
-        mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, null, currentTime);
         mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
         mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0af0c73..ce94220 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -67,7 +67,6 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
@@ -2521,6 +2520,8 @@
             return;
         }
 
+        mUsageStats.registerEnqueuedByApp(pkg);
+
         // Limit the number of notifications that any given package except the android
         // package or a registered listener can enqueue.  Prevents DOS attacks and deals with leaks.
         if (!isSystemNotification && !isNotificationFromListener) {
@@ -2614,17 +2615,18 @@
     private static void setPendingIntentWhitelistDuration(ActivityManagerInternal am, long duration,
             Bundle extras) {
         for (String key : extras.keySet()) {
-            setPendingIntentWhitelistDuration(am, duration, extras.getParcelable(key));
-            final Parcelable[] parcelableArray = extras.getParcelableArray(key);
-            if (parcelableArray != null) {
-                for (Parcelable parcelable: parcelableArray) {
+            final Object value = extras.get(key);
+            if (value instanceof Parcelable) {
+                setPendingIntentWhitelistDuration(am, duration, (Parcelable) value);
+            } else if (value instanceof Parcelable[]) {
+                for (Parcelable parcelable : (Parcelable[]) value) {
                     setPendingIntentWhitelistDuration(am, duration, parcelable);
                 }
-            }
-            final ArrayList<Parcelable> parcelableList = extras.getParcelableArrayList(key);
-            if (parcelableList != null) {
-                for (Parcelable parcelable: parcelableList) {
-                    setPendingIntentWhitelistDuration(am, duration, parcelable);
+            } else if (value instanceof List) {
+                for (Object element : (List <?>) value) {
+                    if (element instanceof Parcelable) {
+                        setPendingIntentWhitelistDuration(am, duration, (Parcelable) element);
+                    }
                 }
             }
         }
@@ -2802,7 +2804,7 @@
         // notification was a summary and its group key changed.
         if (oldIsSummary && (!isSummary || !oldGroup.equals(group))) {
             cancelGroupChildrenLocked(old, callingUid, callingPid, null,
-                    REASON_GROUP_SUMMARY_CANCELED);
+                    REASON_GROUP_SUMMARY_CANCELED, false /* sendDelete */);
         }
     }
 
@@ -3435,7 +3437,7 @@
 
                         cancelNotificationLocked(r, sendDelete, reason);
                         cancelGroupChildrenLocked(r, callingUid, callingPid, listenerName,
-                                REASON_GROUP_SUMMARY_CANCELED);
+                                REASON_GROUP_SUMMARY_CANCELED, sendDelete);
                         updateLightsLocked();
                     }
                 }
@@ -3514,7 +3516,7 @@
                 final int M = canceledNotifications.size();
                 for (int i = 0; i < M; i++) {
                     cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid,
-                            listenerName, REASON_GROUP_SUMMARY_CANCELED);
+                            listenerName, REASON_GROUP_SUMMARY_CANCELED, false /* sendDelete */);
                 }
             }
             if (canceledNotifications != null) {
@@ -3558,14 +3560,14 @@
         int M = canceledNotifications != null ? canceledNotifications.size() : 0;
         for (int i = 0; i < M; i++) {
             cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid,
-                    listenerName, REASON_GROUP_SUMMARY_CANCELED);
+                    listenerName, REASON_GROUP_SUMMARY_CANCELED, false /* sendDelete */);
         }
         updateLightsLocked();
     }
 
     // Warning: The caller is responsible for invoking updateLightsLocked().
     private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid,
-            String listenerName, int reason) {
+            String listenerName, int reason, boolean sendDelete) {
         Notification n = r.getNotification();
         if (!n.isGroupSummary()) {
             return;
@@ -3588,7 +3590,7 @@
                 EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, childSbn.getId(),
                         childSbn.getTag(), userId, 0, 0, reason, listenerName);
                 mNotificationList.remove(i);
-                cancelNotificationLocked(childR, false, reason);
+                cancelNotificationLocked(childR, sendDelete, reason);
             }
         }
     }
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 7b573da..07142f0 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -114,6 +114,17 @@
     }
 
     /**
+     * Called when a notification is tentatively enqueued by an app, before rate checking.
+     */
+    public synchronized void registerEnqueuedByApp(String packageName) {
+        AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(packageName);
+        for (AggregatedStats stats : aggregatedStatsArray) {
+            stats.numEnqueuedByApp++;
+        }
+        releaseAggregatedStatsLocked(aggregatedStatsArray);
+    }
+
+    /**
      * Called when a notification has been posted.
      */
     public synchronized void registerPostedByApp(NotificationRecord notification) {
@@ -344,6 +355,7 @@
         private AggregatedStats mPrevious;
 
         // ---- Updated as the respective events occur.
+        public int numEnqueuedByApp;
         public int numPostedByApp;
         public int numUpdatedByApp;
         public int numRemovedByApp;
@@ -470,6 +482,7 @@
 
         public void emit() {
             AggregatedStats previous = getPrevious();
+            maybeCount("note_enqueued", (numEnqueuedByApp - previous.numEnqueuedByApp));
             maybeCount("note_post", (numPostedByApp - previous.numPostedByApp));
             maybeCount("note_update", (numUpdatedByApp - previous.numUpdatedByApp));
             maybeCount("note_remove", (numRemovedByApp - previous.numRemovedByApp));
@@ -501,6 +514,7 @@
             quietImportance.maybeCount(previous.quietImportance);
             finalImportance.maybeCount(previous.finalImportance);
 
+            previous.numEnqueuedByApp = numEnqueuedByApp;
             previous.numPostedByApp = numPostedByApp;
             previous.numUpdatedByApp = numUpdatedByApp;
             previous.numRemovedByApp = numRemovedByApp;
@@ -568,6 +582,8 @@
             output.append(indentPlusTwo);
             output.append("key='").append(key).append("',\n");
             output.append(indentPlusTwo);
+            output.append("numEnqueuedByApp=").append(numEnqueuedByApp).append(",\n");
+            output.append(indentPlusTwo);
             output.append("numPostedByApp=").append(numPostedByApp).append(",\n");
             output.append(indentPlusTwo);
             output.append("numUpdatedByApp=").append(numUpdatedByApp).append(",\n");
@@ -631,6 +647,7 @@
             JSONObject dump = new JSONObject();
             dump.put("key", key);
             dump.put("duration", SystemClock.elapsedRealtime() - mCreated);
+            maybePut(dump, "numEnqueuedByApp", numEnqueuedByApp);
             maybePut(dump, "numPostedByApp", numPostedByApp);
             maybePut(dump, "numUpdatedByApp", numUpdatedByApp);
             maybePut(dump, "numRemovedByApp", numRemovedByApp);
diff --git a/services/core/java/com/android/server/notification/RateEstimator.java b/services/core/java/com/android/server/notification/RateEstimator.java
index c17db4a..a2f93dc 100644
--- a/services/core/java/com/android/server/notification/RateEstimator.java
+++ b/services/core/java/com/android/server/notification/RateEstimator.java
@@ -26,9 +26,12 @@
     private static final double RATE_ALPHA = 0.8;
     private static final double MINIMUM_DT = 0.0005;
     private Long mLastEventTime;
-    private Float mInterarrivalTime;
+    private double mInterarrivalTime;
 
-    public RateEstimator() {}
+    public RateEstimator() {
+        // assume something generous if we have no information
+        mInterarrivalTime = 1000.0;
+    }
 
     /** Update the estimate to account for an event that just happened. */
     public float update(long now) {
@@ -38,7 +41,7 @@
             rate = 0f;
         } else {
             // Calculate the new inter-arrival time based on last event time.
-            mInterarrivalTime = (float) getInterarrivalEstimate(now);
+            mInterarrivalTime = getInterarrivalEstimate(now);
             rate = (float) (1.0 / mInterarrivalTime);
         }
         mLastEventTime = now;
@@ -57,10 +60,6 @@
     private double getInterarrivalEstimate(long now) {
         double dt = ((double) (now - mLastEventTime)) / 1000.0;
         dt = Math.max(dt, MINIMUM_DT);
-        if (mInterarrivalTime == null) {
-            // No last inter-arrival time, return the new value directly.
-            return dt;
-        }
         // a*iat_old + (1-a)*(t_now-t_last)
         return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt);
     }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 1186340..46da607 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -776,8 +776,7 @@
                                     /* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
                                     /* component= */ null,
                                     ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
-                                    | ShortcutQuery.FLAG_GET_PINNED
-                                    | ShortcutQuery.FLAG_GET_DYNAMIC
+                                    | ShortcutQuery.FLAG_GET_ALL_KINDS
                                     , userId);
                     try {
                         listener.onShortcutChanged(user, packageName,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2562707..c627ff0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -464,7 +464,7 @@
 
     private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
 
-    private static int DEFAULT_EPHEMERAL_HASH_PREFIX_MASK = 0xFFFFFFFF;
+    private static int DEFAULT_EPHEMERAL_HASH_PREFIX_MASK = 0xFFFFF000;
     private static int DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT = 5;
 
     /** Permission grant: not grant the permission. */
@@ -1219,7 +1219,9 @@
                     StringBuffer sb = new StringBuffer();
 
                     String firstLine = readLine(in, sb);
-                    if (firstLine.equals(USAGE_FILE_MAGIC_VERSION_1)) {
+                    if (firstLine == null) {
+                        // Empty file. Do nothing.
+                    } else if (USAGE_FILE_MAGIC_VERSION_1.equals(firstLine)) {
                         readVersion1LP(in, sb);
                     } else {
                         readVersion0LP(in, sb, firstLine);
@@ -2451,8 +2453,14 @@
                     | PackageParser.PARSE_IS_SYSTEM
                     | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
 
+            // Collected privileged vendor packages.
+            final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
+            scanDirLI(privilegedVendorAppDir, PackageParser.PARSE_IS_SYSTEM
+                    | PackageParser.PARSE_IS_SYSTEM_DIR
+                    | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
+
             // Collect all vendor packages.
-            File vendorAppDir = new File("/vendor/app");
+            File vendorAppDir = new File(Environment.getVendorDirectory(), "app");
             try {
                 vendorAppDir = vendorAppDir.getCanonicalFile();
             } catch (IOException e) {
@@ -4764,10 +4772,8 @@
                 final SharedUserSetting sus = (SharedUserSetting) obj;
                 final int N = sus.packages.size();
                 final String[] res = new String[N];
-                final Iterator<PackageSetting> it = sus.packages.iterator();
-                int i = 0;
-                while (it.hasNext()) {
-                    res[i++] = it.next().name;
+                for (int i = 0; i < N; i++) {
+                    res[i] = sus.packages.valueAt(i).name;
                 }
                 return res;
             } else if (obj instanceof PackageSetting) {
@@ -5000,7 +5006,8 @@
                 Global.EPHEMERAL_HASH_PREFIX_MASK, DEFAULT_EPHEMERAL_HASH_PREFIX_MASK);
         final int ephemeralPrefixCount = Global.getInt(mContext.getContentResolver(),
                 Global.EPHEMERAL_HASH_PREFIX_COUNT, DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT);
-        final EphemeralDigest digest = new EphemeralDigest(intent.getData(), ephemeralPrefixCount);
+        final EphemeralDigest digest = new EphemeralDigest(intent.getData(), ephemeralPrefixMask,
+                ephemeralPrefixCount);
         final int[] shaPrefix = digest.getDigestPrefix();
         final byte[][] digestBytes = digest.getDigestBytes();
         final List<EphemeralResolveInfo> ephemeralResolveInfoList =
@@ -5012,7 +5019,7 @@
         }
 
         // Go in reverse order so we match the narrowest scope first.
-        for (int i = shaPrefix.length; i >= 0 ; --i) {
+        for (int i = shaPrefix.length - 1; i >= 0 ; --i) {
             for (EphemeralResolveInfo ephemeralApplication : ephemeralResolveInfoList) {
                 if (!Arrays.equals(digestBytes[i], ephemeralApplication.getDigestBytes())) {
                     continue;
@@ -14485,7 +14492,9 @@
         // Remove existing system package
         removePackageLI(deletedPackage, true);
 
-        disabledSystem = disableSystemPackageLPw(deletedPackage, pkg);
+        synchronized (mPackages) {
+            disabledSystem = disableSystemPackageLPw(deletedPackage, pkg);
+        }
         if (!disabledSystem) {
             // We didn't need to disable the .apk as a current system package,
             // which means we are replacing another update that is already
@@ -15139,16 +15148,13 @@
             }
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
             // Do not run PackageDexOptimizer through the local performDexOpt
-            // method because `pkg` is not in `mPackages` yet.
-            int result = mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
+            // method because `pkg` may not be in `mPackages` yet.
+            //
+            // Also, don't fail application installs if the dexopt step fails.
+            mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
                     null /* instructionSets */, false /* checkProfiles */,
                     getCompilerFilterForReason(REASON_INSTALL));
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-            if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
-                String msg = "Extracting package failed for " + pkgName;
-                res.setError(INSTALL_FAILED_DEXOPT, msg);
-                return;
-            }
 
             // Notify BackgroundDexOptService that the package has been changed.
             // If this is an update of a package which used to fail to compile,
@@ -15821,7 +15827,10 @@
         try {
             final String privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app")
                     .getCanonicalPath();
-            return path.getCanonicalPath().startsWith(privilegedAppDir);
+            final String privilegedAppVendorDir = new File(Environment.getVendorDirectory(), "priv-app")
+                    .getCanonicalPath();
+            return (path.getCanonicalPath().startsWith(privilegedAppDir)
+                    || path.getCanonicalPath().startsWith(privilegedAppVendorDir));
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
         }
@@ -19359,10 +19368,18 @@
             if ((flags & StorageManager.FLAG_STORAGE_DE) != 0 && !mOnlyCore) {
                 UserManagerService.enforceSerialNumber(
                         Environment.getDataUserDeDirectory(volumeUuid, userId), userSerial);
+                if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
+                    UserManagerService.enforceSerialNumber(
+                            Environment.getDataSystemDeDirectory(userId), userSerial);
+                }
             }
             if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && !mOnlyCore) {
                 UserManagerService.enforceSerialNumber(
                         Environment.getDataUserCeDirectory(volumeUuid, userId), userSerial);
+                if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
+                    UserManagerService.enforceSerialNumber(
+                            Environment.getDataSystemCeDirectory(userId), userSerial);
+                }
             }
 
             synchronized (mInstallLock) {
@@ -19431,6 +19448,10 @@
                 .listFilesOrEmpty(Environment.getDataUserDeDirectory(volumeUuid)));
         Collections.addAll(files, FileUtils
                 .listFilesOrEmpty(Environment.getDataUserCeDirectory(volumeUuid)));
+        Collections.addAll(files, FileUtils
+                .listFilesOrEmpty(Environment.getDataSystemDeDirectory()));
+        Collections.addAll(files, FileUtils
+                .listFilesOrEmpty(Environment.getDataSystemCeDirectory()));
         for (File file : files) {
             if (!file.isDirectory()) continue;
 
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 934545a..d637586 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -19,10 +19,8 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ShortcutInfo;
 import android.content.res.Resources;
 import android.os.PersistableBundle;
@@ -51,8 +49,6 @@
 import java.util.Set;
 import java.util.function.Predicate;
 
-import sun.misc.Resource;
-
 /**
  * Package information used by {@link ShortcutService}.
  * User information used by {@link ShortcutService}.
@@ -63,6 +59,7 @@
  */
 class ShortcutPackage extends ShortcutPackageItem {
     private static final String TAG = ShortcutService.TAG;
+    private static final String TAG_VERIFY = ShortcutService.TAG + ".verify";
 
     static final String TAG_ROOT = "package";
     private static final String TAG_INTENT_EXTRAS = "intent-extras";
@@ -303,12 +300,17 @@
      * Remove all dynamic shortcuts.
      */
     public void deleteAllDynamicShortcuts() {
+        final long now = mShortcutUser.mService.injectCurrentTimeMillis();
+
         boolean changed = false;
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
             if (si.isDynamic()) {
                 changed = true;
+
+                si.setTimestamp(now);
                 si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+                si.setRank(0); // It may still be pinned, so clear the rank.
             }
         }
         if (changed) {
@@ -356,10 +358,14 @@
             ensureNotImmutable(oldShortcut);
         }
         if (oldShortcut.isPinned()) {
+
+            oldShortcut.setRank(0);
             oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
             if (disable) {
                 oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
             }
+            oldShortcut.setTimestamp(mShortcutUser.mService.injectCurrentTimeMillis());
+
             return oldShortcut;
         } else {
             deleteShortcutInner(shortcutId);
@@ -676,6 +682,8 @@
             changed |= pushOutExcessShortcuts();
         }
 
+        s.verifyStates();
+
         if (changed) {
             // This will send a notification to the launcher, and also save .
             s.packageShortcutsChanged(getPackageName(), getPackageUserId());
@@ -768,6 +776,7 @@
             }
             removeOrphans();
         }
+        adjustRanks();
         return changed;
     }
 
@@ -804,7 +813,6 @@
                 deleteDynamicWithId(shortcut.getId());
             }
         }
-        service.verifyStates();
 
         return changed;
     }
@@ -829,7 +837,7 @@
         if (!a.isManifestShortcut() && b.isManifestShortcut()) {
             return 1;
         }
-        return a.getRank() - b.getRank();
+        return Integer.compare(a.getRank(), b.getRank());
     };
 
     /**
@@ -837,8 +845,6 @@
      * contain "floating" shortcuts because they don't belong on any activities.
      */
     private ArrayMap<ComponentName, ArrayList<ShortcutInfo>> sortShortcutsToActivities() {
-        final int maxShortcuts = mShortcutUser.mService.getMaxActivityShortcuts();
-
         final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> activitiesToShortcuts
                 = new ArrayMap<>();
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
@@ -851,7 +857,7 @@
 
             ArrayList<ShortcutInfo> list = activitiesToShortcuts.get(activity);
             if (list == null) {
-                list = new ArrayList<>(maxShortcuts * 2);
+                list = new ArrayList<>();
                 activitiesToShortcuts.put(activity, list);
             }
             list.add(si);
@@ -976,6 +982,96 @@
         }
     }
 
+    /** Clears the implicit ranks for all shortcuts. */
+    public void clearAllImplicitRanks() {
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+            si.clearImplicitRankAndRankChangedFlag();
+        }
+    }
+
+    /**
+     * Used to sort shortcuts for rank auto-adjusting.
+     */
+    final Comparator<ShortcutInfo> mShortcutRankComparator = (ShortcutInfo a, ShortcutInfo b) -> {
+        // First, sort by rank.
+        int ret = Integer.compare(a.getRank(), b.getRank());
+        if (ret != 0) {
+            return ret;
+        }
+        // When ranks are tie, then prioritize the ones that have just been assigned new ranks.
+        // e.g. when there are 3 shortcuts, "s1" "s2" and "s3" with rank 0, 1, 2 respectively,
+        // adding a shortcut "s4" with rank 1 will "insert" it between "s1" and "s2", because
+        // "s2" and "s4" have the same rank 1 but s4 has isRankChanged() set.
+        // Similarly, updating s3's rank to 1 will insert it between s1 and s2.
+        if (a.isRankChanged() != b.isRankChanged()) {
+            return a.isRankChanged() ? -1 : 1;
+        }
+        // If they're still tie, sort by implicit rank -- i.e. preserve the order in which
+        // they're passed to the API.
+        ret = Integer.compare(a.getImplicitRank(), b.getImplicitRank());
+        if (ret != 0) {
+            return ret;
+        }
+        // If they're stil tie, just sort by their IDs.
+        // This may happen with updateShortcuts() -- see
+        // the testUpdateShortcuts_noManifestShortcuts() test.
+        return a.getId().compareTo(b.getId());
+    };
+
+    /**
+     * Re-calculate the ranks for all shortcuts.
+     */
+    public void adjustRanks() {
+        final ShortcutService s = mShortcutUser.mService;
+        final long now = s.injectCurrentTimeMillis();
+
+        // First, clear ranks for floating shortcuts.
+        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+            final ShortcutInfo si = mShortcuts.valueAt(i);
+            if (si.isFloating()) {
+                if (si.getRank() != 0) {
+                    si.setTimestamp(now);
+                    si.setRank(0);
+                }
+            }
+        }
+
+        // Then adjust ranks.  Ranks are unique for each activity, so we first need to sort
+        // shortcuts to each activity.
+        // Then sort the shortcuts within each activity with mShortcutRankComparator, and
+        // assign ranks from 0.
+        final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> all =
+                sortShortcutsToActivities();
+        for (int outer = all.size() - 1; outer >= 0; outer--) { // For each activity.
+            final ArrayList<ShortcutInfo> list = all.valueAt(outer);
+
+            // Sort by ranks and other signals.
+            Collections.sort(list, mShortcutRankComparator);
+
+            int rank = 0;
+
+            final int size = list.size();
+            for (int i = 0; i < size; i++) {
+                final ShortcutInfo si = list.get(i);
+                if (si.isManifestShortcut()) {
+                    // Don't adjust ranks for manifest shortcuts.
+                    continue;
+                }
+                // At this point, it must be dynamic.
+                if (!si.isDynamic()) {
+                    s.wtf("Non-dynamic shortcut found.");
+                    continue;
+                }
+                final int thisRank = rank++;
+                if (si.getRank() != thisRank) {
+                    si.setTimestamp(now);
+                    si.setRank(thisRank);
+                }
+            }
+        }
+    }
+
     public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
         pw.println();
 
@@ -1087,7 +1183,6 @@
         ShortcutService.writeAttr(out, ATTR_DISABLED_MESSAGE_RES_NAME,
                 si.getDisabledMessageResName());
         ShortcutService.writeAttr(out, ATTR_INTENT, si.getIntentNoExtras());
-        ShortcutService.writeAttr(out, ATTR_RANK, si.getRank());
         ShortcutService.writeAttr(out, ATTR_TIMESTAMP,
                 si.getLastChangedTimestamp());
         if (forBackup) {
@@ -1097,6 +1192,10 @@
                             ~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
                             | ShortcutInfo.FLAG_DYNAMIC));
         } else {
+            // When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
+            // as dynamic.
+            ShortcutService.writeAttr(out, ATTR_RANK, si.getRank());
+
             ShortcutService.writeAttr(out, ATTR_FLAGS, si.getFlags());
             ShortcutService.writeAttr(out, ATTR_ICON_RES_ID, si.getIconResourceId());
             ShortcutService.writeAttr(out, ATTR_ICON_RES_NAME, si.getIconResName());
@@ -1272,35 +1371,74 @@
                 sortShortcutsToActivities();
 
         // Make sure each activity won't have more than max shortcuts.
-        for (int i = all.size() - 1; i >= 0; i--) {
-            if (all.valueAt(i).size() > mShortcutUser.mService.getMaxActivityShortcuts()) {
+        for (int outer = all.size() - 1; outer >= 0; outer--) {
+            final ArrayList<ShortcutInfo> list = all.valueAt(outer);
+            if (list.size() > mShortcutUser.mService.getMaxActivityShortcuts()) {
                 failed = true;
-                Log.e(TAG, "Package " + getPackageName() + ": activity " + all.keyAt(i)
-                        + " has " + all.valueAt(i).size() + " shortcuts.");
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": activity " + all.keyAt(outer)
+                        + " has " + all.valueAt(outer).size() + " shortcuts.");
             }
+
+            // Sort by rank.
+            Collections.sort(list, (a, b) -> Integer.compare(a.getRank(), b.getRank()));
+
+            // Split into two arrays for each kind.
+            final ArrayList<ShortcutInfo> dynamicList = new ArrayList<>(list);
+            dynamicList.removeIf((si) -> !si.isDynamic());
+
+            final ArrayList<ShortcutInfo> manifestList = new ArrayList<>(list);
+            dynamicList.removeIf((si) -> !si.isManifestShortcut());
+
+            verifyRanksSequential(dynamicList);
+            verifyRanksSequential(manifestList);
         }
 
+        // Verify each shortcut's status.
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
             if (!(si.isManifestShortcut() || si.isDynamic() || si.isPinned())) {
                 failed = true;
-                Log.e(TAG, "Package " + getPackageName() + ": shortcut " + si.getId()
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is not manifest, dynamic or pinned.");
             }
+            if (si.isManifestShortcut() && si.isDynamic()) {
+                failed = true;
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+                        + " is both dynamic and manifest at the same time.");
+            }
             if (si.getActivity() == null) {
                 failed = true;
-                Log.e(TAG, "Package " + getPackageName() + ": shortcut " + si.getId()
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has null activity.");
             }
             if ((si.isDynamic() || si.isManifestShortcut()) && !si.isEnabled()) {
                 failed = true;
-                Log.e(TAG, "Package " + getPackageName() + ": shortcut " + si.getId()
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " is not floating, but is disabled.");
             }
+            if (si.isFloating() && si.getRank() != 0) {
+                failed = true;
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+                        + " is floating, but has rank=" + si.getRank());
+            }
         }
 
         if (failed) {
             throw new IllegalStateException("See logcat for errors");
         }
     }
+
+    private boolean verifyRanksSequential(List<ShortcutInfo> list) {
+        boolean failed = false;
+
+        for (int i = 0; i < list.size(); i++) {
+            final ShortcutInfo si = list.get(i);
+            if (si.getRank() != i) {
+                failed = true;
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+                        + " rank=" + si.getRank() + " but expected to be "+ i);
+            }
+        }
+        return failed;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java
index 470d4af..c349b75 100644
--- a/services/core/java/com/android/server/pm/ShortcutParser.java
+++ b/services/core/java/com/android/server/pm/ShortcutParser.java
@@ -24,10 +24,10 @@
 import android.content.pm.ShortcutInfo;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
-import android.net.Uri;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.Slog;
 import android.util.Xml;
 
@@ -48,10 +48,12 @@
     private static final boolean DEBUG = ShortcutService.DEBUG || false; // DO NOT SUBMIT WITH TRUE
 
     @VisibleForTesting
-    static final String METADATA_KEY = "android.pm.Shortcuts";
+    static final String METADATA_KEY = "android.app.shortcuts";
 
     private static final String TAG_SHORTCUTS = "shortcuts";
     private static final String TAG_SHORTCUT = "shortcut";
+    private static final String TAG_INTENT = "intent";
+    private static final String TAG_CATEGORIES = "categories";
 
     @Nullable
     public static List<ShortcutInfo> parseShortcuts(ShortcutService service,
@@ -60,10 +62,17 @@
 
         List<ShortcutInfo> result = null;
 
-        if (pi != null && pi.activities != null) {
-            for (ActivityInfo activityInfo : pi.activities) {
-                result = parseShortcutsOneFile(service, activityInfo, packageName, userId, result);
+        try {
+            if (pi != null && pi.activities != null) {
+                for (ActivityInfo activityInfo : pi.activities) {
+                    result = parseShortcutsOneFile(service, activityInfo, packageName, userId, result);
+                }
             }
+        } catch (RuntimeException e) {
+            // Resource ID mismatch may cause various runtime exceptions when parsing XMLs.
+            service.wtf(
+                    "Exception caught while parsing shortcut XML for package=" + packageName, e);
+            return null;
         }
         return result;
     }
@@ -89,49 +98,132 @@
             final int maxShortcuts = service.getMaxActivityShortcuts();
             int numShortcuts = 0;
 
+            // We instantiate ShortcutInfo at <shortcut>, but we add it to the list at </shortcut>,
+            // after parsing <intent>.  We keep the current one in here.
+            ShortcutInfo currentShortcut = null;
+
+            Set<String> categories = null;
+
             outer:
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                     && (type != XmlPullParser.END_TAG || parser.getDepth() > 0)) {
+                final int depth = parser.getDepth();
+                final String tag = parser.getName();
+
+                // When a shortcut tag is closing, publish.
+                if ((type == XmlPullParser.END_TAG) && (depth == 2) && (TAG_SHORTCUT.equals(tag))) {
+                    if (currentShortcut == null) {
+                        // Shortcut was invalid.
+                        continue;
+                    }
+                    final ShortcutInfo si = currentShortcut;
+                    currentShortcut = null; // Make sure to null out for the next iteration.
+
+                    if (si.getIntent() == null) {
+                        Log.e(TAG, "Shortcut " + si.getId() + " has no intent. Skipping it.");
+                        continue;
+                    }
+
+                    if (numShortcuts >= maxShortcuts) {
+                        Log.e(TAG, "More than " + maxShortcuts + " shortcuts found for "
+                                + activityInfo.getComponentName() + ". Skipping the rest.");
+                        return result;
+                    }
+                    if (categories != null) {
+                        si.setCategories(categories);
+                        categories = null;
+                    }
+
+                    if (result == null) {
+                        result = new ArrayList<>();
+                    }
+                    result.add(si);
+                    numShortcuts++;
+                    rank++;
+                    if (ShortcutService.DEBUG) {
+                        Slog.d(TAG, "Shortcut added: " + si.toInsecureString());
+                    }
+                    continue;
+                }
+
+                // Otherwise, just look at start tags.
                 if (type != XmlPullParser.START_TAG) {
                     continue;
                 }
-                final int depth = parser.getDepth();
-                final String tag = parser.getName();
 
                 if (depth == 1 && TAG_SHORTCUTS.equals(tag)) {
                     continue; // Root tag.
                 }
                 if (depth == 2 && TAG_SHORTCUT.equals(tag)) {
                     final ShortcutInfo si = parseShortcutAttributes(
-                            service, attrs, packageName, activity, userId, rank++);
+                            service, attrs, packageName, activity, userId, rank);
+                    if (si == null) {
+                        // Shortcut was invalid.
+                        continue;
+                    }
                     if (ShortcutService.DEBUG) {
-                        Slog.d(TAG, "Shortcut=" + si);
+                        Slog.d(TAG, "Shortcut found: " + si.toInsecureString());
                     }
                     if (result != null) {
                         for (int i = result.size() - 1; i >= 0; i--) {
                             if (si.getId().equals(result.get(i).getId())) {
-                                Slog.w(TAG, "Duplicate shortcut ID detected, skipping.");
+                                Log.e(TAG, "Duplicate shortcut ID detected. Skipping it.");
                                 continue outer;
                             }
                         }
                     }
+                    if (!si.isEnabled()) {
+                        // Just set the default intent to disabled shortcuts.
+                        si.setIntent(new Intent(Intent.ACTION_VIEW));
+                    }
+                    currentShortcut = si;
+                    categories = null;
+                    continue;
+                }
+                if (depth == 3 && TAG_INTENT.equals(tag)) {
+                    if ((currentShortcut == null)
+                            || (currentShortcut.getIntentNoExtras() != null)
+                            || !currentShortcut.isEnabled()) {
+                        Log.e(TAG, "Ignoring excessive intent tag.");
+                        continue;
+                    }
 
-                    if (si != null) {
-                        if (numShortcuts >= maxShortcuts) {
-                            Slog.w(TAG, "More than " + maxShortcuts + " shortcuts found for "
-                                    + activityInfo.getComponentName() + ", ignoring the rest.");
-                            return result;
-                        }
-
-                        if (result == null) {
-                            result = new ArrayList<>();
-                        }
-                        result.add(si);
-                        numShortcuts++;
+                    final Intent intent = Intent.parseIntent(service.mContext.getResources(),
+                            parser, attrs);
+                    if (TextUtils.isEmpty(intent.getAction())) {
+                        Log.e(TAG, "Shortcut intent action must be provided. activity=" + activity);
+                        continue;
+                    }
+                    try {
+                        currentShortcut.setIntent(intent);
+                    } catch (RuntimeException e) {
+                        // This shouldn't happen because intents in XML can't have complicated
+                        // extras, but just in case Intent.parseIntent() supports such a thing one
+                        // day.
+                        Log.e(TAG, "Shortcut's extras contain un-persistable values. Skipping it.");
+                        continue;
                     }
                     continue;
                 }
-                Slog.w(TAG, "Unknown tag " + tag);
+                if (depth == 3 && TAG_CATEGORIES.equals(tag)) {
+                    if ((currentShortcut == null)
+                            || (currentShortcut.getCategories() != null)) {
+                        continue;
+                    }
+                    final String name = parseCategories(service, attrs);
+                    if (TextUtils.isEmpty(name)) {
+                        Log.e(TAG, "Empty category found. activity=" + activity);
+                        continue;
+                    }
+
+                    if (categories == null) {
+                        categories = new ArraySet<>();
+                    }
+                    categories.add(name);
+                    continue;
+                }
+
+                Log.w(TAG, "Unknown tag " + tag + " at depth " + depth);
             }
         } finally {
             if (parser != null) {
@@ -141,6 +233,16 @@
         return result;
     }
 
+    private static String parseCategories(ShortcutService service, AttributeSet attrs) {
+        final TypedArray sa = service.mContext.getResources().obtainAttributes(attrs,
+                R.styleable.ShortcutCategories);
+        try {
+            return sa.getString(R.styleable.ShortcutCategories_name);
+        } finally {
+            sa.recycle();
+        }
+    }
+
     private static ShortcutInfo parseShortcutAttributes(ShortcutService service,
             AttributeSet attrs, String packageName, ComponentName activity,
             @UserIdInt int userId, int rank) {
@@ -149,14 +251,11 @@
         try {
             final String id = sa.getString(R.styleable.Shortcut_shortcutId);
             final boolean enabled = sa.getBoolean(R.styleable.Shortcut_enabled, true);
-            final int iconResId = sa.getResourceId(R.styleable.Shortcut_shortcutIcon, 0);
+            final int iconResId = sa.getResourceId(R.styleable.Shortcut_icon, 0);
             final int titleResId = sa.getResourceId(R.styleable.Shortcut_shortcutShortLabel, 0);
             final int textResId = sa.getResourceId(R.styleable.Shortcut_shortcutLongLabel, 0);
             final int disabledMessageResId = sa.getResourceId(
                     R.styleable.Shortcut_shortcutDisabledMessage, 0);
-            final String categories = sa.getString(R.styleable.Shortcut_shortcutCategories);
-            String intentAction = sa.getString(R.styleable.Shortcut_shortcutIntentAction);
-            final String intentData = sa.getString(R.styleable.Shortcut_shortcutIntentData);
 
             if (TextUtils.isEmpty(id)) {
                 Slog.w(TAG, "Shortcut ID must be provided. activity=" + activity);
@@ -166,31 +265,6 @@
                 Slog.w(TAG, "Shortcut title must be provided. activity=" + activity);
                 return null;
             }
-            if (TextUtils.isEmpty(intentAction)) {
-                if (enabled) {
-                    Slog.w(TAG, "Shortcut intent action must be provided. activity=" + activity);
-                    return null;
-                } else {
-                    // Disabled shortcut doesn't have to have an action, but just set VIEW as the
-                    // default.
-                    intentAction = Intent.ACTION_VIEW;
-                }
-            }
-
-            final ArraySet<String> categoriesSet;
-            if (categories == null) {
-                categoriesSet = null;
-            } else {
-                final String[] arr = categories.split(":");
-                categoriesSet = new ArraySet<>(arr.length);
-                for (String v : arr) {
-                    categoriesSet.add(v);
-                }
-            }
-            final Intent intent = new Intent(intentAction);
-            if (!TextUtils.isEmpty(intentData)) {
-                intent.setData(Uri.parse(intentData));
-            }
 
             return createShortcutFromManifest(
                     service,
@@ -201,8 +275,6 @@
                     titleResId,
                     textResId,
                     disabledMessageResId,
-                    categoriesSet,
-                    intent,
                     rank,
                     iconResId,
                     enabled);
@@ -213,8 +285,8 @@
 
     private static ShortcutInfo createShortcutFromManifest(ShortcutService service,
             @UserIdInt int userId, String id, String packageName, ComponentName activityComponent,
-            int titleResId, int textResId, int disabledMessageResId, Set<String> categories,
-            Intent intent, int rank, int iconResId, boolean enabled) {
+            int titleResId, int textResId, int disabledMessageResId,
+            int rank, int iconResId, boolean enabled) {
 
         final int flags =
                 (enabled ? ShortcutInfo.FLAG_MANIFEST : ShortcutInfo.FLAG_DISABLED)
@@ -238,8 +310,8 @@
                 null, // disabled message string
                 disabledMessageResId,
                 null, // disabled message res name
-                categories,
-                intent,
+                null, // categories
+                null, // intent
                 null, // intent extras
                 rank,
                 null, // extras
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 5769402..be8eeed 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -114,7 +114,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
@@ -223,7 +222,7 @@
         String KEY_MAX_ICON_DIMENSION_DP_LOWRAM = "max_icon_dimension_dp_lowram";
 
         /**
-         * Key name for the max dynamic shortcuts per app. (int)
+         * Key name for the max dynamic shortcuts per activity. (int)
          */
         String KEY_MAX_SHORTCUTS = "max_shortcuts";
 
@@ -1479,6 +1478,12 @@
         return (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
     }
 
+    private void assignImplicitRanks(List<ShortcutInfo> shortcuts) {
+        for (int i = shortcuts.size() - 1; i >= 0; i--) {
+            shortcuts.get(i).setImplicitRank(i);
+        }
+    }
+
     // === APIs ===
 
     @Override
@@ -1501,7 +1506,10 @@
                 return false;
             }
 
-            // Validate the shortcuts.
+            // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
+            ps.clearAllImplicitRanks();
+            assignImplicitRanks(newShortcuts);
+
             for (int i = 0; i < size; i++) {
                 fixUpIncomingShortcutInfo(newShortcuts.get(i), /* forUpdate= */ false);
             }
@@ -1514,6 +1522,9 @@
                 final ShortcutInfo newShortcut = newShortcuts.get(i);
                 ps.addOrUpdateDynamicShortcut(newShortcut);
             }
+
+            // Lastly, adjust the ranks.
+            ps.adjustRanks();
         }
         packageShortcutsChanged(packageName, userId);
 
@@ -1542,41 +1553,58 @@
                 return false;
             }
 
+            // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
+            ps.clearAllImplicitRanks();
+            assignImplicitRanks(newShortcuts);
+
             for (int i = 0; i < size; i++) {
                 final ShortcutInfo source = newShortcuts.get(i);
                 fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
 
                 final ShortcutInfo target = ps.findShortcutById(source.getId());
-                if (target != null) {
-                    if (target.isEnabled() != source.isEnabled()) {
-                        Slog.w(TAG,
-                                "ShortcutInfo.enabled cannot be changed with updateShortcuts()");
-                    }
+                if (target == null) {
+                    continue;
+                }
 
-                    final boolean replacingIcon = (source.getIcon() != null);
-                    if (replacingIcon) {
-                        removeIcon(userId, target);
-                    }
+                if (target.isEnabled() != source.isEnabled()) {
+                    Slog.w(TAG,
+                            "ShortcutInfo.enabled cannot be changed with updateShortcuts()");
+                }
 
-                    if (source.getActivity() != null &&
-                            !source.getActivity().equals(target.getActivity())) {
-                        // TODO When activity is changing, check the dynamic count.
-                    }
+                // When updating the rank, we need to insert between existing ranks, so set
+                // this setRankChanged, and also copy the implicit rank fo adjustRanks().
+                if (source.hasRank()) {
+                    target.setRankChanged();
+                    target.setImplicitRank(source.getImplicitRank());
+                }
 
-                    // Note copyNonNullFieldsFrom() does the "updatable with?" check too.
-                    target.copyNonNullFieldsFrom(source);
+                final boolean replacingIcon = (source.getIcon() != null);
+                if (replacingIcon) {
+                    removeIcon(userId, target);
+                }
 
-                    if (replacingIcon) {
-                        saveIconAndFixUpShortcut(userId, target);
-                    }
+                if (source.getActivity() != null &&
+                        !source.getActivity().equals(target.getActivity())) {
+                    // TODO When activity is changing, check the dynamic count.
+                }
 
-                    // When we're updating any resource related fields, re-extract the res names and
-                    // the values.
-                    if (replacingIcon || source.hasStringResources()) {
-                        fixUpShortcutResourceNamesAndValues(target);
-                    }
+                // Note copyNonNullFieldsFrom() does the "updatable with?" check too.
+                target.copyNonNullFieldsFrom(source);
+                target.setTimestamp(injectCurrentTimeMillis());
+
+                if (replacingIcon) {
+                    saveIconAndFixUpShortcut(userId, target);
+                }
+
+                // When we're updating any resource related fields, re-extract the res names and
+                // the values.
+                if (replacingIcon || source.hasStringResources()) {
+                    fixUpShortcutResourceNamesAndValues(target);
                 }
             }
+
+            // Lastly, adjust the ranks.
+            ps.adjustRanks();
         }
         packageShortcutsChanged(packageName, userId);
 
@@ -1600,6 +1628,10 @@
 
             ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_ADD);
 
+            // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
+            ps.clearAllImplicitRanks();
+            assignImplicitRanks(newShortcuts);
+
             // Throttling.
             if (!ps.tryApiCall()) {
                 return false;
@@ -1610,9 +1642,16 @@
                 // Validate the shortcut.
                 fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false);
 
+                // When ranks are changing, we need to insert between ranks, so set the
+                // "rank changed" flag.
+                newShortcut.setRankChanged();
+
                 // Add it.
                 ps.addOrUpdateDynamicShortcut(newShortcut);
             }
+
+            // Lastly, adjust the ranks.
+            ps.adjustRanks();
         }
         packageShortcutsChanged(packageName, userId);
 
@@ -1637,6 +1676,9 @@
                         disabledMessage, disabledMessageResId,
                         /* overrideImmutable=*/ false);
             }
+
+            // We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
+            ps.adjustRanks();
         }
         packageShortcutsChanged(packageName, userId);
 
@@ -1677,6 +1719,9 @@
                 ps.deleteDynamicWithId(
                         Preconditions.checkStringNotEmpty((String) shortcutIds.get(i)));
             }
+
+            // We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
+            ps.adjustRanks();
         }
         packageShortcutsChanged(packageName, userId);
 
@@ -2328,6 +2373,7 @@
         } finally {
             logDurationStat(Stats.CHECK_PACKAGE_CHANGES, start);
         }
+        verifyStates();
     }
 
     private void handlePackageAdded(String packageName, @UserIdInt int userId) {
@@ -2339,6 +2385,7 @@
             user.attemptToRestoreIfNeededAndSave(this, packageName, userId);
             user.handlePackageAddedOrUpdated(packageName);
         }
+        verifyStates();
     }
 
     private void handlePackageUpdateFinished(String packageName, @UserIdInt int userId) {
@@ -2354,6 +2401,7 @@
                 user.handlePackageAddedOrUpdated(packageName);
             }
         }
+        verifyStates();
     }
 
     private void handlePackageRemoved(String packageName, @UserIdInt int packageUserId) {
@@ -2362,6 +2410,8 @@
                     packageUserId));
         }
         cleanUpPackageForAllLoadedUsers(packageName, packageUserId);
+
+        verifyStates();
     }
 
     private void handlePackageDataCleared(String packageName, int packageUserId) {
@@ -2370,6 +2420,8 @@
                     packageUserId));
         }
         cleanUpPackageForAllLoadedUsers(packageName, packageUserId);
+
+        verifyStates();
     }
 
     // === PackageManager interaction ===
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c2c569e..ced44fa 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -67,6 +67,8 @@
 import android.os.UserManagerInternal;
 import android.os.UserManagerInternal.UserRestrictionsListener;
 import android.os.storage.StorageManager;
+import android.security.GateKeeper;
+import android.service.gatekeeper.IGateKeeperService;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -90,6 +92,7 @@
 import com.android.internal.util.XmlUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.LocalServices;
+import com.android.server.SystemService;
 import com.android.server.am.UserState;
 
 import libcore.io.IoUtils;
@@ -122,6 +125,7 @@
  * </ul>
  */
 public class UserManagerService extends IUserManager.Stub {
+
     private static final String LOG_TAG = "UserManagerService";
     static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
     private static final boolean DBG_WITH_STACKTRACE = false; // DO NOT SUBMIT WITH TRUE
@@ -370,6 +374,31 @@
         }
     }
 
+    public static class LifeCycle extends SystemService {
+
+        private UserManagerService mUms;
+
+        /**
+         * @param context
+         */
+        public LifeCycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            mUms = UserManagerService.getInstance();
+            publishBinderService(Context.USER_SERVICE, mUms);
+        }
+
+        @Override
+        public void onBootPhase(int phase) {
+            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+                mUms.cleanupPartialUsers();
+            }
+        }
+    }
+
     @VisibleForTesting
     UserManagerService(File dataDir) {
         this(null, null, new Object(), dataDir);
@@ -411,25 +440,6 @@
     }
 
     void systemReady() {
-        // Prune out any partially created, partially removed and ephemeral users.
-        ArrayList<UserInfo> partials = new ArrayList<>();
-        synchronized (mUsersLock) {
-            final int userSize = mUsers.size();
-            for (int i = 0; i < userSize; i++) {
-                UserInfo ui = mUsers.valueAt(i).info;
-                if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) {
-                    partials.add(ui);
-                }
-            }
-        }
-        final int partialsSize = partials.size();
-        for (int i = 0; i < partialsSize; i++) {
-            UserInfo ui = partials.get(i);
-            Slog.w(LOG_TAG, "Removing partially created user " + ui.id
-                    + " (name=" + ui.name + ")");
-            removeUserState(ui.id);
-        }
-
         mAppOpsService = IAppOpsService.Stub.asInterface(
                 ServiceManager.getService(Context.APP_OPS_SERVICE));
 
@@ -452,6 +462,27 @@
                 null, mHandler);
     }
 
+    void cleanupPartialUsers() {
+        // Prune out any partially created, partially removed and ephemeral users.
+        ArrayList<UserInfo> partials = new ArrayList<>();
+        synchronized (mUsersLock) {
+            final int userSize = mUsers.size();
+            for (int i = 0; i < userSize; i++) {
+                UserInfo ui = mUsers.valueAt(i).info;
+                if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) {
+                    partials.add(ui);
+                }
+            }
+        }
+        final int partialsSize = partials.size();
+        for (int i = 0; i < partialsSize; i++) {
+            UserInfo ui = partials.get(i);
+            Slog.w(LOG_TAG, "Removing partially created user " + ui.id
+                    + " (name=" + ui.name + ")");
+            removeUserState(ui.id);
+        }
+    }
+
     @Override
     public String getUserAccount(int userId) {
         checkManageUserAndAcrossUsersFullPermission("get user account");
@@ -1277,14 +1308,16 @@
         }
 
         if (mAppOpsService != null) { // We skip it until system-ready.
-            final long token = Binder.clearCallingIdentity();
-            try {
-                mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
-            } catch (RemoteException e) {
-                Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
+                    } catch (RemoteException e) {
+                        Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
+                    }
+                }
+            });
         }
 
         propagateUserRestrictionsLR(userId, effective, prevAppliedRestrictions);
@@ -2272,7 +2305,7 @@
      */
     @Override
     public UserInfo createRestrictedProfile(String name, int parentUserId) {
-        checkManageUsersPermission("setupRestrictedProfile");
+        checkManageOrCreateUsersPermission("setupRestrictedProfile");
         final UserInfo user = createProfileForUser(name, UserInfo.FLAG_RESTRICTED, parentUserId);
         if (user == null) {
             return null;
@@ -2479,8 +2512,23 @@
                 "Destroying key for user " + userHandle + " failed, continuing anyway", e);
         }
 
+        // Cleanup gatekeeper secure user id
+        try {
+            final IGateKeeperService gk = GateKeeper.getService();
+            if (gk != null) {
+                gk.clearSecureUserId(userHandle);
+            }
+        } catch (Exception ex) {
+            Slog.w(LOG_TAG, "unable to clear GK secure user id");
+        }
+
         // Cleanup package manager settings
         mPm.cleanUpUser(this, userHandle);
+
+        // Clean up all data before removing metadata
+        mPm.destroyUserData(userHandle,
+                StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+
         // Remove this user from the list
         synchronized (mUsersLock) {
             mUsers.remove(userHandle);
@@ -2503,12 +2551,6 @@
         AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
         userFile.delete();
         updateUserIds();
-
-        // Now that we've purged all the metadata above, destroy the actual data
-        // on disk; if we battery pull in here we'll finish cleaning up when
-        // reconciling after reboot.
-        mPm.destroyUserData(userHandle,
-                StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
     }
 
     private void sendProfileRemovedBroadcast(int parentUserId, int removedUserId) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 414d165..c082143 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -429,7 +429,7 @@
                     if (newValue) {
                         PersistentDataBlockManager manager = (PersistentDataBlockManager) context
                                 .getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
-                        if (manager != null) {
+                        if (manager != null && manager.getOemUnlockEnabled()) {
                             manager.setOemUnlockEnabled(false);
                         }
                     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f9f0fd9..ea47303 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -7268,7 +7268,7 @@
 
     private boolean areSystemNavigationKeysEnabled() {
         return Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.SYSTEM_NAVIGATION_KEYS_ENABLED, 0) == 1;
+                Settings.Global.SYSTEM_NAVIGATION_KEYS_ENABLED, 1) == 1;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 1bbb9f5..ad87a88 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -43,6 +43,9 @@
 
     /**
      * Set the current VR mode state.
+     * <p/>
+     * This may delay the mode change slightly during application transitions to avoid frequently
+     * tearing down VrListenerServices unless necessary.
      *
      * @param enabled {@code true} to enable VR mode.
      * @param packageName The package name of the requested VrListenerService to bind.
@@ -52,6 +55,18 @@
     public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName,
             int userId, @NonNull ComponentName calling);
 
+    /**
+     * Set the current VR mode state immediately.
+     *
+     * @param enabled {@code true} to enable VR mode.
+     * @param packageName The package name of the requested VrListenerService to bind.
+     * @param userId the user requesting the VrListenerService component.
+     * @param calling the component currently using VR mode, or null to leave unchanged.
+     */
+    public abstract void setVrModeImmediate(boolean enabled, @NonNull ComponentName packageName,
+            int userId, @NonNull ComponentName calling);
+
+
    /**
     * Return NO_ERROR if the given package is installed on the device and enabled as a
     * VrListenerService for the given current user, or a negative error code indicating a failure.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index b4c4bd8..5fefd4c 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -218,7 +218,6 @@
                     String packageName = mNotificationAccessPackageToUserId.keyAt(i);
                     revokeNotificationListenerAccess(packageName, grantUserId);
                     revokeNotificationPolicyAccess(packageName);
-                    revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
                     mNotificationAccessPackageToUserId.removeAt(i);
                 }
             }
@@ -227,7 +226,6 @@
                 if (!packageNames.contains(pkg)) {
                     revokeNotificationListenerAccess(pkg, currentUserId);
                     revokeNotificationPolicyAccess(pkg);
-                    revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
                     mNotificationAccessPackageToUserId.remove(pkg);
                 }
             }
@@ -235,7 +233,6 @@
                 if (!allowed.contains(pkg)) {
                     grantNotificationPolicyAccess(pkg);
                     grantNotificationListenerAccess(pkg, currentUserId);
-                    grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
                     mNotificationAccessPackageToUserId.put(pkg, currentUserId);
                 }
             }
@@ -373,7 +370,13 @@
         @Override
         public void setVrMode(boolean enabled, ComponentName packageName, int userId,
                 ComponentName callingPackage) {
-            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
+            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, false);
+        }
+
+        @Override
+        public void setVrModeImmediate(boolean enabled, ComponentName packageName, int userId,
+                ComponentName callingPackage) {
+            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage, true);
         }
 
         @Override
@@ -754,22 +757,6 @@
                 flatSettings, userId);
     }
 
-    private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
-        // Don't clobber the user if permission set in current state explicitly
-        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
-            mContext.getPackageManager().grantRuntimePermission(pkg,
-                    Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
-        }
-    }
-
-    private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
-        // Don't clobber the user if permission set in current state explicitly
-        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
-            mContext.getPackageManager().revokeRuntimePermission(pkg,
-                    Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
-        }
-    }
-
     private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
         final int flags = mContext.getPackageManager().getPermissionFlags(
                 permission, pkg, new UserHandle(userId));
@@ -916,11 +903,11 @@
      */
 
     private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
-            int userId, @NonNull ComponentName callingPackage) {
+            int userId, @NonNull ComponentName callingPackage, boolean immediate) {
 
         synchronized (mLock) {
 
-            if (!enabled && mCurrentVrService != null) {
+            if (!enabled && mCurrentVrService != null && !immediate) {
                 // If we're transitioning out of VR mode, delay briefly to avoid expensive HAL calls
                 // and service bind/unbind in case we are immediately switching to another VR app.
                 if (mPendingState == null) {
diff --git a/services/core/java/com/android/server/webkit/SystemImpl.java b/services/core/java/com/android/server/webkit/SystemImpl.java
index 361f0d4..bb76449 100644
--- a/services/core/java/com/android/server/webkit/SystemImpl.java
+++ b/services/core/java/com/android/server/webkit/SystemImpl.java
@@ -270,5 +270,6 @@
 
     // flags declaring we want extra info from the package manager for webview providers
     private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
-            | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+            | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
+            | PackageManager.MATCH_UNINSTALLED_PACKAGES;
 }
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 9b971e0..846169c 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -63,6 +63,7 @@
         mWebViewUpdatedReceiver = new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
+                    int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                     switch (intent.getAction()) {
                         case Intent.ACTION_PACKAGE_REMOVED:
                             // When a package is replaced we will receive two intents, one
@@ -73,24 +74,22 @@
                             // run the update-logic twice.
                             if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) return;
                             mImpl.packageStateChanged(packageNameFromIntent(intent),
-                                    PACKAGE_REMOVED);
+                                    PACKAGE_REMOVED, userId);
                             break;
                         case Intent.ACTION_PACKAGE_CHANGED:
                             // Ensure that we only heed PACKAGE_CHANGED intents if they change an
                             // entire package, not just a component
                             if (entirePackageChanged(intent)) {
                                 mImpl.packageStateChanged(packageNameFromIntent(intent),
-                                        PACKAGE_CHANGED);
+                                        PACKAGE_CHANGED, userId);
                             }
                             break;
                         case Intent.ACTION_PACKAGE_ADDED:
                             mImpl.packageStateChanged(packageNameFromIntent(intent),
                                     (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)
-                                     ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED));
+                                     ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED), userId);
                             break;
                         case Intent.ACTION_USER_ADDED:
-                            int userId =
-                                intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                             mImpl.handleNewUser(userId);
                             break;
                     }
@@ -105,11 +104,14 @@
         for (WebViewProviderInfo provider : mImpl.getWebViewPackages()) {
             filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
         }
-        getContext().registerReceiver(mWebViewUpdatedReceiver, filter);
+
+        getContext().registerReceiverAsUser(mWebViewUpdatedReceiver, UserHandle.ALL, filter,
+                null /* broadcast permission */, null /* handler */);
 
         IntentFilter userAddedFilter = new IntentFilter();
         userAddedFilter.addAction(Intent.ACTION_USER_ADDED);
-        getContext().registerReceiver(mWebViewUpdatedReceiver, userAddedFilter);
+        getContext().registerReceiverAsUser(mWebViewUpdatedReceiver, UserHandle.ALL,
+                userAddedFilter, null /* broadcast permission */, null /* handler */);
 
         publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/);
     }
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index ecab009..2cf1722 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -20,6 +20,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
+import android.os.UserHandle;
 import android.util.Base64;
 import android.util.Slog;
 import android.webkit.WebViewFactory;
@@ -49,7 +50,10 @@
         mWebViewUpdater = new WebViewUpdater(mContext, mSystemInterface);
     }
 
-    void packageStateChanged(String packageName, int changedState) {
+    void packageStateChanged(String packageName, int changedState, int userId) {
+        // We don't early out here in different cases where we could potentially early-out (e.g. if
+        // we receive PACKAGE_CHANGED for another user than the system user) since that would
+        // complicate this logic further and open up for more edge cases.
         updateFallbackStateOnPackageChange(packageName, changedState);
         mWebViewUpdater.packageStateChanged(packageName, changedState);
     }
@@ -64,7 +68,7 @@
             if (provider.availableByDefault && !provider.isFallback) {
                 try {
                     PackageInfo packageInfo = mSystemInterface.getPackageInfoForProvider(provider);
-                    if (isEnabledPackage(packageInfo)
+                    if (isInstalledPackage(packageInfo) && isEnabledPackage(packageInfo)
                             && mWebViewUpdater.isValidProvider(provider, packageInfo)) {
                         return true;
                     }
@@ -103,7 +107,7 @@
     }
 
     WebViewProviderInfo[] getValidWebViewPackages() {
-        return mWebViewUpdater.getValidWebViewPackages();
+        return mWebViewUpdater.getValidAndInstalledWebViewPackages();
     }
 
     WebViewProviderInfo[] getWebViewPackages() {
@@ -254,6 +258,12 @@
                                     // (not if it has been enabled/disabled).
                                     return;
                                 }
+                                if (newPackage.packageName.equals(oldProviderName)
+                                        && (newPackage.lastUpdateTime
+                                            == mCurrentWebViewPackage.lastUpdateTime)) {
+                                    // If the chosen package hasn't been updated, then early-out
+                                    return;
+                                }
                             }
                             // Only trigger update actions if the updated package is the one
                             // that will be used, or the one that was in use before the
@@ -373,14 +383,15 @@
             }
         }
 
-        private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
+        private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos(boolean onlyInstalled) {
             WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
             List<ProviderAndPackageInfo> providers = new ArrayList<>();
             for(int n = 0; n < allProviders.length; n++) {
                 try {
                     PackageInfo packageInfo =
                         mSystemInterface.getPackageInfoForProvider(allProviders[n]);
-                    if (isValidProvider(allProviders[n], packageInfo)) {
+                    if ((!onlyInstalled || isInstalledPackage(packageInfo))
+                            && isValidProvider(allProviders[n], packageInfo)) {
                         providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
                     }
                 } catch (NameNotFoundException e) {
@@ -393,8 +404,9 @@
         /**
          * Fetch only the currently valid WebView packages.
          **/
-        public WebViewProviderInfo[] getValidWebViewPackages() {
-            ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
+        public WebViewProviderInfo[] getValidAndInstalledWebViewPackages() {
+            ProviderAndPackageInfo[] providersAndPackageInfos =
+                getValidWebViewPackagesAndInfos(true /* only fetch installed packages */);
             WebViewProviderInfo[] providers =
                 new WebViewProviderInfo[providersAndPackageInfos.length];
             for(int n = 0; n < providersAndPackageInfos.length; n++) {
@@ -421,29 +433,33 @@
          *
          */
         private PackageInfo findPreferredWebViewPackage() {
-            ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
+            ProviderAndPackageInfo[] providers =
+                getValidWebViewPackagesAndInfos(false /* onlyInstalled */);
 
             String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(mContext);
 
             // If the user has chosen provider, use that
             for (ProviderAndPackageInfo providerAndPackage : providers) {
                 if (providerAndPackage.provider.packageName.equals(userChosenProvider)
+                        && isInstalledPackage(providerAndPackage.packageInfo)
                         && isEnabledPackage(providerAndPackage.packageInfo)) {
                     return providerAndPackage.packageInfo;
                 }
             }
 
             // User did not choose, or the choice failed; use the most stable provider that is
-            // enabled and available by default (not through user choice).
+            // installed and enabled for the device owner, and available by default (not through
+            // user choice).
             for (ProviderAndPackageInfo providerAndPackage : providers) {
                 if (providerAndPackage.provider.availableByDefault
+                        && isInstalledPackage(providerAndPackage.packageInfo)
                         && isEnabledPackage(providerAndPackage.packageInfo)) {
                     return providerAndPackage.packageInfo;
                 }
             }
 
-            // Could not find any enabled package either, use the most stable and default-available
-            // provider.
+            // Could not find any installed and enabled package either, use the most stable and
+            // default-available provider.
             for (ProviderAndPackageInfo providerAndPackage : providers) {
                 if (providerAndPackage.provider.availableByDefault) {
                     return providerAndPackage.packageInfo;
@@ -642,4 +658,13 @@
         return packageInfo.applicationInfo.enabled;
     }
 
+    /**
+     * Return true if the package is installed and not hidden
+     */
+    private static boolean isInstalledPackage(PackageInfo packageInfo) {
+        return (((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0)
+            && ((packageInfo.applicationInfo.privateFlags
+                        & ApplicationInfo.PRIVATE_FLAG_HIDDEN) == 0));
+    }
+
 }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index f57e83aa..b907da6 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -72,6 +72,7 @@
     int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean layoutConfigChanges;
     boolean showForAllUsers;
+    int targetSdk;
 
     // The input dispatching timeout for this application token in nanoseconds.
     long inputDispatchingTimeoutNanos;
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index c4eca08..9d0fb61 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -28,6 +28,7 @@
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.hardware.input.InputManager;
+import android.os.Build;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Process;
@@ -289,7 +290,7 @@
         if (!targetWin.isPotentialDragTarget()) {
             return false;
         }
-        if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
+        if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0 || !targetWindowSupportsGlobalDrag(targetWin)) {
             // Drag is limited to the current window.
             if (mLocalWin != targetWin.mClient.asBinder()) {
                 return false;
@@ -300,6 +301,13 @@
                 mSourceUserId == UserHandle.getUserId(targetWin.getOwningUid());
     }
 
+    private boolean targetWindowSupportsGlobalDrag(WindowState targetWin) {
+        // Global drags are limited to system windows, and windows for apps that are targeting N and
+        // above.
+        return targetWin.mAppToken == null
+                || targetWin.mAppToken.targetSdk >= Build.VERSION_CODES.N;
+    }
+
     /* helper - send a ACTION_DRAG_STARTED event only if the window has not
      * previously been notified, i.e. it became visible after the drag operation
      * was begun.  This is a rare case.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8474fcf..36875123 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3420,7 +3420,7 @@
             int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId,
             int configChanges, boolean voiceInteraction, boolean launchTaskBehind,
             Rect taskBounds, Configuration config, int taskResizeMode, boolean alwaysFocusable,
-            boolean homeTask) {
+            boolean homeTask, int targetSdkVersion) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "addAppToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -3450,6 +3450,7 @@
             atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
             atoken.appFullscreen = fullscreen;
             atoken.showForAllUsers = showForAllUsers;
+            atoken.targetSdk = targetSdkVersion;
             atoken.requestedOrientation = requestedOrientation;
             atoken.layoutConfigChanges = (configChanges &
                     (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 1ae1a77..b53933e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -120,7 +120,7 @@
             // First, try to read from the legacy file.
             final File legacy = getLegacyConfigFileWithTestOverride();
 
-            final List<UserInfo> users = mUserManager.getUsers();
+            final List<UserInfo> users = mUserManager.getUsers(true);
 
             if (readLegacyOwnerFileLocked(legacy)) {
                 if (DEBUG) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index b21f5fb4..8f8ba1d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -475,7 +475,7 @@
         }
 
         traceBeginAndSlog("StartUserManagerService");
-        ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
+        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
         Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
 
         // Initialize attribute cache used to cache resources from packages.
diff --git a/services/tests/servicestests/res/drawable/icon3.png b/services/tests/servicestests/res/drawable/icon3.png
new file mode 100644
index 0000000..64eb294
--- /dev/null
+++ b/services/tests/servicestests/res/drawable/icon3.png
Binary files differ
diff --git a/services/tests/servicestests/res/xml/shortcut_1.xml b/services/tests/servicestests/res/xml/shortcut_1.xml
index f6d54fc..e3f9172 100644
--- a/services/tests/servicestests/res/xml/shortcut_1.xml
+++ b/services/tests/servicestests/res/xml/shortcut_1.xml
@@ -2,12 +2,17 @@
     <shortcut
         android:shortcutId="ms1"
         android:enabled="true"
-        android:shortcutIcon="@drawable/icon1"
+        android:icon="@drawable/icon1"
         android:shortcutShortLabel="@string/shortcut_title1"
         android:shortcutLongLabel="@string/shortcut_text1"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
-        android:shortcutCategories="android.shortcut.conversation:android.shortcut.media"
-        android:shortcutIntentAction="action1"
-        android:shortcutIntentData="data1"
-    />
+        >
+        <intent
+            android:action="action1"
+            android:data="data1"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+        <categories android:name="android.shortcut.media" />
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_1_alt.xml b/services/tests/servicestests/res/xml/shortcut_1_alt.xml
index bf14f49..2d5e8e7 100644
--- a/services/tests/servicestests/res/xml/shortcut_1_alt.xml
+++ b/services/tests/servicestests/res/xml/shortcut_1_alt.xml
@@ -17,12 +17,17 @@
     <shortcut
         android:shortcutId="ms1-alt"
         android:enabled="true"
-        android:shortcutIcon="@drawable/icon1"
+        android:icon="@drawable/icon1"
         android:shortcutShortLabel="@string/shortcut_title1"
         android:shortcutLongLabel="@string/shortcut_text1"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
-        android:shortcutCategories="android.shortcut.conversation:android.shortcut.media"
-        android:shortcutIntentAction="action1"
-        android:shortcutIntentData="data1"
-    />
+        >
+        <intent
+            android:action="action1"
+            android:data="data1"
+        >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+        <categories android:name="android.shortcut.media" />
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_1_disable.xml b/services/tests/servicestests/res/xml/shortcut_1_disable.xml
index 81a84b4..e3ee3a0 100644
--- a/services/tests/servicestests/res/xml/shortcut_1_disable.xml
+++ b/services/tests/servicestests/res/xml/shortcut_1_disable.xml
@@ -17,7 +17,7 @@
     <shortcut
         android:shortcutId="ms1"
         android:enabled="false"
-        android:shortcutIcon="@drawable/icon2"
+        android:icon="@drawable/icon2"
         android:shortcutShortLabel="@string/shortcut_title2"
         android:shortcutLongLabel="@string/shortcut_text2"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message2"
diff --git a/services/tests/servicestests/res/xml/shortcut_2.xml b/services/tests/servicestests/res/xml/shortcut_2.xml
index 96ed382..f7ea803 100644
--- a/services/tests/servicestests/res/xml/shortcut_2.xml
+++ b/services/tests/servicestests/res/xml/shortcut_2.xml
@@ -17,23 +17,32 @@
     <shortcut
         android:shortcutId="ms1"
         android:enabled="true"
-        android:shortcutIcon="@drawable/icon1"
+        android:icon="@drawable/icon1"
         android:shortcutShortLabel="@string/shortcut_title1"
         android:shortcutLongLabel="@string/shortcut_text1"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
-        android:shortcutCategories="android.shortcut.conversation:android.shortcut.media"
-        android:shortcutIntentAction="action1"
-        android:shortcutIntentData="http://a.b.c/"
-    />
+        >
+        <intent
+            android:action="action1"
+            android:data="http://a.b.c/"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+        <categories android:name="android.shortcut.media" />
+    </shortcut>
     <shortcut
         android:shortcutId="ms2"
         android:enabled="true"
-        android:shortcutIcon="@drawable/icon2"
+        android:icon="@drawable/icon2"
         android:shortcutShortLabel="@string/shortcut_title2"
         android:shortcutLongLabel="@string/shortcut_text2"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message2"
-        android:shortcutCategories="android.shortcut.conversation"
-        android:shortcutIntentAction="action2"
-        android:shortcutIntentData="http://a.b.c/2"
-    />
+        >
+        <intent
+            android:action="action2"
+            android:data="http://a.b.c/2"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_2_duplicate.xml b/services/tests/servicestests/res/xml/shortcut_2_duplicate.xml
index 2f814b7..b00ec60 100644
--- a/services/tests/servicestests/res/xml/shortcut_2_duplicate.xml
+++ b/services/tests/servicestests/res/xml/shortcut_2_duplicate.xml
@@ -17,11 +17,19 @@
     <shortcut
         android:shortcutId="ms1"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="action1"
-    />
+        >
+        <intent
+            android:action="action1"
+            >
+        </intent>
+    </shortcut>
     <shortcut
         android:shortcutId="ms1"
         android:shortcutShortLabel="@string/shortcut_title2"
-        android:shortcutIntentAction="action2"
-    />
+        >
+        <intent
+            android:action="action2"
+            >
+        </intent>
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_3.xml b/services/tests/servicestests/res/xml/shortcut_3.xml
new file mode 100644
index 0000000..432ca49
--- /dev/null
+++ b/services/tests/servicestests/res/xml/shortcut_3.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+    <shortcut
+        android:shortcutId="ms1"
+        android:enabled="true"
+        android:icon="@drawable/icon1"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        android:shortcutLongLabel="@string/shortcut_text1"
+        android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
+        >
+        <intent
+            android:action="action1"
+            android:data="http://a.b.c/"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+        <categories android:name="android.shortcut.media" />
+    </shortcut>
+    <shortcut
+        android:shortcutId="ms2"
+        android:enabled="true"
+        android:icon="@drawable/icon2"
+        android:shortcutShortLabel="@string/shortcut_title2"
+        android:shortcutLongLabel="@string/shortcut_text2"
+        android:shortcutDisabledMessage="@string/shortcut_disabled_message2"
+        >
+        <intent
+            android:action="action2"
+            android:data="http://a.b.c/2"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+    </shortcut>
+    <shortcut
+        android:shortcutId="ms3"
+        android:enabled="true"
+        android:icon="@drawable/icon3"
+        android:shortcutShortLabel="@string/shortcut_title2"
+        >
+        <intent android:action="action3" />
+    </shortcut>
+</shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_5.xml b/services/tests/servicestests/res/xml/shortcut_5.xml
index 56dba0e..9551100 100644
--- a/services/tests/servicestests/res/xml/shortcut_5.xml
+++ b/services/tests/servicestests/res/xml/shortcut_5.xml
@@ -17,37 +17,69 @@
     <shortcut
         android:shortcutId="ms1"
         android:enabled="true"
-        android:shortcutIcon="@drawable/icon1"
+        android:icon="@drawable/icon1"
         android:shortcutShortLabel="@string/shortcut_title1"
         android:shortcutLongLabel="@string/shortcut_text1"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
-        android:shortcutCategories="android.shortcut.conversation:android.shortcut.media"
-        android:shortcutIntentAction="action1"
-        android:shortcutIntentData="http://a.b.c/1"
-    />
+        >
+        <intent
+            android:action="action1"
+            android:data="http://a.b.c/1"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+        <categories android:name="android.shortcut.media" />
+    </shortcut>
     <shortcut
         android:shortcutId="ms2"
         android:enabled="true"
-        android:shortcutIcon="@drawable/icon2"
+        android:icon="@drawable/icon2"
         android:shortcutShortLabel="@string/shortcut_title2"
         android:shortcutLongLabel="@string/shortcut_text2"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message2"
-        android:shortcutCategories="android.shortcut.conversation"
-        android:shortcutIntentAction="action2"
-    />
+        >
+        <intent
+            android:action="action2"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+    </shortcut>
     <shortcut
         android:shortcutId="ms3"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
     <shortcut
         android:shortcutId="ms4"
-        android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        android:shortcutShortLabel="@string/shortcut_title2"
+        >
+        <intent
+            android:action="android.intent.action.VIEW2"
+            >
+        </intent>
+        <categories />
+        <categories android:name="" />
+        <categories android:name="cat" />
+    </shortcut>
     <shortcut
         android:shortcutId="ms5"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="action"
+            android:data="http://www/"
+            android:targetPackage="abc"
+            android:targetClass=".xyz"
+            android:mimeType="foo/bar"
+            >
+            <categories android:name="cat1" />
+            <categories android:name="cat2" />
+            <extra android:name="key1" android:value="value1" />
+            <extra android:name="key2" android:value="value2" />
+        </intent>
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_5_alt.xml b/services/tests/servicestests/res/xml/shortcut_5_alt.xml
index 74085d9..f79cd6f 100644
--- a/services/tests/servicestests/res/xml/shortcut_5_alt.xml
+++ b/services/tests/servicestests/res/xml/shortcut_5_alt.xml
@@ -17,37 +17,58 @@
     <shortcut
         android:shortcutId="ms1_alt"
         android:enabled="true"
-        android:shortcutIcon="@drawable/icon1"
+        android:icon="@drawable/icon1"
         android:shortcutShortLabel="@string/shortcut_title1"
         android:shortcutLongLabel="@string/shortcut_text1"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
-        android:shortcutCategories="android.shortcut.conversation:android.shortcut.media"
-        android:shortcutIntentAction="action1"
-        android:shortcutIntentData="http://a.b.c/1"
-    />
+        >
+        <intent
+            android:action="action1"
+            android:data="http://a.b.c/1"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+        <categories android:name="android.shortcut.media" />
+    </shortcut>
     <shortcut
         android:shortcutId="ms2_alt"
         android:enabled="true"
-        android:shortcutIcon="@drawable/icon2"
+        android:icon="@drawable/icon2"
         android:shortcutShortLabel="@string/shortcut_title2"
         android:shortcutLongLabel="@string/shortcut_text2"
         android:shortcutDisabledMessage="@string/shortcut_disabled_message2"
-        android:shortcutCategories="android.shortcut.conversation"
-        android:shortcutIntentAction="action2"
-    />
+        >
+        <intent
+            android:action="action2"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+    </shortcut>
     <shortcut
         android:shortcutId="ms3_alt"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
     <shortcut
         android:shortcutId="ms4_alt"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
     <shortcut
         android:shortcutId="ms5_alt"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_5_reverse.xml b/services/tests/servicestests/res/xml/shortcut_5_reverse.xml
new file mode 100644
index 0000000..d5b7c8f
--- /dev/null
+++ b/services/tests/servicestests/res/xml/shortcut_5_reverse.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+    <shortcut
+        android:shortcutId="ms5"
+        android:enabled="true"
+        android:icon="@drawable/icon1"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        android:shortcutLongLabel="@string/shortcut_text1"
+        android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
+        >
+        <intent
+            android:action="action1"
+            android:data="http://a.b.c/1"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+        <categories android:name="android.shortcut.media" />
+    </shortcut>
+    <shortcut
+        android:shortcutId="ms4"
+        android:enabled="true"
+        android:icon="@drawable/icon2"
+        android:shortcutShortLabel="@string/shortcut_title2"
+        android:shortcutLongLabel="@string/shortcut_text2"
+        android:shortcutDisabledMessage="@string/shortcut_disabled_message2"
+        >
+        <intent
+            android:action="action2"
+            >
+        </intent>
+        <categories android:name="android.shortcut.conversation" />
+    </shortcut>
+    <shortcut
+        android:shortcutId="ms3"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
+    <shortcut
+        android:shortcutId="ms2"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
+    <shortcut
+        android:shortcutId="ms1"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        >
+        <intent
+            android:action="action"
+            >
+            <categories android:name="cat1" />
+            <categories android:name="cat2" />
+            <extra android:name="key1" android:value="value1" />
+            <extra android:name="key2" android:value="value2" />
+        </intent>
+    </shortcut>
+</shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_error_1.xml b/services/tests/servicestests/res/xml/shortcut_error_1.xml
index 5822496..3990d02 100644
--- a/services/tests/servicestests/res/xml/shortcut_error_1.xml
+++ b/services/tests/servicestests/res/xml/shortcut_error_1.xml
@@ -16,11 +16,19 @@
 <shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
     <shortcut
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
     <shortcut
         android:shortcutId="x1"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_error_2.xml b/services/tests/servicestests/res/xml/shortcut_error_2.xml
index ca67ec7..a6f7150 100644
--- a/services/tests/servicestests/res/xml/shortcut_error_2.xml
+++ b/services/tests/servicestests/res/xml/shortcut_error_2.xml
@@ -16,11 +16,19 @@
 <shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
     <shortcut
         android:shortcutId="manifest-shortcut-3"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
     <shortcut
         android:shortcutId="x2"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_error_3.xml b/services/tests/servicestests/res/xml/shortcut_error_3.xml
index fb7b31c..a7b9b84 100644
--- a/services/tests/servicestests/res/xml/shortcut_error_3.xml
+++ b/services/tests/servicestests/res/xml/shortcut_error_3.xml
@@ -21,6 +21,10 @@
     <shortcut
         android:shortcutId="x3"
         android:shortcutShortLabel="@string/shortcut_title1"
-        android:shortcutIntentAction="android.intent.action.VIEW"
-    />
+        >
+        <intent
+            android:action="android.intent.action.VIEW"
+            >
+        </intent>
+    </shortcut>
 </shortcuts>
diff --git a/services/tests/servicestests/res/xml/shortcut_error_4.xml b/services/tests/servicestests/res/xml/shortcut_error_4.xml
new file mode 100644
index 0000000..3697bb4
--- /dev/null
+++ b/services/tests/servicestests/res/xml/shortcut_error_4.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+    <!-- This is valid -->
+    <shortcut
+        android:shortcutId="ms1"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        >
+        <intent android:action="action1" />
+    </shortcut>
+
+    <!-- Invalid: no intent -->
+    <shortcut
+        android:shortcutId="ms_ignored1"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        />
+
+    <!-- Valid: more than one intent; first one will be picked. -->
+    <shortcut
+        android:shortcutId="ms2"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        >
+        <intent android:action="action2_1" />
+        <intent android:action="action2_2" />
+    </shortcut>
+
+    <!-- Valid: disabled shortcut doesn't need an intent -->
+    <shortcut
+        android:shortcutId="ms3"
+        android:enabled="false"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        />
+
+    <!-- Valid, but disabled shortcut's intent will be ignored. -->
+    <shortcut
+        android:shortcutId="ms4"
+        android:enabled="false"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        >
+        <intent android:action="action4" />
+    </shortcut>
+
+    <!-- Invalid, no intent action -->
+    <shortcut
+        android:shortcutId="ms_ignored2"
+        android:shortcutShortLabel="@string/shortcut_title1"
+        >
+        <intent android:data="x"/>
+    </shortcut>
+</shortcuts>
diff --git a/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java b/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
index b5698d5..3278cf1 100644
--- a/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
@@ -59,6 +59,15 @@
     }
 
     @SmallTest
+    public void testInstantaneousBurstIsEstimatedUnderTwoPercent() throws Exception {
+        assertUpdateTime(mTestStartTime);
+        long eventStart = mTestStartTime + 1000; // start event a long time after initialization
+        long nextEventTime = postEvents(eventStart, 0, 5); // five events at \inf
+        final float rate = mEstimator.getRate(nextEventTime);
+        assertLessThan("Rate", rate, 20f);
+    }
+
+    @SmallTest
     public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception {
         assertUpdateTime(mTestStartTime);
         long eventStart = mTestStartTime + 1000; // start event a long time after initialization
@@ -110,12 +119,19 @@
         assertLessThan("Rate", rate, 0.1f);
     }
 
+    @SmallTest
+    public void testGetRateWithOneUpdate() throws Exception {
+        assertUpdateTime(mTestStartTime);
+        final float rate = mEstimator.getRate(mTestStartTime+1);
+        assertLessThan("Rate", rate, 1f);
+    }
+
     private void assertLessThan(String label, float a, float b)  {
-        assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a < b);
+        assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a <= b);
     }
 
     private void assertGreaterThan(String label, float a, float b)  {
-        assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a > b);
+        assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a >= b);
     }
 
     /** @returns the next event time. */
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 2f11967..b8b67e9 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -532,7 +532,7 @@
 
     static {
         QUERY_ALL.setQueryFlags(
-                ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+                ShortcutQuery.FLAG_GET_ALL_KINDS);
     }
 
     @Override
@@ -742,6 +742,9 @@
         if (mService != null) {
             // Flush all the unsaved data from the previous instance.
             mService.saveDirtyInfo();
+
+            // Make sure everything is consistent.
+            mService.verifyStates();
         }
         LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
 
@@ -1431,7 +1434,7 @@
     protected static ShortcutQuery buildAllQuery(String packageName) {
         final ShortcutQuery q = new ShortcutQuery();
         q.setPackage(packageName);
-        q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+        q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
         return q;
     }
 
@@ -1442,6 +1445,12 @@
         return q;
     }
 
+    protected static ShortcutQuery buildQueryWithFlags(int queryFlags) {
+        final ShortcutQuery q = new ShortcutQuery();
+        q.setQueryFlags(queryFlags);
+        return q;
+    }
+
     protected void backupAndRestore() {
         int prevUid = mInjectedCallingUid;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index fe2d1ec..0894323 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -45,6 +45,7 @@
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertEmpty;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertShortcutIds;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.filterByActivity;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.findShortcut;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.hashSet;
@@ -71,7 +72,6 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.ShortcutInfo;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.BitmapFactory;
@@ -79,7 +79,6 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.Process;
 import android.os.UserHandle;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
@@ -969,23 +968,34 @@
         // Set up shortcuts.
 
         setCaller(CALLING_PACKAGE_1);
-        final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 5000);
-        final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 1000);
+        final ShortcutInfo s1_1 = makeShortcut("s1");
+        final ShortcutInfo s1_2 = makeShortcut("s2");
 
         assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
 
+        // Because setDynamicShortcuts will update the timestamps when ranks are changing,
+        // we explicitly set timestamps here.
+        getCallerShortcut("s1").setTimestamp(5000);
+        getCallerShortcut("s2").setTimestamp(1000);
+
         setCaller(CALLING_PACKAGE_2);
-        final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
-        final ShortcutInfo s2_3 = makeShortcutWithTimestampWithActivity("s3", 3000,
+        final ShortcutInfo s2_2 = makeShortcut("s2");
+        final ShortcutInfo s2_3 = makeShortcutWithActivity("s3",
                 makeComponent(ShortcutActivity2.class));
-        final ShortcutInfo s2_4 = makeShortcutWithTimestampWithActivity("s4", 500,
+        final ShortcutInfo s2_4 = makeShortcutWithActivity("s4",
                 makeComponent(ShortcutActivity.class));
         assertTrue(mManager.setDynamicShortcuts(list(s2_2, s2_3, s2_4)));
 
+        getCallerShortcut("s2").setTimestamp(1500);
+        getCallerShortcut("s3").setTimestamp(3000);
+        getCallerShortcut("s4").setTimestamp(500);
+
         setCaller(CALLING_PACKAGE_3);
-        final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s3", START_TIME + 5000);
+        final ShortcutInfo s3_2 = makeShortcut("s3");
         assertTrue(mManager.setDynamicShortcuts(list(s3_2)));
 
+        getCallerShortcut("s3").setTimestamp(START_TIME + 5000);
+
         setCaller(LAUNCHER_1);
 
         // Get dynamic
@@ -1092,6 +1102,117 @@
         // TODO More tests: pinned but dynamic.
     }
 
+    public void testGetShortcuts_shortcutKinds() throws Exception {
+        // Create 3 manifest and 3 dynamic shortcuts
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_3);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+
+        // Pin 2 and 3
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "ms3", "s2", "s3"),
+                    HANDLE_USER_0);
+        });
+
+        // Remove ms3 and s3
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_2);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"))));
+        });
+
+        // Check their status.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1", "ms2", "ms3", "s1", "s2", "s3")
+
+                    .selectByIds("ms1", "ms2")
+                    .areAllManifest()
+                    .areAllImmutable()
+                    .areAllNotDynamic()
+
+                    .revertToOriginalList()
+                    .selectByIds("ms3")
+                    .areAllNotManifest()
+                    .areAllImmutable()
+                    .areAllDisabled()
+                    .areAllNotDynamic()
+
+                    .revertToOriginalList()
+                    .selectByIds("s1", "s2")
+                    .areAllNotManifest()
+                    .areAllMutable()
+                    .areAllDynamic()
+
+                    .revertToOriginalList()
+                    .selectByIds("s3")
+                    .areAllNotManifest()
+                    .areAllMutable()
+                    .areAllEnabled()
+                    .areAllNotDynamic()
+
+                    .revertToOriginalList()
+                    .selectByIds("s1", "ms1")
+                    .areAllNotPinned()
+
+                    .revertToOriginalList()
+                    .selectByIds("s2", "s3", "ms2", "ms3")
+                    .areAllPinned()
+            ;
+        });
+
+        // Finally, actual tests.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertWith(mLauncherApps.getShortcuts(
+                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0))
+                    .haveIds("s1", "s2");
+            assertWith(mLauncherApps.getShortcuts(
+                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_MANIFEST), HANDLE_USER_0))
+                    .haveIds("ms1", "ms2");
+            assertWith(mLauncherApps.getShortcuts(
+                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0))
+                    .haveIds("s2", "s3", "ms2", "ms3");
+
+            assertWith(mLauncherApps.getShortcuts(
+                    buildQueryWithFlags(
+                            ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED
+                    ), HANDLE_USER_0))
+                    .haveIds("s1", "s2", "s3", "ms2", "ms3");
+
+            assertWith(mLauncherApps.getShortcuts(
+                    buildQueryWithFlags(
+                            ShortcutQuery.FLAG_GET_MANIFEST | ShortcutQuery.FLAG_GET_PINNED
+                    ), HANDLE_USER_0))
+                    .haveIds("ms1", "s2", "s3", "ms2", "ms3");
+
+            assertWith(mLauncherApps.getShortcuts(
+                    buildQueryWithFlags(
+                            ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_MANIFEST
+                    ), HANDLE_USER_0))
+                    .haveIds("ms1", "ms2", "s1", "s2");
+
+            assertWith(mLauncherApps.getShortcuts(
+                    buildQueryWithFlags(
+                            ShortcutQuery.FLAG_GET_ALL_KINDS
+                    ), HANDLE_USER_0))
+                    .haveIds("ms1", "ms2", "ms3", "s1", "s2", "s3");
+        });
+    }
+
     public void testGetShortcuts_resolveStrings() throws Exception {
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             ShortcutInfo si = new ShortcutInfo.Builder(mClientContext)
@@ -2213,6 +2334,12 @@
     }
 
     public void testLauncherCallback() throws Throwable {
+        // Disable throttling for this test.
+        mService.updateConfigurationLocked(
+                ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=99999999,"
+                        + ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999"
+        );
+
         LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
 
         // Set listeners
@@ -2233,8 +2360,10 @@
                 shortcuts.capture(),
                 eq(HANDLE_USER_0)
         );
-        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
-                "s1", "s2", "s3");
+        assertWith(shortcuts.getValue())
+                .haveIds("s1", "s2", "s3")
+                .areAllWithKeyFieldsOnly()
+                .areAllDynamic();
 
         // From different package.
         reset(c0);
@@ -2249,8 +2378,10 @@
                 shortcuts.capture(),
                 eq(HANDLE_USER_0)
         );
-        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
-                "s1", "s2", "s3");
+        assertWith(shortcuts.getValue())
+                .haveIds("s1", "s2", "s3")
+                .areAllWithKeyFieldsOnly()
+                .areAllDynamic();
 
         // Different user, callback shouldn't be called.
         reset(c0);
@@ -2279,8 +2410,10 @@
                 shortcuts.capture(),
                 eq(HANDLE_USER_0)
         );
-        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
-                "s1", "s2", "s3", "s4");
+        assertWith(shortcuts.getValue())
+                .haveIds("s1", "s2", "s3", "s4")
+                .areAllWithKeyFieldsOnly()
+                .areAllDynamic();
 
         // Test for remove
         reset(c0);
@@ -2295,8 +2428,10 @@
                 shortcuts.capture(),
                 eq(HANDLE_USER_0)
         );
-        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
-                "s2", "s3", "s4");
+        assertWith(shortcuts.getValue())
+                .haveIds("s2", "s3", "s4")
+                .areAllWithKeyFieldsOnly()
+                .areAllDynamic();
 
         // Test for update
         reset(c0);
@@ -2312,8 +2447,10 @@
                 shortcuts.capture(),
                 eq(HANDLE_USER_0)
         );
-        assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
-                "s2", "s3", "s4");
+        assertWith(shortcuts.getValue())
+                .haveIds("s2", "s3", "s4")
+                .areAllWithKeyFieldsOnly()
+                .areAllDynamic();
 
         // Test for deleteAll
         reset(c0);
@@ -2328,7 +2465,100 @@
                 shortcuts.capture(),
                 eq(HANDLE_USER_0)
         );
-        assertEquals(0, shortcuts.getValue().size());
+        assertWith(shortcuts.getValue())
+                .isEmpty();
+
+        // Update package1 with manifest shortcuts
+        reset(c0);
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_2);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        waitOnMainThread();
+        shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(c0).onShortcutsChanged(
+                eq(CALLING_PACKAGE_1),
+                shortcuts.capture(),
+                eq(HANDLE_USER_0)
+        );
+        assertWith(shortcuts.getValue())
+                .areAllManifest()
+                .areAllWithKeyFieldsOnly()
+                .haveIds("ms1", "ms2");
+
+        // Make sure pinned shortcuts are passed too.
+        // 1. Add dynamic shortcuts.
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"))));
+        });
+
+        // 2. Pin some.
+        runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_0);
+        });
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1", "ms2", "s1", "s2")
+                    .areAllEnabled()
+
+                    .selectByIds("ms1", "ms2")
+                    .areAllManifest()
+
+                    .revertToOriginalList()
+                    .selectByIds("s1", "s2")
+                    .areAllDynamic()
+                    ;
+        });
+
+        // 3 Update the app with no manifest shortcuts.  (Pinned one will survive.)
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_0);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        reset(c0); // Check the callback for the next API call.
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            mManager.removeDynamicShortcuts(list("s2"));
+
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms2", "s1", "s2")
+
+                    .selectByIds("ms2")
+                    .areAllNotManifest()
+                    .areAllPinned()
+                    .areAllImmutable()
+                    .areAllDisabled()
+
+                    .revertToOriginalList()
+                    .selectByIds("s1")
+                    .areAllDynamic()
+                    .areAllNotPinned()
+                    .areAllEnabled()
+
+                    .revertToOriginalList()
+                    .selectByIds("s2")
+                    .areAllNotDynamic()
+                    .areAllPinned()
+                    .areAllEnabled()
+                    ;
+        });
+
+        waitOnMainThread();
+        shortcuts = ArgumentCaptor.forClass(List.class);
+        verify(c0).onShortcutsChanged(
+                eq(CALLING_PACKAGE_1),
+                shortcuts.capture(),
+                eq(HANDLE_USER_0)
+        );
+        assertWith(shortcuts.getValue())
+                .haveIds("ms2", "s1", "s2")
+                .areAllWithKeyFieldsOnly();
 
         // Remove CALLING_PACKAGE_2
         reset(c0);
@@ -2343,7 +2573,8 @@
                 shortcuts.capture(),
                 eq(HANDLE_USER_0)
         );
-        assertEquals(0, shortcuts.getValue().size());
+        assertWith(shortcuts.getValue())
+                .isEmpty();
     }
 
     public void testLauncherCallback_crossProfile() throws Throwable {
@@ -4384,11 +4615,11 @@
 
     public void testOnApplicationActive_permission() {
         assertExpectException(SecurityException.class, "Missing permission", () ->
-                mService.onApplicationActive(CALLING_PACKAGE_1, USER_0));
+                mManager.onApplicationActive(CALLING_PACKAGE_1, USER_0));
 
         // Has permission, now it should pass.
         mCallerPermissions.add(permission.RESET_SHORTCUT_MANAGER_THROTTLING);
-        mService.onApplicationActive(CALLING_PACKAGE_1, USER_0);
+        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_0);
     }
 
     public void testDumpsys_crossProfile() {
@@ -4606,7 +4837,6 @@
         assertNull(mService.getPackageShortcutForTest(LAUNCHER_1, USER_0));
     }
 
-
     public void testManifestShortcut_publishOnBroadcast() {
         // First, no packages are installed.
         uninstallPackage(USER_0, CALLING_PACKAGE_1);
@@ -4677,6 +4907,10 @@
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2", "ms3", "ms4", "ms5");
+            assertWith(getCallerShortcuts()).selectManifest()
+                    .selectByActivity(
+                            new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()))
+                    .haveRanksInOrder("ms1", "ms2", "ms3", "ms4", "ms5");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
@@ -4710,6 +4944,10 @@
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
+            assertWith(getCallerShortcuts()).selectManifest()
+                    .selectByActivity(
+                            new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()))
+                    .haveRanksInOrder("ms1", "ms2");
             assertShortcutIds(assertAllImmutable(assertAllPinned(
                     mManager.getPinnedShortcuts())),
                     "ms2", "ms3");
@@ -4733,6 +4971,10 @@
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
+            assertWith(getCallerShortcuts()).selectManifest()
+                    .selectByActivity(
+                            new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()))
+                    .haveRanksInOrder("ms1", "ms2");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
@@ -4741,6 +4983,10 @@
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
+            assertWith(getCallerShortcuts()).selectManifest()
+                    .selectByActivity(
+                            new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()))
+                    .haveRanksInOrder("ms1", "ms2");
             assertShortcutIds(assertAllImmutable(assertAllPinned(
                     mManager.getPinnedShortcuts())),
                     "ms2", "ms3");
@@ -4749,10 +4995,43 @@
             assertAllDisabled(list(getCallerShortcut("ms3")));
         });
 
+        // Multiple activities.
+        // Add shortcuts on activity 2 for package 2.
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
+                R.xml.shortcut_5_alt);
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_2, ShortcutActivity2.class.getName()),
+                R.xml.shortcut_5_reverse);
+
+        updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
+
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
+                    mManager.getManifestShortcuts()))),
+                    "ms1", "ms2", "ms3", "ms4", "ms5",
+                    "ms1_alt", "ms2_alt", "ms3_alt", "ms4_alt", "ms5_alt");
+
+            // Make sure they have the correct ranks, regardless of their ID's alphabetical order.
+            assertWith(getCallerShortcuts()).selectManifest()
+                    .selectByActivity(
+                            new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()))
+                    .haveRanksInOrder("ms1_alt", "ms2_alt", "ms3_alt", "ms4_alt", "ms5_alt");
+            assertWith(getCallerShortcuts()).selectManifest()
+                    .selectByActivity(
+                            new ComponentName(CALLING_PACKAGE_2, ShortcutActivity2.class.getName()))
+                    .haveRanksInOrder("ms5", "ms4", "ms3", "ms2", "ms1");
+        });
+
         // Package 2 now has no manifest shortcuts.
         addManifestShortcutResource(
                 new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
                 R.xml.shortcut_0);
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_2, ShortcutActivity2.class.getName()),
+                R.xml.shortcut_0);
         updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
@@ -4826,6 +5105,117 @@
         });
     }
 
+    public void testManifestShortcuts_intentDefinitions() {
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_error_4);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            // Make sure invalid ones are not published.
+            // Note that at this point disabled ones don't show up because they weren't pinned.
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1", "ms2")
+                    .areAllManifest()
+                    .areAllNotDynamic()
+                    .areAllNotPinned()
+                    .areAllImmutable()
+                    .areAllEnabled()
+                    .forShortcutWithId("ms1", si -> {
+                        assertTrue(si.isEnabled());
+                        assertEquals("action1", si.getIntent().getAction());
+                    })
+                    .forShortcutWithId("ms2", si -> {
+                        assertTrue(si.isEnabled());
+                        assertEquals("action2_1", si.getIntent().getAction());
+                    });
+        });
+
+        // Publish 5 enabled to pin some, so we can later test disabled manfiest shortcuts..
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_5);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            // Make sure 5 manifest shortcuts are published.
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1", "ms2", "ms3", "ms4", "ms5")
+                    .areAllManifest()
+                    .areAllNotDynamic()
+                    .areAllNotPinned()
+                    .areAllImmutable()
+                    .areAllEnabled();
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("ms3", "ms4", "ms5"), HANDLE_USER_0);
+        });
+
+        // Make sure they're pinned.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1", "ms2", "ms3", "ms4", "ms5")
+                    .selectByIds("ms1", "ms2")
+                    .areAllNotPinned()
+                    .areAllEnabled()
+
+                    .revertToOriginalList()
+                    .selectByIds("ms3", "ms4", "ms5")
+                    .areAllPinned()
+                    .areAllEnabled();
+        });
+
+        // Update the app.
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_error_4);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        // Make sure 3, 4 and 5 still exist but disabled.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1", "ms2", "ms3", "ms4", "ms5")
+                    .areAllNotDynamic()
+                    .areAllImmutable()
+
+                    .selectByIds("ms1", "ms2")
+                    .areAllManifest()
+                    .areAllNotPinned()
+                    .areAllEnabled()
+
+                    .revertToOriginalList()
+                    .selectByIds("ms3", "ms4", "ms5")
+                    .areAllNotManifest()
+                    .areAllPinned()
+                    .areAllDisabled()
+
+                    .revertToOriginalList()
+                    .forShortcutWithId("ms1", si -> {
+                        assertEquals(si.getId(), "action1", si.getIntent().getAction());
+                    })
+                    .forShortcutWithId("ms2", si -> {
+                        assertEquals(si.getId(), "action2_1", si.getIntent().getAction());
+                    })
+                    .forShortcutWithId("ms3", si -> {
+                        assertEquals(si.getId(), Intent.ACTION_VIEW, si.getIntent().getAction());
+                    })
+                    .forShortcutWithId("ms4", si -> {
+                        assertEquals(si.getId(), Intent.ACTION_VIEW, si.getIntent().getAction());
+                    })
+                    .forShortcutWithId("ms5", si -> {
+                        assertEquals(si.getId(), "action", si.getIntent().getAction());
+                    });
+        });
+    }
+
     public void testManifestShortcuts_checkAllFields() {
         mService.handleUnlockUser(USER_0);
 
@@ -4839,63 +5229,95 @@
 
         // Only the valid one is published.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
-                    mManager.getManifestShortcuts()))),
-                    "ms1", "ms2", "ms3", "ms4", "ms5");
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1", "ms2", "ms3", "ms4", "ms5")
+                    .areAllManifest()
+                    .areAllImmutable()
+                    .areAllEnabled()
+                    .areAllNotPinned()
+                    .areAllNotDynamic()
 
-            // check first shortcut.
-            ShortcutInfo si = getCallerShortcut("ms1");
+                    .forShortcutWithId("ms1", si -> {
+                        assertEquals(R.drawable.icon1, si.getIconResourceId());
+                        assertEquals(new ComponentName(CALLING_PACKAGE_1,
+                                ShortcutActivity.class.getName()),
+                                si.getActivity());
 
-            assertEquals("ms1", si.getId());
-            assertEquals(R.drawable.icon1, si.getIconResourceId());
-            assertEquals(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
-                    si.getActivity());
+                        assertEquals(R.string.shortcut_title1, si.getTitleResId());
+                        assertEquals("r" + R.string.shortcut_title1, si.getTitleResName());
+                        assertEquals(R.string.shortcut_text1, si.getTextResId());
+                        assertEquals("r" + R.string.shortcut_text1, si.getTextResName());
+                        assertEquals(R.string.shortcut_disabled_message1,
+                                si.getDisabledMessageResourceId());
+                        assertEquals("r" + R.string.shortcut_disabled_message1,
+                                si.getDisabledMessageResName());
 
-            assertEquals(R.string.shortcut_title1, si.getTitleResId());
-            assertEquals("r" + R.string.shortcut_title1, si.getTitleResName());
-            assertEquals(R.string.shortcut_text1, si.getTextResId());
-            assertEquals("r" + R.string.shortcut_text1, si.getTextResName());
-            assertEquals(R.string.shortcut_disabled_message1, si.getDisabledMessageResourceId());
-            assertEquals("r" + R.string.shortcut_disabled_message1, si.getDisabledMessageResName());
+                        assertEquals(set("android.shortcut.conversation", "android.shortcut.media"),
+                                si.getCategories());
+                        assertEquals("action1", si.getIntent().getAction());
+                        assertEquals(Uri.parse("http://a.b.c/1"), si.getIntent().getData());
+                    })
 
-            assertEquals(set("android.shortcut.conversation", "android.shortcut.media"),
-                    si.getCategories());
-            assertEquals("action1", si.getIntent().getAction());
-            assertEquals(Uri.parse("http://a.b.c/1"), si.getIntent().getData());
+                    .forShortcutWithId("ms2", si -> {
+                        assertEquals("ms2", si.getId());
+                        assertEquals(R.drawable.icon2, si.getIconResourceId());
 
-            // check another
-            si = getCallerShortcut("ms2");
+                        assertEquals(R.string.shortcut_title2, si.getTitleResId());
+                        assertEquals("r" + R.string.shortcut_title2, si.getTitleResName());
+                        assertEquals(R.string.shortcut_text2, si.getTextResId());
+                        assertEquals("r" + R.string.shortcut_text2, si.getTextResName());
+                        assertEquals(R.string.shortcut_disabled_message2,
+                                si.getDisabledMessageResourceId());
+                        assertEquals("r" + R.string.shortcut_disabled_message2,
+                                si.getDisabledMessageResName());
 
-            assertEquals("ms2", si.getId());
-            assertEquals(R.drawable.icon2, si.getIconResourceId());
+                        assertEquals(set("android.shortcut.conversation"), si.getCategories());
+                        assertEquals("action2", si.getIntent().getAction());
+                        assertEquals(null, si.getIntent().getData());
+                    })
 
-            assertEquals(R.string.shortcut_title2, si.getTitleResId());
-            assertEquals("r" + R.string.shortcut_title2, si.getTitleResName());
-            assertEquals(R.string.shortcut_text2, si.getTextResId());
-            assertEquals("r" + R.string.shortcut_text2, si.getTextResName());
-            assertEquals(R.string.shortcut_disabled_message2, si.getDisabledMessageResourceId());
-            assertEquals("r" + R.string.shortcut_disabled_message2, si.getDisabledMessageResName());
+                    .forShortcutWithId("ms3", si -> {
+                        assertEquals(0, si.getIconResourceId());
+                        assertEquals(R.string.shortcut_title1, si.getTitleResId());
+                        assertEquals("r" + R.string.shortcut_title1, si.getTitleResName());
 
-            assertEquals(set("android.shortcut.conversation"), si.getCategories());
-            assertEquals("action2", si.getIntent().getAction());
-            assertEquals(null, si.getIntent().getData());
+                        assertEquals(0, si.getTextResId());
+                        assertEquals(null, si.getTextResName());
+                        assertEquals(0, si.getDisabledMessageResourceId());
+                        assertEquals(null, si.getDisabledMessageResName());
 
-            // check another
-            si = getCallerShortcut("ms3");
+                        assertEmpty(si.getCategories());
+                        assertEquals("android.intent.action.VIEW", si.getIntent().getAction());
+                        assertEquals(null, si.getIntent().getData());
+                    })
 
-            assertEquals("ms3", si.getId());
-            assertEquals(0, si.getIconResourceId());
-            assertEquals(R.string.shortcut_title1, si.getTitleResId());
-            assertEquals("r" + R.string.shortcut_title1, si.getTitleResName());
+                    .forShortcutWithId("ms4", si -> {
+                        assertEquals(0, si.getIconResourceId());
+                        assertEquals(R.string.shortcut_title2, si.getTitleResId());
+                        assertEquals("r" + R.string.shortcut_title2, si.getTitleResName());
 
-            assertEquals(0, si.getTextResId());
-            assertEquals(null, si.getTextResName());
-            assertEquals(0, si.getDisabledMessageResourceId());
-            assertEquals(null, si.getDisabledMessageResName());
+                        assertEquals(0, si.getTextResId());
+                        assertEquals(null, si.getTextResName());
+                        assertEquals(0, si.getDisabledMessageResourceId());
+                        assertEquals(null, si.getDisabledMessageResName());
 
-            assertEquals(null, si.getCategories());
-            assertEquals("android.intent.action.VIEW", si.getIntent().getAction());
-            assertEquals(null, si.getIntent().getData());
+                        assertEquals(set("cat"), si.getCategories());
+                        assertEquals("android.intent.action.VIEW2", si.getIntent().getAction());
+                        assertEquals(null, si.getIntent().getData());
+                    })
+
+                    .forShortcutWithId("ms5", si -> {
+                        si = getCallerShortcut("ms5");
+                        assertEquals("action", si.getIntent().getAction());
+                        assertEquals("http://www/", si.getIntent().getData().toString());
+                        assertEquals("foo/bar", si.getIntent().getType());
+                        assertEquals(
+                                new ComponentName("abc", ".xyz"), si.getIntent().getComponent());
+
+                        assertEquals(set("cat1", "cat2"), si.getIntent().getCategories());
+                        assertEquals("value1", si.getIntent().getStringExtra("key1"));
+                        assertEquals("value2", si.getIntent().getStringExtra("key2"));
+                    });
         });
     }
 
@@ -5128,7 +5550,7 @@
         // ShortcutActivity2 has two shortcuts, ms1 and ms2.
         addManifestShortcutResource(
                 new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
-                R.xml.shortcut_2);
+                R.xml.shortcut_5);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
                 genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
@@ -5136,13 +5558,14 @@
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
-                    "ms1", "ms2");
+                    "ms1", "ms2", "ms3", "ms4", "ms5");
 
             // ms1 should belong to ShortcutActivity.
             ShortcutInfo si = getCallerShortcut("ms1");
             assertEquals(R.string.shortcut_title1, si.getTitleResId());
             assertEquals(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
                     si.getActivity());
+            assertEquals(0, si.getRank());
 
             // ms2 should belong to ShortcutActivity*2*.
             si = getCallerShortcut("ms2");
@@ -5150,8 +5573,18 @@
             assertEquals(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
                     si.getActivity());
 
+            // Also check the ranks
+            assertWith(getCallerShortcuts()).selectManifest()
+                    .selectByActivity(
+                            new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()))
+                    .haveRanksInOrder("ms1");
+            assertWith(getCallerShortcuts()).selectManifest()
+                    .selectByActivity(
+                            new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()))
+                    .haveRanksInOrder("ms2", "ms3", "ms4", "ms5");
+
             // Make sure there's no other dangling shortcuts.
-            assertShortcutIds(getCallerShortcuts(), "ms1", "ms2");
+            assertShortcutIds(getCallerShortcuts(), "ms1", "ms2", "ms3", "ms4", "ms5");
         });
     }
 
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 ea44462..fdd8f142 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -329,7 +329,7 @@
 
         assertEquals(mClientContext.getPackageName(), si.getPackage());
         assertEquals("id", si.getId());
-        assertEquals(null, si.getActivity());
+        assertEquals(new ComponentName("a", "b"), si.getActivity());
         assertEquals(null, si.getIcon());
         assertEquals(null, si.getTitle());
         assertEquals(null, si.getText());
@@ -445,7 +445,7 @@
 
         assertEquals(mClientContext.getPackageName(), si.getPackage());
         assertEquals("id", si.getId());
-        assertEquals(null, si.getActivity());
+        assertEquals(new ComponentName("a", "b"), si.getActivity());
         assertEquals(null, si.getIcon());
         assertEquals(0, si.getTitleResId());
         assertEquals(null, si.getTitleResName());
@@ -533,6 +533,7 @@
         si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
                 .setActivity(new ComponentName("x", "y")).build());
         assertEquals("text", si.getText());
+        assertEquals(123, si.getRank());
         assertEquals(new ComponentName("x", "y"), si.getActivity());
 
         si = sorig.clone(/* flags=*/ 0);
@@ -627,16 +628,6 @@
                 .setExtras(pb2).build());
         assertEquals("text", si.getText());
         assertEquals(99, si.getExtras().getInt("x"));
-
-        // Make sure the timestamp gets updated too.
-
-        final long timestamp = si.getLastChangedTimestamp();
-        Thread.sleep(2);
-
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
-                .setTitle("xyz").build());
-
-        assertTrue(si.getLastChangedTimestamp() > timestamp);
     }
 
     public void testShortcutInfoCopyNonNullFieldsFrom_resId() throws InterruptedException {
@@ -764,16 +755,6 @@
                 .setExtras(pb2).build());
         assertEquals(11, si.getTextResId());
         assertEquals(99, si.getExtras().getInt("x"));
-
-        // Make sure the timestamp gets updated too.
-
-        final long timestamp = si.getLastChangedTimestamp();
-        Thread.sleep(2);
-
-        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
-                .setTitle("xyz").build());
-
-        assertTrue(si.getLastChangedTimestamp() > timestamp);
     }
 
     public void testShortcutInfoSaveAndLoad() throws InterruptedException {
@@ -797,7 +778,15 @@
                 .setExtras(pb)
                 .build();
 
-        mManager.addDynamicShortcuts(list(sorig));
+        ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
+                .setId("id2")
+                .setTitle("x")
+                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setRank(456)
+                .build();
+
+        mManager.addDynamicShortcuts(list(sorig, sorig2));
 
         Thread.sleep(2);
         final long now = System.currentTimeMillis();
@@ -822,7 +811,7 @@
         assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
         assertEquals("action", si.getIntent().getAction());
         assertEquals("val", si.getIntent().getStringExtra("key"));
-        assertEquals(123, si.getRank());
+        assertEquals(0, si.getRank());
         assertEquals(1, si.getExtras().getInt("k"));
 
         assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE
@@ -830,6 +819,11 @@
         assertNotNull(si.getBitmapPath()); // Something should be set.
         assertEquals(0, si.getIconResourceId());
         assertTrue(si.getLastChangedTimestamp() < now);
+
+        // Make sure ranks are saved too.  Because of the auto-adjusting, we need two shortcuts
+        // to test it.
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
+        assertEquals(1, si.getRank());
     }
 
     public void testShortcutInfoSaveAndLoad_resId() throws InterruptedException {
@@ -852,7 +846,15 @@
                 .setExtras(pb)
                 .build();
 
-        mManager.addDynamicShortcuts(list(sorig));
+        ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
+                .setId("id2")
+                .setTitle("x")
+                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setRank(456)
+                .build();
+
+        mManager.addDynamicShortcuts(list(sorig, sorig2));
 
         Thread.sleep(2);
         final long now = System.currentTimeMillis();
@@ -880,7 +882,7 @@
         assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
         assertEquals("action", si.getIntent().getAction());
         assertEquals("val", si.getIntent().getStringExtra("key"));
-        assertEquals(123, si.getRank());
+        assertEquals(0, si.getRank());
         assertEquals(1, si.getExtras().getInt("k"));
 
         assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_RES
@@ -888,6 +890,11 @@
         assertNull(si.getBitmapPath());
         assertEquals(R.drawable.black_32x32, si.getIconResourceId());
         assertTrue(si.getLastChangedTimestamp() < now);
+
+        // Make sure ranks are saved too.  Because of the auto-adjusting, we need two shortcuts
+        // to test it.
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
+        assertEquals(1, si.getRank());
     }
 
     public void testShortcutInfoSaveAndLoad_forBackup() {
@@ -911,11 +918,19 @@
                 .setExtras(pb)
                 .build();
 
-        mManager.addDynamicShortcuts(list(sorig));
+        ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
+                .setId("id2")
+                .setTitle("x")
+                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setRank(456)
+                .build();
+
+        mManager.addDynamicShortcuts(list(sorig, sorig2));
 
         // Dynamic shortcuts won't be backed up, so we need to pin it.
         setCaller(LAUNCHER_1, USER_0);
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id"), HANDLE_USER_0);
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0);
 
         // Do backup & restore.
         backupAndRestore();
@@ -935,12 +950,16 @@
         assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
         assertEquals("action", si.getIntent().getAction());
         assertEquals("val", si.getIntent().getStringExtra("key"));
-        assertEquals(123, si.getRank());
+        assertEquals(0, si.getRank());
         assertEquals(1, si.getExtras().getInt("k"));
 
         assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
         assertNull(si.getBitmapPath()); // No icon.
         assertEquals(0, si.getIconResourceId());
+
+        // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
+        assertEquals(0, si.getRank());
     }
 
     public void testShortcutInfoSaveAndLoad_forBackup_resId() {
@@ -963,11 +982,19 @@
                 .setExtras(pb)
                 .build();
 
-        mManager.addDynamicShortcuts(list(sorig));
+        ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
+                .setId("id2")
+                .setTitle("x")
+                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
+                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+                .setRank(456)
+                .build();
+
+        mManager.addDynamicShortcuts(list(sorig, sorig2));
 
         // Dynamic shortcuts won't be backed up, so we need to pin it.
         setCaller(LAUNCHER_1, USER_0);
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id"), HANDLE_USER_0);
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0);
 
         // Do backup & restore.
         backupAndRestore();
@@ -990,13 +1017,17 @@
         assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
         assertEquals("action", si.getIntent().getAction());
         assertEquals("val", si.getIntent().getStringExtra("key"));
-        assertEquals(123, si.getRank());
+        assertEquals(0, si.getRank());
         assertEquals(1, si.getExtras().getInt("k"));
 
         assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
         assertNull(si.getBitmapPath()); // No icon.
         assertEquals(0, si.getIconResourceId());
         assertEquals(null, si.getIconResName());
+
+        // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
+        assertEquals(0, si.getRank());
     }
 
     public void testThrottling() {
@@ -1457,7 +1488,7 @@
 
         // Simulate a call from sys UI.
         mCallerPermissions.add(permission.RESET_SHORTCUT_MANAGER_THROTTLING);
-        mService.onApplicationActive(CALLING_PACKAGE_1, USER_0);
+        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_0);
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
@@ -1478,7 +1509,7 @@
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
 
-        mService.onApplicationActive(CALLING_PACKAGE_3, USER_0);
+        mManager.onApplicationActive(CALLING_PACKAGE_3, USER_0);
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
@@ -1499,7 +1530,7 @@
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
 
-        mService.onApplicationActive(CALLING_PACKAGE_1, USER_10);
+        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_10);
 
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
new file mode 100644
index 0000000..eb4db7a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.pm;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+
+import android.content.ComponentName;
+import android.content.pm.ShortcutInfo;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.frameworks.servicestests.R;
+import com.android.server.pm.ShortcutService.ConfigConstants;
+
+/**
+ * Tests related to shortcut rank auto-adjustment.
+ */
+@SmallTest
+public class ShortcutManagerTest3 extends BaseShortcutManagerTest {
+
+    private static final String CALLING_PACKAGE = CALLING_PACKAGE_1;
+
+    private static final ComponentName A1 = new ComponentName(CALLING_PACKAGE,
+            ShortcutActivity.class.getName());
+
+    private static final ComponentName A2 = new ComponentName(CALLING_PACKAGE,
+            ShortcutActivity2.class.getName());
+
+    private static final ComponentName A3 = new ComponentName(CALLING_PACKAGE,
+            ShortcutActivity3.class.getName());
+
+    private ShortcutInfo shortcut(String id, ComponentName activity, int rank) {
+        return makeShortcutWithActivityAndRank(id, activity, rank);
+    }
+
+    private ShortcutInfo shortcut(String id, ComponentName activity) {
+        return makeShortcutWithActivityAndRank(id, activity, ShortcutInfo.RANK_NOT_SET);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // We don't need throttling during this test class, and also relax the max cap.
+        mService.updateConfigurationLocked(
+                ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=99999999,"
+                + ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999"
+        );
+
+        setCaller(CALLING_PACKAGE, USER_0);
+    }
+
+    private void publishManifestShortcuts(ComponentName activity, int resId) {
+        addManifestShortcutResource(activity, resId);
+        updatePackageVersion(CALLING_PACKAGE, 1);
+        mService.mPackageMonitor.onReceive(getTestContext(),
+                genPackageAddIntent(CALLING_PACKAGE, USER_0));
+    }
+
+    public void testSetDynamicShortcuts_noManifestShortcuts() {
+        mManager.setDynamicShortcuts(list(
+                shortcut("s1", A1)
+        ));
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s1");
+
+        assertTrue(mManager.setDynamicShortcuts(list(
+                shortcut("s5", A1),
+                shortcut("s4", A1),
+                shortcut("s3", A1)
+        )));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s4", "s3");
+
+        // RANK_NOT_SET is always the last.
+        assertTrue(mManager.setDynamicShortcuts(list(
+                shortcut("s5", A1),
+                shortcut("s4", A1, 5),
+                shortcut("s3", A1, 3),
+                shortcut("s2", A1)
+        )));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s3", "s4", "s5", "s2");
+
+        // Same rank, preserve the argument order.
+        assertTrue(mManager.setDynamicShortcuts(list(
+                shortcut("s5", A1, 5),
+                shortcut("s4", A1, 0),
+                shortcut("s3", A1, 5)
+        )));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s4", "s5", "s3");
+
+        // Multiple activities.
+        assertTrue(mManager.setDynamicShortcuts(list(
+                shortcut("s5", A1),
+                shortcut("s4", A2),
+                shortcut("s3", A3)
+        )));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5");
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("s4");
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A3)
+                .haveRanksInOrder("s3");
+
+        assertTrue(mManager.setDynamicShortcuts(list(
+                shortcut("s5", A1, 5),
+                shortcut("s4", A1),
+                shortcut("s3", A1, 5),
+                shortcut("x5", A2, 5),
+                shortcut("x4", A2),
+                shortcut("x3", A2, 1)
+        )));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s4");
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x5", "x4");
+
+        // Clear.  Make sure it wouldn't lead to invalid internals state.
+        // (ShortcutService.verifyStates() will do so internally.)
+        assertTrue(mManager.setDynamicShortcuts(list()));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1).isEmpty();
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2).isEmpty();
+    }
+
+    private void runTestWithManifestShortcuts(Runnable r) {
+        publishManifestShortcuts(A1, R.xml.shortcut_5_alt);
+        publishManifestShortcuts(A2, R.xml.shortcut_1);
+
+        assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A1)
+                .haveRanksInOrder("ms1_alt", "ms2_alt", "ms3_alt", "ms4_alt", "ms5_alt");
+
+        assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A2)
+                .haveRanksInOrder("ms1");
+
+        // Existence of manifest shortcuts shouldn't affect dynamic shortcut ranks,
+        // so running another test here should pass.
+        r.run();
+
+        // And dynamic shortcut tests shouldn't affect manifest shortcuts, so repeat the
+        // same check.
+        assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A1)
+                .haveRanksInOrder("ms1_alt", "ms2_alt", "ms3_alt", "ms4_alt", "ms5_alt");
+
+        assertWith(getCallerShortcuts()).selectManifest().selectByActivity(A2)
+                .haveRanksInOrder("ms1");
+    }
+
+    public void testSetDynamicShortcuts_withManifestShortcuts() {
+        runTestWithManifestShortcuts(() -> testSetDynamicShortcuts_noManifestShortcuts());
+    }
+
+    public void testAddDynamicShortcuts_noManifestShortcuts() {
+        mManager.addDynamicShortcuts(list(
+                shortcut("s1", A1)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s1");
+
+        //------------------------------------------------------
+        long lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.addDynamicShortcuts(list(
+                shortcut("s5", A1, 0),
+                shortcut("s4", A1),
+                shortcut("s2", A1, 3),
+                shortcut("x1", A2),
+                shortcut("x3", A2, 2),
+                shortcut("x2", A2, 2),
+                shortcut("s3", A1, 0)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s1", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s5", "s3", "s1", "s2", "s4", "x3", "x2", "x1");
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.addDynamicShortcuts(list(
+                shortcut("s1", A1, 1)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s1", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s1", "s3");
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.addDynamicShortcuts(list(
+                shortcut("s1", A1, 1),
+
+                // This is add, not update, so the following means s5 will have NO_RANK,
+                // which puts it at the end.
+                shortcut("s5", A1),
+                shortcut("s3", A1, 0),
+
+                // s10 also has NO_RANK, so it'll be put at the end, even after "s5" as we preserve
+                // the argument order.
+                shortcut("s10", A1),
+
+                // Note we're changing the activity for x2.
+                shortcut("x2", A1, 0),
+                shortcut("x10", A2)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s3", "x2", "s1", "s2", "s4", "s5", "s10");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x1", "x10");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s3", "x2", "s1", "s5", "s10", "x1", "x10");
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        // Change the activities again.
+        mManager.addDynamicShortcuts(list(
+                shortcut("s1", A2),
+                shortcut("s2", A2, 999)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s3", "x2", "s4", "s5", "s10");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x1", "x10", "s2", "s1");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s1", "s2", "s4", "s5", "s10");
+    }
+
+    public void testAddDynamicShortcuts_withManifestShortcuts() {
+        runTestWithManifestShortcuts(() -> testAddDynamicShortcuts_noManifestShortcuts());
+    }
+
+    public void testUpdateShortcuts_noManifestShortcuts() {
+        mManager.addDynamicShortcuts(list(
+                shortcut("s5", A1, 0),
+                shortcut("s4", A1),
+                shortcut("s2", A1, 3),
+                shortcut("x1", A2),
+                shortcut("x3", A2, 2),
+                shortcut("x2", A2, 2),
+                shortcut("s3", A1, 0)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        //------------------------------------------------------
+        long lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.updateShortcuts(list());
+        // Same order.
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .isEmpty();
+
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_0);
+        });
+        // Still same order.
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.updateShortcuts(list(
+                shortcut("s4", A1, 1),
+
+                // Rank not changing, should keep the same positions.
+                // c.f. in case of addDynamicShortcuts, this means "put them at the end".
+                shortcut("s3", A1),
+                shortcut("x2", A2)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s4", "s3", "s2");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s4", "s3", "s2", "x2");
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.updateShortcuts(list(
+                shortcut("s4", A1, 0),
+
+                // Change the activity without specifying a rank -> keep the same rank.
+                shortcut("s5", A2),
+
+                // Change the activity without specifying a rank -> assign a new rank.
+                shortcut("x2", A1, 2),
+
+                // "xx" doesn't exist, so it'll be ignored.
+                shortcut("xx", A1, 0)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s4", "x2", "s3", "s2");
+
+        // Interesting case: both x3 and s5 originally had rank=0, and in this case s5 has moved
+        // to A2 without changing the rank.  So they're tie for the new rank, as well as
+        // the "rank changed" bit.  Also in this case, "s5" won't have an implicit order, since
+        // its rank isn't changing.  So we sort them by ID, thus s5 comes before x3.
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("s5", "x3", "x1");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s4", "x2", "s5", "x3");
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.updateShortcuts(list(
+                shortcut("s3", A3)));
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s4", "x2", "s2");
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("s5", "x3", "x1");
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A3)
+                .haveRanksInOrder("s3");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s3", "s2");
+    }
+
+    public void testUpdateShortcuts_withManifestShortcuts() {
+        runTestWithManifestShortcuts(() -> testUpdateShortcuts_noManifestShortcuts());
+    }
+
+    public void testDeleteDynamicShortcuts_noManifestShortcuts() {
+        mManager.addDynamicShortcuts(list(
+                shortcut("s5", A1, 0),
+                shortcut("s4", A1),
+                shortcut("s2", A1, 3),
+                shortcut("x1", A2),
+                shortcut("x3", A2, 2),
+                shortcut("x2", A2, 2),
+                shortcut("s3", A1, 0)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        //------------------------------------------------------
+        long lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.removeDynamicShortcuts(list());
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .isEmpty();
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(
+                    CALLING_PACKAGE, list("s2", "s4", "x1", "x2"), HANDLE_USER_0);
+        });
+        // Still same order.
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.removeDynamicShortcuts(list("s3", "x1", "xxxx"));
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s2", "s4");
+    }
+
+    public void testDeleteDynamicShortcuts_withManifestShortcuts() {
+        runTestWithManifestShortcuts(() -> testDeleteDynamicShortcuts_noManifestShortcuts());
+    }
+
+    public void testDisableShortcuts_noManifestShortcuts() {
+        mManager.addDynamicShortcuts(list(
+                shortcut("s5", A1, 0),
+                shortcut("s4", A1),
+                shortcut("s2", A1, 3),
+                shortcut("x1", A2),
+                shortcut("x3", A2, 2),
+                shortcut("x2", A2, 2),
+                shortcut("s3", A1, 0)
+        ));
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        //------------------------------------------------------
+        long lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.disableShortcuts(list());
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s3", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2", "x1");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .isEmpty();
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.disableShortcuts(list("s3", "x1", "xxxx"));
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s2", "s4");
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_0);
+        });
+        // Still same order.
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s2", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x3", "x2");
+
+        //------------------------------------------------------
+        lastApiTime = ++mInjectedCurrentTimeMillis;
+
+        mManager.disableShortcuts(list("s2", "x3"));
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
+                .haveRanksInOrder("s5", "s4");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A2)
+                .haveRanksInOrder("x2");
+
+        assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
+                .haveIds("s4", "x2");
+    }
+
+    public void testDisableShortcuts_withManifestShortcuts() {
+        runTestWithManifestShortcuts(() -> testDisableShortcuts_noManifestShortcuts());
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
index c03324a..b737033 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -86,7 +86,7 @@
     private void setEnabledAndValidPackageInfos(WebViewProviderInfo[] providers) {
         for(WebViewProviderInfo wpi : providers) {
             mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName, true /* enabled */,
-                        true /* valid */));
+                        true /* valid */, true /* installed */));
         }
     }
 
@@ -137,12 +137,17 @@
     }
 
     private static PackageInfo createPackageInfo(
-            String packageName, boolean enabled, boolean valid) {
+            String packageName, boolean enabled, boolean valid, boolean installed) {
         PackageInfo p = new PackageInfo();
         p.packageName = packageName;
         p.applicationInfo = new ApplicationInfo();
         p.applicationInfo.enabled = enabled;
         p.applicationInfo.metaData = new Bundle();
+        if (installed) {
+            p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
+        } else {
+            p.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
+        }
         if (valid) {
             // no flag means invalid
             p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah");
@@ -150,10 +155,23 @@
         return p;
     }
 
-    private static PackageInfo createPackageInfo(
-            String packageName, boolean enabled, boolean valid, Signature[] signatures) {
-        PackageInfo p = createPackageInfo(packageName, enabled, valid);
+    private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid,
+            boolean installed, Signature[] signatures, long updateTime) {
+        PackageInfo p = createPackageInfo(packageName, enabled, valid, installed);
         p.signatures = signatures;
+        p.lastUpdateTime = updateTime;
+        return p;
+    }
+
+    private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid,
+            boolean installed, Signature[] signatures, long updateTime, boolean hidden) {
+        PackageInfo p =
+            createPackageInfo(packageName, enabled, valid, installed, signatures, updateTime);
+        if (hidden) {
+            p.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
+        } else {
+            p.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
+        }
         return p;
     }
 
@@ -223,9 +241,11 @@
         setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
                 false /* isDebuggable */);
         mTestSystemImpl.setPackageInfo(createPackageInfo(invalidPackage, true /* enabled */,
-                    true /* valid */, new Signature[]{invalidPackageSignature}));
+                    true /* valid */, true /* installed */, new Signature[]{invalidPackageSignature}
+                    , 0 /* updateTime */));
         mTestSystemImpl.setPackageInfo(createPackageInfo(validPackage, true /* enabled */,
-                    true /* valid */, new Signature[]{validSignature}));
+                    true /* valid */, true /* installed */, new Signature[]{validSignature}
+                    , 0 /* updateTime */));
 
         mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
 
@@ -273,7 +293,8 @@
         WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi};
         setupWithPackages(packages);
         mTestSystemImpl.setPackageInfo(
-                createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */));
+                createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */,
+                    true /* installed */));
 
         mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
 
@@ -285,9 +306,10 @@
 
         // Verify that we can recover from failing to list webview packages.
         mTestSystemImpl.setPackageInfo(
-                createPackageInfo(wpi.packageName, true /* enabled */, true /* valid */));
+                createPackageInfo(wpi.packageName, true /* enabled */, true /* valid */,
+                    true /* installed */));
         mWebViewUpdateServiceImpl.packageStateChanged(wpi.packageName,
-                WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
 
         checkPreparationPhasesForPackage(wpi.packageName, 1);
     }
@@ -345,7 +367,7 @@
             // Have all packages be disabled so that we can change one to enabled later
             for(WebViewProviderInfo wpi : packages) {
                 mTestSystemImpl.setPackageInfo(createPackageInfo(wpi.packageName,
-                            false /* enabled */, true /* valid */));
+                            false /* enabled */, true /* valid */, true /* installed */));
             }
         }
 
@@ -371,7 +393,7 @@
             }
         }).start();
         try {
-            Thread.sleep(1000); // Let the new thread run / be blocked
+            Thread.sleep(500); // Let the new thread run / be blocked
         } catch (InterruptedException e) {
         }
 
@@ -380,9 +402,9 @@
         } else {
             // Switch provider by enabling the second one
             mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
-                        true /* valid */));
+                        true /* valid */, true /* installed */));
             mWebViewUpdateServiceImpl.packageStateChanged(
-                    secondPackage, WebViewUpdateService.PACKAGE_CHANGED);
+                    secondPackage, WebViewUpdateService.PACKAGE_CHANGED, 0);
         }
         mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
         // first package done, should start on second
@@ -432,9 +454,9 @@
 
         // Enable fallback package
         mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
-                        true /* valid */));
+                        true /* valid */, true /* installed */));
         mWebViewUpdateServiceImpl.packageStateChanged(
-                fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED);
+                fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED, 0);
 
         if (fallbackLogicEnabled) {
             // Check that we have now disabled the fallback package twice
@@ -463,7 +485,8 @@
                     fallbackPackage, "", true /* default available */, true /* fallback */, null)};
         setupWithPackages(packages, true /* isFallbackLogicEnabled */);
         mTestSystemImpl.setPackageInfo(
-                createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */));
+                createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */,
+                    true /* installed */));
 
         mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
         Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
@@ -474,9 +497,10 @@
 
         // Install primary package
         mTestSystemImpl.setPackageInfo(
-                createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */));
+                createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */,
+                    true /* installed */));
         mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
-                WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
 
         // Verify fallback disabled, primary package used as provider, and fallback package killed
         Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
@@ -507,9 +531,10 @@
 
         // Disable primary package and ensure fallback becomes enabled and used
         mTestSystemImpl.setPackageInfo(
-                createPackageInfo(primaryPackage, false /* enabled */, true /* valid */));
+                createPackageInfo(primaryPackage, false /* enabled */, true /* valid */,
+                    true /* installed */));
         mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
-                WebViewUpdateService.PACKAGE_CHANGED);
+                WebViewUpdateService.PACKAGE_CHANGED, 0);
 
         Mockito.verify(mTestSystemImpl).enablePackageForUser(
                 Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */,
@@ -520,9 +545,10 @@
 
         // Again enable primary package and verify primary is used and fallback becomes disabled
         mTestSystemImpl.setPackageInfo(
-                createPackageInfo(primaryPackage, true /* enabled */, true /* valid */));
+                createPackageInfo(primaryPackage, true /* enabled */, true /* valid */,
+                    true /* installed */));
         mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
-                WebViewUpdateService.PACKAGE_CHANGED);
+                WebViewUpdateService.PACKAGE_CHANGED, 0);
 
         // Verify fallback is disabled a second time when primary package becomes enabled
         Mockito.verify(mTestSystemImpl, Mockito.times(2)).enablePackageForUser(
@@ -593,9 +619,10 @@
 
         // Make packages invalid to cause exception to be thrown
         mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
-                    false /* valid */));
+                    false /* valid */, true /* installed */, null /* signatures */,
+                    0 /* updateTime */));
         mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
-                    false /* valid */));
+                    false /* valid */, true /* installed */));
 
         // This shouldn't throw an exception!
         mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
@@ -605,10 +632,11 @@
 
         // Now make a package valid again and verify that we can switch back to that
         mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
-                    true /* valid */));
+                    true /* valid */, true /* installed */, null /* signatures */,
+                    1 /* updateTime */ ));
 
         mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
-                WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
 
         // Ensure we use firstPackage
         checkPreparationPhasesForPackage(firstPackage, 2 /* second preparation for this package */);
@@ -634,16 +662,16 @@
 
         // Remove second package (invalidate it) and verify that first package is used
         mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
-                    false /* valid */));
+                    false /* valid */, true /* installed */));
         mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
-                WebViewUpdateService.PACKAGE_ADDED);
+                WebViewUpdateService.PACKAGE_ADDED, 0);
         checkPreparationPhasesForPackage(firstPackage, 2 /* second time for this package */);
 
         // Now make the second package valid again and verify that it is used again
         mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
-                    true /* valid */));
+                    true /* valid */, true /* installed */));
         mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
-                WebViewUpdateService.PACKAGE_ADDED);
+                WebViewUpdateService.PACKAGE_ADDED, 0);
         checkPreparationPhasesForPackage(secondPackage, 2 /* second time for this package */);
     }
 
@@ -663,7 +691,7 @@
         setupWithPackages(packages);
         // Only 'install' nonChosenPackage
         mTestSystemImpl.setPackageInfo(
-                createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */));
+                createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */, true /* installed */));
 
         // Set user-chosen package
         mTestSystemImpl.updateUserSetting(null, chosenPackage);
@@ -702,16 +730,16 @@
 
         // Make both packages invalid so that we fail listing WebView packages
         mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
-                    false /* valid */));
+                    false /* valid */, true /* installed */));
         mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
-                    false /* valid */));
+                    false /* valid */, true /* installed */));
 
         // Change package to hit the webview packages listing problem.
         if (settingsChange) {
             mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
         } else {
             mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
-                    WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+                    WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
         }
 
         WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
@@ -719,10 +747,10 @@
 
         // Make second package valid and verify that we can load it again
         mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
-                    true /* valid */));
+                    true /* valid */, true /* installed */));
 
         mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
-                WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
 
 
         checkPreparationPhasesForPackage(secondPackage, 1);
@@ -749,13 +777,14 @@
         // Replace or remove the current webview package
         if (replaced) {
             mTestSystemImpl.setPackageInfo(
-                    createPackageInfo(firstPackage, true /* enabled */, false /* valid */));
+                    createPackageInfo(firstPackage, true /* enabled */, false /* valid */,
+                        true /* installed */));
             mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
-                    WebViewUpdateService.PACKAGE_ADDED_REPLACED);
+                    WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
         } else {
             mTestSystemImpl.removePackageInfo(firstPackage);
             mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
-                    WebViewUpdateService.PACKAGE_REMOVED);
+                    WebViewUpdateService.PACKAGE_REMOVED, 0);
         }
 
         checkPreparationPhasesForPackage(secondPackage, 1);
@@ -806,7 +835,7 @@
         checkPreparationPhasesForPackage(thirdPackage, 1);
 
         mTestSystemImpl.setPackageInfo(
-                createPackageInfo(secondPackage, true /* enabled */, false /* valid */));
+                createPackageInfo(secondPackage, true /* enabled */, false /* valid */, true /* installed */));
 
         // Try to switch to the invalid second package, this should result in switching to the first
         // package, since that is more preferred than the third one.
@@ -817,4 +846,229 @@
 
         Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(thirdPackage));
     }
+
+    // Ensure that the update service uses an uninstalled package if that is the only package
+    // available.
+    public void testWithSingleUninstalledPackage() {
+        String testPackageName = "test.package.name";
+        WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
+                new WebViewProviderInfo(testPackageName, "",
+                        true /*default available*/, false /* fallback */, null)};
+        setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
+        mTestSystemImpl.setPackageInfo(createPackageInfo(testPackageName, true /* enabled */,
+                    true /* valid */, false /* installed */));
+
+        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+        checkPreparationPhasesForPackage(testPackageName, 1 /* first preparation phase */);
+    }
+
+    public void testNonhiddenPackageUserOverHidden() {
+        checkVisiblePackageUserOverNonVisible(false /* true == uninstalled, false == hidden */);
+    }
+
+    public void testInstalledPackageUsedOverUninstalled() {
+        checkVisiblePackageUserOverNonVisible(true /* true == uninstalled, false == hidden */);
+    }
+
+    private void checkVisiblePackageUserOverNonVisible(boolean uninstalledNotHidden) {
+        boolean testUninstalled = uninstalledNotHidden;
+        boolean testHidden = !uninstalledNotHidden;
+        String installedPackage = "installedPackage";
+        String uninstalledPackage = "uninstalledPackage";
+        WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
+            new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
+                    false /* fallback */, null),
+            new WebViewProviderInfo(installedPackage, "", true /* available by default */,
+                    false /* fallback */, null)};
+
+        setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
+        mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */,
+                    true /* valid */, true /* installed */));
+        mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */,
+                    true /* valid */, (testUninstalled ? false : true) /* installed */,
+                    null /* signatures */, 0 /* updateTime */, (testHidden ? true : false)));
+
+        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+        checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
+    }
+
+    public void testCantSwitchToHiddenPackage () {
+        checkCantSwitchToNonVisiblePackage(false /* true == uninstalled, false == hidden */);
+    }
+
+
+    public void testCantSwitchToUninstalledPackage () {
+        checkCantSwitchToNonVisiblePackage(true /* true == uninstalled, false == hidden */);
+    }
+
+    /**
+     * Ensure that we won't prioritize an uninstalled (or hidden) package even if it is user-chosen,
+     * and that an uninstalled (or hidden) package is not considered valid (in the
+     * getValidWebViewPackages() API).
+     */
+    private void checkCantSwitchToNonVisiblePackage(boolean uninstalledNotHidden) {
+        boolean testUninstalled = uninstalledNotHidden;
+        boolean testHidden = !uninstalledNotHidden;
+        String installedPackage = "installedPackage";
+        String uninstalledPackage = "uninstalledPackage";
+        WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
+            new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
+                    false /* fallback */, null),
+            new WebViewProviderInfo(installedPackage, "", true /* available by default */,
+                    false /* fallback */, null)};
+
+        setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
+        mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */,
+                    true /* valid */, true /* installed */));
+        mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */,
+                    true /* valid */, (testUninstalled ? false : true) /* installed */,
+                    null /* signatures */, 0 /* updateTime */,
+                    (testHidden ? true : false) /* hidden */));
+
+        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+        checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
+
+        // Ensure that only the installed package is considered valid
+        WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages();
+        assertEquals(1, validPackages.length);
+        assertEquals(installedPackage, validPackages[0].packageName);
+
+        // ensure that we don't switch to the uninstalled package (it will be used if it becomes
+        // installed later)
+        assertEquals(installedPackage,
+                mWebViewUpdateServiceImpl.changeProviderAndSetting(uninstalledPackage));
+
+        // We should only have called onWebViewProviderChanged once (before calling
+        // changeProviderAndSetting
+        Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged(
+                Mockito.argThat(new IsPackageInfoWithName(installedPackage)));
+    }
+
+    public void testHiddenPackageNotPrioritizedEvenIfChosen() {
+        checkNonvisiblePackageNotPrioritizedEvenIfChosen(
+                false /* true == uninstalled, false == hidden */);
+    }
+
+    public void testUninstalledPackageNotPrioritizedEvenIfChosen() {
+        checkNonvisiblePackageNotPrioritizedEvenIfChosen(
+                true /* true == uninstalled, false == hidden */);
+    }
+
+    public void checkNonvisiblePackageNotPrioritizedEvenIfChosen(boolean uninstalledNotHidden) {
+        boolean testUninstalled = uninstalledNotHidden;
+        boolean testHidden = !uninstalledNotHidden;
+        String installedPackage = "installedPackage";
+        String uninstalledPackage = "uninstalledPackage";
+        WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
+            new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
+                    false /* fallback */, null),
+            new WebViewProviderInfo(installedPackage, "", true /* available by default */,
+                    false /* fallback */, null)};
+
+        setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
+        mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */,
+                    true /* valid */, true /* installed */));
+        mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */,
+                    true /* valid */, (testUninstalled ? false : true) /* installed */,
+                    null /* signatures */, 0 /* updateTime */,
+                    (testHidden ? true : false) /* hidden */));
+
+        // Start with the setting pointing to the uninstalled package
+        mTestSystemImpl.updateUserSetting(null, uninstalledPackage);
+
+        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+        checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
+    }
+
+    /**
+     * Ensures that fallback becomes enabled if the primary package is uninstalled for the current
+     * user.
+     */
+    public void testFallbackEnabledIfPrimaryUninstalled() {
+        String primaryPackage = "primary";
+        String fallbackPackage = "fallback";
+        WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+            new WebViewProviderInfo(
+                    primaryPackage, "", true /* default available */, false /* fallback */, null),
+            new WebViewProviderInfo(
+                    fallbackPackage, "", true /* default available */, true /* fallback */, null)};
+        setupWithPackages(packages, true /* fallback logic enabled */);
+        mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
+                    true /* valid */, false /* installed */));
+        mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
+                    true /* valid */, true /* installed */));
+
+        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+        // Verify that we enable the fallback package
+        Mockito.verify(mTestSystemImpl).enablePackageForAllUsers(
+                Mockito.anyObject(), Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */);
+
+        checkPreparationPhasesForPackage(fallbackPackage, 1 /* first preparation phase */);
+    }
+
+    public void testPreparationRunsIffNewPackage() {
+        String primaryPackage = "primary";
+        String fallbackPackage = "fallback";
+        WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
+            new WebViewProviderInfo(
+                    primaryPackage, "", true /* default available */, false /* fallback */, null),
+            new WebViewProviderInfo(
+                    fallbackPackage, "", true /* default available */, true /* fallback */, null)};
+        setupWithPackages(packages, true /* fallback logic enabled */);
+        mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
+                    true /* valid */, true /* installed */, null /* signatures */,
+                    10 /* lastUpdateTime*/ ));
+        mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
+                    true /* valid */, true /* installed */));
+
+        mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
+
+        checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */);
+        Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
+                Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
+                Matchers.anyInt() /* user */);
+
+
+        mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0 /* userId */);
+        mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 1 /* userId */);
+        mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2 /* userId */);
+        // package still has the same update-time so we shouldn't run preparation here
+        Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged(
+                Mockito.argThat(new IsPackageInfoWithName(primaryPackage)));
+        Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
+                Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
+                Matchers.anyInt() /* user */);
+
+        // Ensure we can still load the package
+        WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
+        assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
+        assertEquals(primaryPackage, response.packageInfo.packageName);
+
+
+        mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
+                    true /* valid */, true /* installed */, null /* signatures */,
+                    20 /* lastUpdateTime*/ ));
+        mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
+        // The package has now changed - ensure that we have run the preparation phase a second time
+        checkPreparationPhasesForPackage(primaryPackage, 2 /* second preparation phase */);
+
+
+        mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
+                    true /* valid */, true /* installed */, null /* signatures */,
+                    50 /* lastUpdateTime*/ ));
+        // Receive intent for different user
+        mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
+                WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2);
+
+        checkPreparationPhasesForPackage(primaryPackage, 3 /* third preparation phase */);
+    }
+
 }
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 04c7a04..d9dbd5a 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -43,9 +43,11 @@
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.test.MoreAsserts;
+import android.util.ArraySet;
 import android.util.Log;
 
 import junit.framework.Assert;
+import junit.framework.AssertionFailedError;
 
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
@@ -58,10 +60,15 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
 import java.util.function.BooleanSupplier;
+import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
@@ -72,10 +79,12 @@
 public class ShortcutManagerTestUtils {
     private static final String TAG = "ShortcutManagerUtils";
 
-    private static final boolean ENABLE_DUMPSYS = true; // DO NOT SUBMIT WITH true
+    private static final boolean ENABLE_DUMPSYS = false; // DO NOT SUBMIT WITH true
 
     private static final int STANDARD_TIMEOUT_SEC = 5;
 
+    private static final String[] EMPTY_STRINGS = new String[0];
+
     private ShortcutManagerTestUtils() {
     }
 
@@ -228,7 +237,7 @@
     }
 
     public static <T> Set<T> hashSet(Set<T> in) {
-        return new HashSet<T>(in);
+        return new LinkedHashSet<>(in);
     }
 
     public static <T> Set<T> set(T... values) {
@@ -240,7 +249,7 @@
     }
 
     public static <T, V> Set<T> set(Function<V, T> converter, List<V> values) {
-        final HashSet<T> ret = new HashSet<>();
+        final LinkedHashSet<T> ret = new LinkedHashSet<>();
         for (V v : values) {
             ret.add(converter.apply(v));
         }
@@ -253,20 +262,29 @@
         }
     }
 
-    public static <T> List<T> assertEmpty(List<T> list) {
-        assertEquals(0, list.size());
-        return list;
+    public static <T extends Collection<?>> T assertEmpty(T collection) {
+        if (collection == null) {
+            return collection; // okay.
+        }
+        assertEquals(0, collection.size());
+        return collection;
+    }
+
+    public static List<ShortcutInfo> filter(List<ShortcutInfo> list, Predicate<ShortcutInfo> p) {
+        final ArrayList<ShortcutInfo> ret = new ArrayList<>(list);
+        ret.removeIf(si -> !p.test(si));
+        return ret;
     }
 
     public static List<ShortcutInfo> filterByActivity(List<ShortcutInfo> list,
             ComponentName activity) {
-        final ArrayList<ShortcutInfo> ret = new ArrayList<>();
-        for (ShortcutInfo si : list) {
-            if (si.getActivity().equals(activity) && (si.isManifestShortcut() || si.isDynamic())) {
-                ret.add(si);
-            }
-        }
-        return ret;
+        return filter(list, si ->
+                (si.getActivity().equals(activity)
+                        && (si.isManifestShortcut() || si.isDynamic())));
+    }
+
+    public static List<ShortcutInfo> changedSince(List<ShortcutInfo> list, long time) {
+        return filter(list, si -> si.getLastChangedTimestamp() >= time);
     }
 
     public static void assertExpectException(Class<? extends Throwable> expectedExceptionType,
@@ -305,8 +323,8 @@
 
     public static List<ShortcutInfo> assertShortcutIds(List<ShortcutInfo> actualShortcuts,
             String... expectedIds) {
-        final HashSet<String> expected = new HashSet<>(list(expectedIds));
-        final HashSet<String> actual = new HashSet<>();
+        final SortedSet<String> expected = new TreeSet<>(list(expectedIds));
+        final SortedSet<String> actual = new TreeSet<>();
         for (ShortcutInfo s : actualShortcuts) {
             actual.add(s.getId());
         }
@@ -316,6 +334,17 @@
         return actualShortcuts;
     }
 
+    public static List<ShortcutInfo> assertShortcutIdsOrdered(List<ShortcutInfo> actualShortcuts,
+            String... expectedIds) {
+        final ArrayList<String> expected = new ArrayList<>(list(expectedIds));
+        final ArrayList<String> actual = new ArrayList<>();
+        for (ShortcutInfo s : actualShortcuts) {
+            actual.add(s.getId());
+        }
+        assertEquals(expected, actual);
+        return actualShortcuts;
+    }
+
     public static List<ShortcutInfo> assertAllHaveIntents(
             List<ShortcutInfo> actualShortcuts) {
         for (ShortcutInfo s : actualShortcuts) {
@@ -482,7 +511,7 @@
     }
 
     public static <T> void assertAllUnique(Collection<T> list) {
-        final Set<Object> set = new HashSet<>();
+        final Set<Object> set = new LinkedHashSet<>();
         for (T item : list) {
             if (set.contains(item)) {
                 fail("Duplicate item found: " + item + " (in the list: " + list + ")");
@@ -594,6 +623,15 @@
         return ret;
     }
 
+    private static final Comparator<ShortcutInfo> sRankComparator =
+            (ShortcutInfo a, ShortcutInfo b) -> Integer.compare(a.getRank(), b.getRank());
+
+    public static List<ShortcutInfo> sortedByRank(List<ShortcutInfo> shortcuts) {
+        final ArrayList<ShortcutInfo> ret = new ArrayList<>(shortcuts);
+        Collections.sort(ret, sRankComparator);
+        return ret;
+    }
+
     public static void waitUntil(String message, BooleanSupplier condition) {
         waitUntil(message, condition, STANDARD_TIMEOUT_SEC);
     }
@@ -612,4 +650,205 @@
         }
         fail("Timed out for: " + message);
     }
+
+    public static ShortcutListAsserter assertWith(List<ShortcutInfo> list) {
+        return new ShortcutListAsserter(list);
+    }
+
+    /**
+     * New style assertion that allows chained calls.
+     */
+    public static class ShortcutListAsserter {
+        private final ShortcutListAsserter mOriginal;
+        private final List<ShortcutInfo> mList;
+
+        ShortcutListAsserter(List<ShortcutInfo> list) {
+            this(null, list);
+        }
+
+        private ShortcutListAsserter(ShortcutListAsserter original, List<ShortcutInfo> list) {
+            mOriginal = original == null ? this : original;
+            mList = new ArrayList<>(list);
+        }
+
+        public ShortcutListAsserter revertToOriginalList() {
+            return mOriginal;
+        }
+
+        public ShortcutListAsserter selectDynamic() {
+            return new ShortcutListAsserter(this,
+                    filter(mList, ShortcutInfo::isDynamic));
+        }
+
+        public ShortcutListAsserter selectManifest() {
+            return new ShortcutListAsserter(this,
+                    filter(mList, ShortcutInfo::isManifestShortcut));
+        }
+
+        public ShortcutListAsserter selectPinned() {
+            return new ShortcutListAsserter(this,
+                    filter(mList, ShortcutInfo::isPinned));
+        }
+
+        public ShortcutListAsserter selectByActivity(ComponentName activity) {
+            return new ShortcutListAsserter(this,
+                    ShortcutManagerTestUtils.filterByActivity(mList, activity));
+        }
+
+        public ShortcutListAsserter selectByChangedSince(long time) {
+            return new ShortcutListAsserter(this,
+                    ShortcutManagerTestUtils.changedSince(mList, time));
+        }
+
+        public ShortcutListAsserter selectByIds(String... ids) {
+            final Set<String> idSet = set(ids);
+            final ArrayList<ShortcutInfo> selected = new ArrayList<>();
+            for (ShortcutInfo si : mList) {
+                if (idSet.contains(si.getId())) {
+                    selected.add(si);
+                    idSet.remove(si.getId());
+                }
+            }
+            if (idSet.size() > 0) {
+                fail("Shortcuts not found for IDs=" + idSet);
+            }
+
+            return new ShortcutListAsserter(this, selected);
+        }
+
+        public ShortcutListAsserter toSortByRank() {
+            return new ShortcutListAsserter(this,
+                    ShortcutManagerTestUtils.sortedByRank(mList));
+        }
+
+        public ShortcutListAsserter call(Consumer<List<ShortcutInfo>> c) {
+            c.accept(mList);
+            return this;
+        }
+
+        public ShortcutListAsserter haveIds(String... expectedIds) {
+            assertShortcutIds(mList, expectedIds);
+            return this;
+        }
+
+        public ShortcutListAsserter haveIdsOrdered(String... expectedIds) {
+            assertShortcutIdsOrdered(mList, expectedIds);
+            return this;
+        }
+
+        private ShortcutListAsserter haveSequentialRanks() {
+            for (int i = 0; i < mList.size(); i++) {
+                final ShortcutInfo si = mList.get(i);
+                assertEquals("Rank not sequential: id=" + si.getId(), i, si.getRank());
+            }
+            return this;
+        }
+
+        public ShortcutListAsserter haveRanksInOrder(String... expectedIds) {
+            toSortByRank()
+                    .haveSequentialRanks()
+                    .haveIdsOrdered(expectedIds);
+            return this;
+        }
+
+        public ShortcutListAsserter isEmpty() {
+            assertEquals(0, mList.size());
+            return this;
+        }
+
+        public ShortcutListAsserter areAllDynamic() {
+            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isDynamic()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllNotDynamic() {
+            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isDynamic()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllPinned() {
+            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isPinned()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllNotPinned() {
+            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isPinned()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllManifest() {
+            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isManifestShortcut()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllNotManifest() {
+            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isManifestShortcut()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllImmutable() {
+            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isImmutable()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllMutable() {
+            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isImmutable()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllEnabled() {
+            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isEnabled()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllDisabled() {
+            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isEnabled()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllWithKeyFieldsOnly() {
+            forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.hasKeyFieldsOnly()));
+            return this;
+        }
+
+        public ShortcutListAsserter areAllNotWithKeyFieldsOnly() {
+            forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.hasKeyFieldsOnly()));
+            return this;
+        }
+
+        public ShortcutListAsserter forAllShortcuts(Consumer<ShortcutInfo> sa) {
+            boolean found = false;
+            for (int i = 0; i < mList.size(); i++) {
+                final ShortcutInfo si = mList.get(i);
+                found = true;
+                sa.accept(si);
+            }
+            assertTrue("No shortcuts found.", found);
+            return this;
+        }
+
+        public ShortcutListAsserter forShortcut(Predicate<ShortcutInfo> p,
+                Consumer<ShortcutInfo> sa) {
+            boolean found = false;
+            for (int i = 0; i < mList.size(); i++) {
+                final ShortcutInfo si = mList.get(i);
+                if (p.test(si)) {
+                    found = true;
+                    try {
+                        sa.accept(si);
+                    } catch (Throwable e) {
+                        throw new AssertionError("Assertion failed for shortcut " + si.getId(), e);
+                    }
+                }
+            }
+            assertTrue("Shortcut with the given condition not found.", found);
+            return this;
+        }
+
+        public ShortcutListAsserter forShortcutWithId(String id, Consumer<ShortcutInfo> sa) {
+            forShortcut(si -> si.getId().equals(id), sa);
+
+            return this;
+        }
+    }
 }
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index be04c90..0eabf15 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -83,6 +83,7 @@
     private StatusHints mStatusHints;
     private Bundle mExtras;
     private Set<String> mPreviousExtraKeys;
+    private final Object mExtrasLock = new Object();
 
     private final Connection.Listener mConnectionDeathListener = new Connection.Listener() {
         @Override
@@ -687,32 +688,35 @@
      * to remove extras.
      */
     public final void setExtras(@Nullable Bundle extras) {
-        // Add/replace any new or changed extras values.
-        putExtras(extras);
+        // Keeping putExtras and removeExtras in the same lock so that this operation happens as a
+        // block instead of letting other threads put/remove while this method is running.
+        synchronized (mExtrasLock) {
+            // Add/replace any new or changed extras values.
+            putExtras(extras);
+            // If we have used "setExtras" in the past, compare the key set from the last invocation
+            // to the current one and remove any keys that went away.
+            if (mPreviousExtraKeys != null) {
+                List<String> toRemove = new ArrayList<String>();
+                for (String oldKey : mPreviousExtraKeys) {
+                    if (extras == null || !extras.containsKey(oldKey)) {
+                        toRemove.add(oldKey);
+                    }
+                }
 
-        // If we have used "setExtras" in the past, compare the key set from the last invocation to
-        // the current one and remove any keys that went away.
-        if (mPreviousExtraKeys != null) {
-            List<String> toRemove = new ArrayList<String>();
-            for (String oldKey : mPreviousExtraKeys) {
-                if (extras == null || !extras.containsKey(oldKey)) {
-                    toRemove.add(oldKey);
+                if (!toRemove.isEmpty()) {
+                    removeExtras(toRemove);
                 }
             }
 
-            if (!toRemove.isEmpty()) {
-                removeExtras(toRemove);
+            // Track the keys the last time set called setExtras.  This way, the next time setExtras
+            // is called we can see if the caller has removed any extras values.
+            if (mPreviousExtraKeys == null) {
+                mPreviousExtraKeys = new ArraySet<String>();
             }
-        }
-
-        // Track the keys the last time set called setExtras.  This way, the next time setExtras is
-        // called we can see if the caller has removed any extras values.
-        if (mPreviousExtraKeys == null) {
-            mPreviousExtraKeys = new ArraySet<String>();
-        }
-        mPreviousExtraKeys.clear();
-        if (extras != null) {
-            mPreviousExtraKeys.addAll(extras.keySet());
+            mPreviousExtraKeys.clear();
+            if (extras != null) {
+                mPreviousExtraKeys.addAll(extras.keySet());
+            }
         }
     }
 
@@ -730,13 +734,19 @@
             return;
         }
 
-        if (mExtras == null) {
-            mExtras = new Bundle();
+        // Creating a Bundle clone so we don't have to synchronize on mExtrasLock while calling
+        // onExtrasChanged.
+        Bundle listenersBundle;
+        synchronized (mExtrasLock) {
+            if (mExtras == null) {
+                mExtras = new Bundle();
+            }
+            mExtras.putAll(extras);
+            listenersBundle = new Bundle(mExtras);
         }
-        mExtras.putAll(extras);
 
         for (Listener l : mListeners) {
-            l.onExtrasChanged(this, extras);
+            l.onExtrasChanged(this, new Bundle(listenersBundle));
         }
     }
 
@@ -789,17 +799,17 @@
             return;
         }
 
-        if (mExtras != null) {
-            for (String key : keys) {
-                mExtras.remove(key);
-            }
-            if (mExtras.size() == 0) {
-                mExtras = null;
+        synchronized (mExtrasLock) {
+            if (mExtras != null) {
+                for (String key : keys) {
+                    mExtras.remove(key);
+                }
             }
         }
 
+        List<String> unmodifiableKeys = Collections.unmodifiableList(keys);
         for (Listener l : mListeners) {
-            l.onExtrasRemoved(this, keys);
+            l.onExtrasRemoved(this, unmodifiableKeys);
         }
     }
 
@@ -849,7 +859,13 @@
      * @hide
      */
     final void handleExtrasChanged(Bundle extras) {
-        mExtras = extras;
-        onExtrasChanged(mExtras);
+        Bundle b = null;
+        synchronized (mExtrasLock) {
+            mExtras = extras;
+            if (mExtras != null) {
+                b = new Bundle(mExtras);
+            }
+        }
+        onExtrasChanged(b);
     }
 }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index c96f7c0..5843fbb 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -1243,6 +1243,7 @@
     private Conference mConference;
     private ConnectionService mConnectionService;
     private Bundle mExtras;
+    private final Object mExtrasLock = new Object();
 
     /**
      * Tracks the key set for the extras bundle provided on the last invocation of
@@ -1401,7 +1402,13 @@
      * @return The extras associated with this connection.
      */
     public final Bundle getExtras() {
-        return mExtras;
+        Bundle extras = null;
+        synchronized (mExtrasLock) {
+            if (mExtras != null) {
+                extras = new Bundle(mExtras);
+            }
+        }
+        return extras;
     }
 
     /**
@@ -1936,14 +1943,20 @@
         if (extras == null) {
             return;
         }
-
-        if (mExtras == null) {
-            mExtras = new Bundle();
+        // Creating a duplicate bundle so we don't have to synchronize on mExtrasLock while calling
+        // the listeners.
+        Bundle listenerExtras;
+        synchronized (mExtrasLock) {
+            if (mExtras == null) {
+                mExtras = new Bundle();
+            }
+            mExtras.putAll(extras);
+            listenerExtras = new Bundle(mExtras);
         }
-        mExtras.putAll(extras);
-
         for (Listener l : mListeners) {
-            l.onExtrasChanged(this, extras);
+            // Create a new clone of the extras for each listener so that they don't clobber
+            // each other
+            l.onExtrasChanged(this, new Bundle(listenerExtras));
         }
     }
 
@@ -1992,18 +2005,16 @@
      * @param keys The keys of the extras to remove.
      */
     public final void removeExtras(List<String> keys) {
-        if (mExtras != null) {
-            for (String key : keys) {
-                mExtras.remove(key);
-            }
-
-            if (mExtras.size() == 0) {
-                mExtras = null;
+        synchronized (mExtrasLock) {
+            if (mExtras != null) {
+                for (String key : keys) {
+                    mExtras.remove(key);
+                }
             }
         }
-
+        List<String> unmodifiableKeys = Collections.unmodifiableList(keys);
         for (Listener l : mListeners) {
-            l.onExtrasRemoved(this, keys);
+            l.onExtrasRemoved(this, unmodifiableKeys);
         }
     }
 
@@ -2291,8 +2302,14 @@
      * @hide
      */
     final void handleExtrasChanged(Bundle extras) {
-        mExtras = extras;
-        onExtrasChanged(mExtras);
+        Bundle b = null;
+        synchronized (mExtrasLock) {
+            mExtras = extras;
+            if (mExtras != null) {
+                b = new Bundle(mExtras);
+            }
+        }
+        onExtrasChanged(b);
     }
 
     /**
diff --git a/telecomm/java/android/telecom/ParcelableCallAnalytics.java b/telecomm/java/android/telecom/ParcelableCallAnalytics.java
index e7c9672..0ee9bab 100644
--- a/telecomm/java/android/telecom/ParcelableCallAnalytics.java
+++ b/telecomm/java/android/telecom/ParcelableCallAnalytics.java
@@ -20,11 +20,168 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @hide
  */
 @SystemApi
 public class ParcelableCallAnalytics implements Parcelable {
+    public static final class AnalyticsEvent implements Parcelable {
+        public static final int SET_SELECT_PHONE_ACCOUNT = 0;
+        public static final int SET_ACTIVE = 1;
+        public static final int SET_DISCONNECTED = 2;
+        public static final int START_CONNECTION = 3;
+        public static final int SET_DIALING = 4;
+        public static final int BIND_CS = 5;
+        public static final int CS_BOUND = 6;
+        public static final int REQUEST_ACCEPT = 7;
+        public static final int REQUEST_REJECT = 8;
+
+        public static final int SCREENING_SENT = 100;
+        public static final int SCREENING_COMPLETED = 101;
+        public static final int DIRECT_TO_VM_INITIATED = 102;
+        public static final int DIRECT_TO_VM_FINISHED = 103;
+        public static final int BLOCK_CHECK_INITIATED = 104;
+        public static final int BLOCK_CHECK_FINISHED = 105;
+        public static final int FILTERING_INITIATED = 106;
+        public static final int FILTERING_COMPLETED = 107;
+        public static final int FILTERING_TIMED_OUT = 108;
+
+        public static final int SKIP_RINGING = 200;
+        public static final int SILENCE = 201;
+        public static final int MUTE = 202;
+        public static final int UNMUTE = 203;
+        public static final int AUDIO_ROUTE_BT = 204;
+        public static final int AUDIO_ROUTE_EARPIECE = 205;
+        public static final int AUDIO_ROUTE_HEADSET = 206;
+        public static final int AUDIO_ROUTE_SPEAKER = 207;
+
+        public static final int CONFERENCE_WITH = 300;
+        public static final int SPLIT_CONFERENCE = 301;
+        public static final int SET_PARENT = 302;
+
+        public static final int REQUEST_HOLD = 400;
+        public static final int REQUEST_UNHOLD = 401;
+        public static final int REMOTELY_HELD = 402;
+        public static final int REMOTELY_UNHELD = 403;
+        public static final int SET_HOLD = 404;
+        public static final int SWAP = 405;
+
+        public static final int REQUEST_PULL = 500;
+
+
+        public static final Parcelable.Creator<AnalyticsEvent> CREATOR =
+                new Parcelable.Creator<AnalyticsEvent> () {
+
+                    @Override
+                    public AnalyticsEvent createFromParcel(Parcel in) {
+                        return new AnalyticsEvent(in);
+                    }
+
+                    @Override
+                    public AnalyticsEvent[] newArray(int size) {
+                        return new AnalyticsEvent[size];
+                    }
+                };
+
+        private int mEventName;
+        private long mTimeSinceLastEvent;
+
+        public AnalyticsEvent(int eventName, long timestamp) {
+            mEventName = eventName;
+            mTimeSinceLastEvent = timestamp;
+        }
+
+        AnalyticsEvent(Parcel in) {
+            mEventName = in.readInt();
+            mTimeSinceLastEvent = in.readLong();
+        }
+
+        public int getEventName() {
+            return mEventName;
+        }
+
+        public long getTimeSinceLastEvent() {
+            return mTimeSinceLastEvent;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeInt(mEventName);
+            out.writeLong(mTimeSinceLastEvent);
+        }
+    }
+
+    public static final class EventTiming implements Parcelable {
+        public static final int ACCEPT_TIMING = 0;
+        public static final int REJECT_TIMING = 1;
+        public static final int DISCONNECT_TIMING = 2;
+        public static final int HOLD_TIMING = 3;
+        public static final int UNHOLD_TIMING = 4;
+        public static final int OUTGOING_TIME_TO_DIALING_TIMING = 5;
+        public static final int BIND_CS_TIMING = 6;
+        public static final int SCREENING_COMPLETED_TIMING = 7;
+        public static final int DIRECT_TO_VM_FINISHED_TIMING = 8;
+        public static final int BLOCK_CHECK_FINISHED_TIMING = 9;
+        public static final int FILTERING_COMPLETED_TIMING = 10;
+        public static final int FILTERING_TIMED_OUT_TIMING = 11;
+
+        public static final int INVALID = 999999;
+
+        public static final Parcelable.Creator<EventTiming> CREATOR =
+                new Parcelable.Creator<EventTiming> () {
+
+                    @Override
+                    public EventTiming createFromParcel(Parcel in) {
+                        return new EventTiming(in);
+                    }
+
+                    @Override
+                    public EventTiming[] newArray(int size) {
+                        return new EventTiming[size];
+                    }
+                };
+
+        private int mName;
+        private long mTime;
+
+        public EventTiming(int name, long time) {
+            this.mName = name;
+            this.mTime = time;
+        }
+
+        private EventTiming(Parcel in) {
+            mName = in.readInt();
+            mTime = in.readLong();
+        }
+
+        public int getName() {
+            return mName;
+        }
+
+        public long getTime() {
+            return mTime;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeInt(mName);
+            out.writeLong(mTime);
+        }
+    }
+
     public static final int CALLTYPE_UNKNOWN = 0;
     public static final int CALLTYPE_INCOMING = 1;
     public static final int CALLTYPE_OUTGOING = 2;
@@ -87,10 +244,17 @@
     // Whether the call object was created from an existing connection.
     private final boolean isCreatedFromExistingConnection;
 
+    // A list of events that are associated with this call
+    private final List<AnalyticsEvent> analyticsEvents;
+
+    // A map from event-pair names to their durations.
+    private final List<EventTiming> eventTimings;
+
     public ParcelableCallAnalytics(long startTimeMillis, long callDurationMillis, int callType,
             boolean isAdditionalCall, boolean isInterrupted, int callTechnologies,
             int callTerminationCode, boolean isEmergencyCall, String connectionService,
-            boolean isCreatedFromExistingConnection) {
+            boolean isCreatedFromExistingConnection, List<AnalyticsEvent> analyticsEvents,
+            List<EventTiming> eventTimings) {
         this.startTimeMillis = startTimeMillis;
         this.callDurationMillis = callDurationMillis;
         this.callType = callType;
@@ -101,6 +265,8 @@
         this.isEmergencyCall = isEmergencyCall;
         this.connectionService = connectionService;
         this.isCreatedFromExistingConnection = isCreatedFromExistingConnection;
+        this.analyticsEvents = analyticsEvents;
+        this.eventTimings = eventTimings;
     }
 
     public ParcelableCallAnalytics(Parcel in) {
@@ -114,6 +280,10 @@
         isEmergencyCall = readByteAsBoolean(in);
         connectionService = in.readString();
         isCreatedFromExistingConnection = readByteAsBoolean(in);
+        analyticsEvents = new ArrayList<>();
+        in.readTypedList(analyticsEvents, AnalyticsEvent.CREATOR);
+        eventTimings = new ArrayList<>();
+        in.readTypedList(eventTimings, EventTiming.CREATOR);
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -127,6 +297,8 @@
         writeBooleanAsByte(out, isEmergencyCall);
         out.writeString(connectionService);
         writeBooleanAsByte(out, isCreatedFromExistingConnection);
+        out.writeTypedList(analyticsEvents);
+        out.writeTypedList(eventTimings);
     }
 
     public long getStartTimeMillis() {
@@ -169,6 +341,14 @@
         return isCreatedFromExistingConnection;
     }
 
+    public List<AnalyticsEvent> analyticsEvents() {
+        return analyticsEvents;
+    }
+
+    public List<EventTiming> getEventTimings() {
+        return eventTimings;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/telecomm/java/android/telecom/ParcelableCallAnalytics.aidl b/telecomm/java/android/telecom/TelecomAnalytics.aidl
similarity index 94%
rename from telecomm/java/android/telecom/ParcelableCallAnalytics.aidl
rename to telecomm/java/android/telecom/TelecomAnalytics.aidl
index b7e78d1..08ad0a2 100644
--- a/telecomm/java/android/telecom/ParcelableCallAnalytics.aidl
+++ b/telecomm/java/android/telecom/TelecomAnalytics.aidl
@@ -19,4 +19,4 @@
 /**
  * {@hide}
  */
-parcelable ParcelableCallAnalytics;
+parcelable TelecomAnalytics;
diff --git a/telecomm/java/android/telecom/TelecomAnalytics.java b/telecomm/java/android/telecom/TelecomAnalytics.java
new file mode 100644
index 0000000..6e0d02c
--- /dev/null
+++ b/telecomm/java/android/telecom/TelecomAnalytics.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.telecom;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide
+ */
+@SystemApi
+public final class TelecomAnalytics implements Parcelable {
+    public static final Parcelable.Creator<TelecomAnalytics> CREATOR =
+            new Parcelable.Creator<TelecomAnalytics> () {
+
+                @Override
+                public TelecomAnalytics createFromParcel(Parcel in) {
+                    return new TelecomAnalytics(in);
+                }
+
+                @Override
+                public TelecomAnalytics[] newArray(int size) {
+                    return new TelecomAnalytics[size];
+                }
+            };
+
+    public static final class SessionTiming extends TimedEvent<Integer> implements Parcelable {
+        public static final Parcelable.Creator<SessionTiming> CREATOR =
+                new Parcelable.Creator<SessionTiming> () {
+
+                    @Override
+                    public SessionTiming createFromParcel(Parcel in) {
+                        return new SessionTiming(in);
+                    }
+
+                    @Override
+                    public SessionTiming[] newArray(int size) {
+                        return new SessionTiming[size];
+                    }
+                };
+
+        public static final int ICA_ANSWER_CALL = 1;
+        public static final int ICA_REJECT_CALL = 2;
+        public static final int ICA_DISCONNECT_CALL = 3;
+        public static final int ICA_HOLD_CALL = 4;
+        public static final int ICA_UNHOLD_CALL = 5;
+        public static final int ICA_MUTE = 6;
+        public static final int ICA_SET_AUDIO_ROUTE = 7;
+        public static final int ICA_CONFERENCE = 8;
+
+        public static final int CSW_HANDLE_CREATE_CONNECTION_COMPLETE = 100;
+        public static final int CSW_SET_ACTIVE = 101;
+        public static final int CSW_SET_RINGING = 102;
+        public static final int CSW_SET_DIALING = 103;
+        public static final int CSW_SET_DISCONNECTED = 104;
+        public static final int CSW_SET_ON_HOLD = 105;
+        public static final int CSW_REMOVE_CALL = 106;
+        public static final int CSW_SET_IS_CONFERENCED = 107;
+        public static final int CSW_ADD_CONFERENCE_CALL = 108;
+
+        private int mId;
+        private long mTime;
+
+        public SessionTiming(int id, long time) {
+            this.mId = id;
+            this.mTime = time;
+        }
+
+        private SessionTiming(Parcel in) {
+            mId = in.readInt();
+            mTime = in.readLong();
+        }
+
+        @Override
+        public Integer getKey() {
+            return mId;
+        }
+
+        @Override
+        public long getTime() {
+            return mTime;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeInt(mId);
+            out.writeLong(mTime);
+        }
+    }
+
+    private List<SessionTiming> mSessionTimings;
+    private List<ParcelableCallAnalytics> mCallAnalytics;
+
+    public TelecomAnalytics(List<SessionTiming> sessionTimings,
+            List<ParcelableCallAnalytics> callAnalytics) {
+        this.mSessionTimings = sessionTimings;
+        this.mCallAnalytics = callAnalytics;
+    }
+
+    private TelecomAnalytics(Parcel in) {
+        mSessionTimings = new ArrayList<>();
+        in.readTypedList(mSessionTimings, SessionTiming.CREATOR);
+        mCallAnalytics = new ArrayList<>();
+        in.readTypedList(mCallAnalytics, ParcelableCallAnalytics.CREATOR);
+    }
+
+    public List<SessionTiming> getSessionTimings() {
+        return mSessionTimings;
+    }
+
+    public List<ParcelableCallAnalytics> getCallAnalytics() {
+        return mCallAnalytics;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeTypedList(mSessionTimings);
+        out.writeTypedList(mCallAnalytics);
+    }
+}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index ff5daaf..f12886a 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1443,9 +1443,9 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.DUMP)
-    public List<ParcelableCallAnalytics> dumpAnalytics() {
+    public TelecomAnalytics dumpAnalytics() {
         ITelecomService service = getTelecomService();
-        List<ParcelableCallAnalytics> result = null;
+        TelecomAnalytics result = null;
         if (service != null) {
             try {
                 result = service.dumpCallAnalytics();
diff --git a/telecomm/java/android/telecom/TimedEvent.java b/telecomm/java/android/telecom/TimedEvent.java
new file mode 100644
index 0000000..e484e79
--- /dev/null
+++ b/telecomm/java/android/telecom/TimedEvent.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.telecom;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @hide
+ */
+public abstract class TimedEvent<T> {
+    public abstract long getTime();
+    public abstract T getKey();
+
+    public static <T> Map<T, Double> averageTimings(Collection<? extends TimedEvent<T>> events) {
+        HashMap<T, Integer> counts = new HashMap<>();
+        HashMap<T, Double> result = new HashMap<>();
+
+        for (TimedEvent<T> entry : events) {
+            if (counts.containsKey(entry.getKey())) {
+                counts.put(entry.getKey(), counts.get(entry.getKey()) + 1);
+                result.put(entry.getKey(), result.get(entry.getKey()) + entry.getTime());
+            } else {
+                counts.put(entry.getKey(), 1);
+                result.put(entry.getKey(), (double) entry.getTime());
+            }
+        }
+
+        for (Map.Entry<T, Double> entry : result.entrySet()) {
+            result.put(entry.getKey(), entry.getValue() / counts.get(entry.getKey()));
+        }
+
+        return result;
+    }
+}
+
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 871565d..5c412e7 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -18,7 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.Intent;
-import android.telecom.ParcelableCallAnalytics;
+import android.telecom.TelecomAnalytics;
 import android.telecom.PhoneAccountHandle;
 import android.net.Uri;
 import android.os.Bundle;
@@ -148,7 +148,7 @@
     /**
     * @see TelecomServiceImpl#dumpCallAnalytics
     */
-    List<ParcelableCallAnalytics> dumpCallAnalytics();
+    TelecomAnalytics dumpCallAnalytics();
 
     //
     // Internal system apis relating to call management.
diff --git a/telephony/java/android/telephony/TelephonyHistogram.java b/telephony/java/android/telephony/TelephonyHistogram.java
index 9d9ce72..e1c3d7b 100644
--- a/telephony/java/android/telephony/TelephonyHistogram.java
+++ b/telephony/java/android/telephony/TelephonyHistogram.java
@@ -31,35 +31,35 @@
 public final class TelephonyHistogram implements Parcelable {
     // Type of Telephony histogram Eg: RIL histogram will have all timing data associated with
     // RIL calls. Similarly we can have any other Telephony histogram.
-    private final int category;
+    private final int mCategory;
 
     // Unique Id identifying a sample within particular category of histogram
-    private final int id;
+    private final int mId;
 
     // Min time taken in ms
-    private int minTimeMs;
+    private int mMinTimeMs;
 
     // Max time taken in ms
-    private int maxTimeMs;
+    private int mMaxTimeMs;
 
     // Average time taken in ms
-    private int averageTimeMs;
+    private int mAverageTimeMs;
 
     // Total count of samples
-    private int sampleCount;
+    private int mSampleCount;
 
     // Array storing time taken for first #RANGE_CALCULATION_COUNT samples of histogram.
-    private int[] initialTimings;
+    private int[] mInitialTimings;
 
     // Total number of time ranges expected (must be greater than 1)
-    private final int bucketCount;
+    private final int mBucketCount;
 
     // Array storing endpoints of range buckets. Calculated based on values of minTime & maxTime
     // after totalTimeCount is #RANGE_CALCULATION_COUNT.
-    private final int[] bucketEndPoints;
+    private final int[] mBucketEndPoints;
 
     // Array storing counts for each time range starting from smallest value range
-    private final int[] bucketCounters;
+    private final int[] mBucketCounters;
 
     /**
      * Constant for Telephony category
@@ -81,69 +81,85 @@
         if (bucketCount <= 1) {
             throw new IllegalArgumentException("Invalid number of buckets");
         }
-        this.category = category;
-        this.id = id;
-        this.minTimeMs = Integer.MAX_VALUE;
-        this.maxTimeMs = 0;
-        this.averageTimeMs = 0;
-        this.sampleCount = 0;
-        initialTimings = new int[RANGE_CALCULATION_COUNT];
-        this.bucketCount = bucketCount;
-        bucketEndPoints = new int[bucketCount - 1];
-        bucketCounters = new int[bucketCount];
+        mCategory = category;
+        mId = id;
+        mMinTimeMs = Integer.MAX_VALUE;
+        mMaxTimeMs = 0;
+        mAverageTimeMs = 0;
+        mSampleCount = 0;
+        mInitialTimings = new int[RANGE_CALCULATION_COUNT];
+        mBucketCount = bucketCount;
+        mBucketEndPoints = new int[bucketCount - 1];
+        mBucketCounters = new int[bucketCount];
     }
 
     public TelephonyHistogram(TelephonyHistogram th) {
-        category = th.getCategory();
-        id = th.getId();
-        minTimeMs = th.getMinTime();
-        maxTimeMs = th.getMaxTime();
-        averageTimeMs = th.getAverageTime();
-        sampleCount = th.getSampleCount();
-        initialTimings = th.getInitialTimings();
-        bucketCount = th.getBucketCount();
-        bucketEndPoints = th.getBucketEndPoints();
-        bucketCounters = th.getBucketCounters();
+        mCategory = th.getCategory();
+        mId = th.getId();
+        mMinTimeMs = th.getMinTime();
+        mMaxTimeMs = th.getMaxTime();
+        mAverageTimeMs = th.getAverageTime();
+        mSampleCount = th.getSampleCount();
+        mInitialTimings = th.getInitialTimings();
+        mBucketCount = th.getBucketCount();
+        mBucketEndPoints = th.getBucketEndPoints();
+        mBucketCounters = th.getBucketCounters();
     }
 
     public int getCategory() {
-        return category;
+        return mCategory;
     }
 
     public int getId() {
-        return id;
+        return mId;
     }
 
     public int getMinTime() {
-        return minTimeMs;
+        return mMinTimeMs;
     }
 
     public int getMaxTime() {
-        return maxTimeMs;
+        return mMaxTimeMs;
     }
 
     public int getAverageTime() {
-        return averageTimeMs;
+        return mAverageTimeMs;
     }
 
     public int getSampleCount () {
-        return sampleCount;
+        return mSampleCount;
     }
 
     private int[] getInitialTimings() {
-        return initialTimings;
+        return mInitialTimings;
     }
 
     public int getBucketCount() {
-        return bucketCount;
+        return mBucketCount;
     }
 
     public int[] getBucketEndPoints() {
-        return getDeepCopyOfArray(bucketEndPoints);
+        if (mSampleCount > 1 && mSampleCount < 10) {
+            int[] tempEndPoints = new int[mBucketCount - 1];
+            calculateBucketEndPoints(tempEndPoints);
+            return tempEndPoints;
+        } else {
+            return getDeepCopyOfArray(mBucketEndPoints);
+        }
     }
 
     public int[] getBucketCounters() {
-        return getDeepCopyOfArray(bucketCounters);
+        if (mSampleCount > 1 && mSampleCount < 10) {
+            int[] tempEndPoints = new int[mBucketCount - 1];
+            int[] tempBucketCounters = new int[mBucketCount];
+            calculateBucketEndPoints(tempEndPoints);
+            for (int j = 0; j < mSampleCount; j++) {
+                addToBucketCounter(tempEndPoints, tempBucketCounters, mInitialTimings[j]);
+            }
+            return tempBucketCounters;
+        } else {
+            return getDeepCopyOfArray(mBucketCounters);
+        }
     }
 
     private int[] getDeepCopyOfArray(int[] array) {
@@ -152,7 +168,7 @@
         return clone;
     }
 
-    private void addToBucketCounter(int time) {
+    private void addToBucketCounter(int[] bucketEndPoints, int[] bucketCounters, int time) {
         int i;
         for (i = 0; i < bucketEndPoints.length; i++) {
             if (time <= bucketEndPoints[i]) {
@@ -163,6 +179,13 @@
         bucketCounters[i]++;
     }
 
+    private void calculateBucketEndPoints(int[] bucketEndPoints) {
+        for (int i = 1; i < mBucketCount; i++) {
+            int endPt = mMinTimeMs + (i * (mMaxTimeMs - mMinTimeMs)) / mBucketCount;
+            bucketEndPoints[i - 1] = endPt;
+        }
+    }
+
     // Add new value of time taken
     // This function updates minTime, maxTime, averageTime & totalTimeCount every time it is
     // called. initialTimings[] is updated if totalTimeCount <= #RANGE_CALCULATION_COUNT. When
@@ -172,65 +195,62 @@
     public void addTimeTaken(int time) {
         // Initialize all fields if its first entry or if integer overflow is going to occur while
         // trying to calculate averageTime
-        if (sampleCount == 0 || (sampleCount == Integer.MAX_VALUE)) {
-            if (sampleCount == 0) {
-                minTimeMs = time;
-                maxTimeMs = time;
-                averageTimeMs = time;
+        if (mSampleCount == 0 || (mSampleCount == Integer.MAX_VALUE)) {
+            if (mSampleCount == 0) {
+                mMinTimeMs = time;
+                mMaxTimeMs = time;
+                mAverageTimeMs = time;
             } else {
-                initialTimings = new int[RANGE_CALCULATION_COUNT];
+                mInitialTimings = new int[RANGE_CALCULATION_COUNT];
             }
-            sampleCount = 1;
-            Arrays.fill(initialTimings, 0);
-            initialTimings[0] = time;
-            Arrays.fill(bucketEndPoints, 0);
-            Arrays.fill(bucketCounters, 0);
+            mSampleCount = 1;
+            Arrays.fill(mInitialTimings, 0);
+            mInitialTimings[0] = time;
+            Arrays.fill(mBucketEndPoints, 0);
+            Arrays.fill(mBucketCounters, 0);
         } else {
-            if (time < minTimeMs) {
-                minTimeMs = time;
+            if (time < mMinTimeMs) {
+                mMinTimeMs = time;
             }
-            if (time > maxTimeMs) {
-                maxTimeMs = time;
+            if (time > mMaxTimeMs) {
+                mMaxTimeMs = time;
             }
-            long totalTime = ((long)averageTimeMs) * sampleCount + time;
-            averageTimeMs = (int)(totalTime/++sampleCount);
+            long totalTime = ((long)mAverageTimeMs) * mSampleCount + time;
+            mAverageTimeMs = (int)(totalTime/++mSampleCount);
 
-            if (sampleCount < RANGE_CALCULATION_COUNT) {
-                initialTimings[sampleCount - 1] = time;
-            } else if (sampleCount == RANGE_CALCULATION_COUNT) {
-                initialTimings[sampleCount - 1] = time;
+            if (mSampleCount < RANGE_CALCULATION_COUNT) {
+                mInitialTimings[mSampleCount - 1] = time;
+            } else if (mSampleCount == RANGE_CALCULATION_COUNT) {
+                mInitialTimings[mSampleCount - 1] = time;
 
                 // Calculate bucket endpoints based on bucketCount expected
-                for (int i = 1; i < bucketCount; i++) {
-                    int endPt = minTimeMs + (i * (maxTimeMs - minTimeMs)) / bucketCount;
-                    bucketEndPoints[i - 1] = endPt;
-                }
+                calculateBucketEndPoints(mBucketEndPoints);
 
                 // Use values stored in initialTimings[] to update bucketCounters
                 for (int j = 0; j < RANGE_CALCULATION_COUNT; j++) {
-                    addToBucketCounter(initialTimings[j]);
+                    addToBucketCounter(mBucketEndPoints, mBucketCounters, mInitialTimings[j]);
                 }
-                initialTimings = null;
+                mInitialTimings = null;
             } else {
-                addToBucketCounter(time);
+                addToBucketCounter(mBucketEndPoints, mBucketCounters, time);
             }
 
         }
     }
 
     public String toString() {
-        String basic = " Histogram id = " + id + " Time(ms): min = " + minTimeMs + " max = "
-                + maxTimeMs + " avg = " + averageTimeMs + " Count = " + sampleCount;
-        if (sampleCount < RANGE_CALCULATION_COUNT) {
+        String basic = " Histogram id = " + mId + " Time(ms): min = " + mMinTimeMs + " max = "
+                + mMaxTimeMs + " avg = " + mAverageTimeMs + " Count = " + mSampleCount;
+        if (mSampleCount < RANGE_CALCULATION_COUNT) {
             return basic;
         } else {
             StringBuffer intervals = new StringBuffer(" Interval Endpoints:");
-            for (int i = 0; i < bucketEndPoints.length; i++) {
-                intervals.append(" " + bucketEndPoints[i]);
+            for (int i = 0; i < mBucketEndPoints.length; i++) {
+                intervals.append(" " + mBucketEndPoints[i]);
             }
             intervals.append(" Interval counters:");
-            for (int i = 0; i < bucketCounters.length; i++) {
-                intervals.append(" " + bucketCounters[i]);
+            for (int i = 0; i < mBucketCounters.length; i++) {
+                intervals.append(" " + mBucketCounters[i]);
             }
             return basic + intervals;
         }
@@ -251,39 +271,39 @@
             };
 
     public TelephonyHistogram(Parcel in) {
-        category = in.readInt();
-        id = in.readInt();
-        minTimeMs = in.readInt();
-        maxTimeMs = in.readInt();
-        averageTimeMs = in.readInt();
-        sampleCount = in.readInt();
+        mCategory = in.readInt();
+        mId = in.readInt();
+        mMinTimeMs = in.readInt();
+        mMaxTimeMs = in.readInt();
+        mAverageTimeMs = in.readInt();
+        mSampleCount = in.readInt();
         if (in.readInt() == PRESENT) {
-            initialTimings = new int[RANGE_CALCULATION_COUNT];
-            in.readIntArray(initialTimings);
+            mInitialTimings = new int[RANGE_CALCULATION_COUNT];
+            in.readIntArray(mInitialTimings);
         }
-        bucketCount = in.readInt();
-        bucketEndPoints = new int[bucketCount - 1];
-        in.readIntArray(bucketEndPoints);
-        bucketCounters = new int[bucketCount];
-        in.readIntArray(bucketCounters);
+        mBucketCount = in.readInt();
+        mBucketEndPoints = new int[mBucketCount - 1];
+        in.readIntArray(mBucketEndPoints);
+        mBucketCounters = new int[mBucketCount];
+        in.readIntArray(mBucketCounters);
     }
 
     public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(category);
-        out.writeInt(id);
-        out.writeInt(minTimeMs);
-        out.writeInt(maxTimeMs);
-        out.writeInt(averageTimeMs);
-        out.writeInt(sampleCount);
-        if (initialTimings == null) {
+        out.writeInt(mCategory);
+        out.writeInt(mId);
+        out.writeInt(mMinTimeMs);
+        out.writeInt(mMaxTimeMs);
+        out.writeInt(mAverageTimeMs);
+        out.writeInt(mSampleCount);
+        if (mInitialTimings == null) {
             out.writeInt(ABSENT);
         } else {
             out.writeInt(PRESENT);
-            out.writeIntArray(initialTimings);
+            out.writeIntArray(mInitialTimings);
         }
-        out.writeInt(bucketCount);
-        out.writeIntArray(bucketEndPoints);
-        out.writeIntArray(bucketCounters);
+        out.writeInt(mBucketCount);
+        out.writeIntArray(mBucketEndPoints);
+        out.writeIntArray(mBucketCounters);
     }
 
     @Override
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index e72fe49..8810cd9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1445,11 +1445,11 @@
     public static final int NETWORK_TYPE_EHRPD = 14;
     /** Current network is HSPA+ */
     public static final int NETWORK_TYPE_HSPAP = 15;
-    /** Current network is GSM {@hide} */
+    /** Current network is GSM */
     public static final int NETWORK_TYPE_GSM = 16;
-     /** Current network is TD_SCDMA {@hide} */
+    /** Current network is TD_SCDMA */
     public static final int NETWORK_TYPE_TD_SCDMA = 17;
-   /** Current network is IWLAN {@hide} */
+    /** Current network is IWLAN */
     public static final int NETWORK_TYPE_IWLAN = 18;
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 70a8653..6115656 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -184,7 +184,7 @@
      */
     void sendTextForSubscriberWithSelfPermissions(in int subId, String callingPkg,
             in String destAddr, in String scAddr, in String text, in PendingIntent sentIntent,
-            in PendingIntent deliveryIntent);
+            in PendingIntent deliveryIntent, in boolean persistMessage);
 
     /**
      * Inject an SMS PDU into the android platform.
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 0286506..a726a15 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -93,7 +93,7 @@
 
         try {
             mWm.addAppToken(0, null, 0, 0, 0, false, false, 0, 0, false, false, null,
-                    Configuration.EMPTY, 0, false, false);
+                    Configuration.EMPTY, 0, false, false, 0);
             fail("IWindowManager.addAppToken did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index ceebdd5..04a59bc 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -78,7 +78,7 @@
     @Override
     public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4,
             boolean arg5, boolean arg6, int arg7, int arg8, boolean arg9, boolean arg10,
-            Rect arg11, Configuration arg12, int arg13, boolean arg14, boolean arg15)
+            Rect arg11, Configuration arg12, int arg13, boolean arg14, boolean arg15, int arg16)
             throws RemoteException {
         // TODO Auto-generated method stub
     }
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index a404a90..590ff1b 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -691,7 +691,7 @@
 
         /**
          * spread (i.e. max - min) distance
-         * @deprecate Use {@link android.net.wifi.RttManager.RttResult#distanceSpread} API.
+         * @deprecated Use {@link android.net.wifi.RttManager.RttResult#distanceSpread} API.
          */
         @Deprecated
         public int distance_spread_cm;
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 2ee1aef..2636c3f 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -141,7 +141,7 @@
     /**
      * reports {@link ScanListener#onResults} when underlying buffers are full
      * this is simply the lack of the {@link #REPORT_EVENT_AFTER_EACH_SCAN} flag
-     * @deprecated
+     * @deprecated It is not supported anymore.
      */
     @Deprecated
     public static final int REPORT_EVENT_AFTER_BUFFER_FULL = 0;