Merge "Do not allow work profile apps to access main profile app."
diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk
index 3a7f945..200f92f 100644
--- a/apct-tests/perftests/core/Android.mk
+++ b/apct-tests/perftests/core/Android.mk
@@ -8,7 +8,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
-    apct-perftests-utils
+    apct-perftests-utils \
+    legacy-android-test
 
 LOCAL_PACKAGE_NAME := CorePerfTests
 
diff --git a/api/current.txt b/api/current.txt
index 3ca98b5..e7c628a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -83,6 +83,7 @@
     field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
     field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
+    field public static final java.lang.String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
     field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
     field public static final java.lang.String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
     field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
@@ -1053,6 +1054,7 @@
     field public static final int resizeable = 16843405; // 0x101028d
     field public static final int resizeableActivity = 16844022; // 0x10104f6
     field public static final int resource = 16842789; // 0x1010025
+    field public static final int restartOnConfigChanges = 16844105; // 0x1010549
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int restrictedAccountType = 16843733; // 0x10103d5
@@ -1377,7 +1379,7 @@
     field public static final int toYDelta = 16843209; // 0x10101c9
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int toolbarStyle = 16843946; // 0x10104aa
-    field public static final int tooltip = 16844084; // 0x1010534
+    field public static final int tooltipText = 16844084; // 0x1010534
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
     field public static final int topDark = 16842951; // 0x10100c7
@@ -2879,15 +2881,18 @@
   public class AccountManager {
     method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
-    method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, int[]);
+    method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
     method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
+    method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
     method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
     method public void clearPassword(android.accounts.Account);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public static android.accounts.AccountManager get(android.content.Context);
+    method public int getAccountVisibility(android.accounts.Account, int);
     method public android.accounts.Account[] getAccounts();
+    method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
     method public android.accounts.Account[] getAccountsByType(java.lang.String);
     method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler);
     method public android.accounts.Account[] getAccountsByTypeForPackage(java.lang.String, java.lang.String);
@@ -2898,13 +2903,11 @@
     method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
     method public java.lang.String getPassword(android.accounts.Account);
     method public java.lang.String getPreviousName(android.accounts.Account);
-    method public int[] getRequestingUidsForType(java.lang.String);
+    method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
     method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
     method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
     method public void invalidateAuthToken(java.lang.String, java.lang.String);
-    method public boolean isAccountVisible(android.accounts.Account, int);
     method public android.accounts.AccountManagerFuture<java.lang.Boolean> isCredentialsUpdateSuggested(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
-    method public boolean makeAccountVisible(android.accounts.Account, int);
     method public static deprecated android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle);
     method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.List<android.accounts.Account>, java.lang.String[], java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle);
     method public boolean notifyAccountAuthenticated(android.accounts.Account);
@@ -2912,9 +2915,9 @@
     method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public boolean removeAccountExplicitly(android.accounts.Account);
-    method public boolean removeAccountVisibility(android.accounts.Account, int);
     method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
     method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
+    method public boolean setAccountVisibility(android.accounts.Account, int, int);
     method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
     method public void setPassword(android.accounts.Account, java.lang.String);
     method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -2953,7 +2956,14 @@
     field public static final java.lang.String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime";
     field public static final java.lang.String KEY_PASSWORD = "password";
     field public static final java.lang.String KEY_USERDATA = "userdata";
-    field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
+    field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
+    field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
+    field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
+    field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
+    field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
+    field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4
+    field public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2; // 0x2
+    field public static final int VISIBILITY_VISIBLE = 1; // 0x1
   }
 
   public abstract interface AccountManagerCallback<V> {
@@ -4828,11 +4838,13 @@
   public static class Instrumentation.ActivityMonitor {
     ctor public Instrumentation.ActivityMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
     ctor public Instrumentation.ActivityMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
+    ctor public Instrumentation.ActivityMonitor();
     method public final android.content.IntentFilter getFilter();
     method public final int getHits();
     method public final android.app.Activity getLastActivity();
     method public final android.app.Instrumentation.ActivityResult getResult();
     method public final boolean isBlocking();
+    method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent);
     method public final android.app.Activity waitForActivity();
     method public final android.app.Activity waitForActivityWithTimeout(long);
   }
@@ -5401,7 +5413,6 @@
     method public java.lang.CharSequence getName();
     method public android.net.Uri getSound();
     method public long[] getVibrationPattern();
-    method public boolean isAllowed();
     method public void setBypassDnd(boolean);
     method public void setImportance(int);
     method public void setLights(boolean);
@@ -5439,6 +5450,7 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
+    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -6138,6 +6150,7 @@
     method public boolean isActivePasswordSufficient();
     method public boolean isAdminActive(android.content.ComponentName);
     method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
+    method public boolean isBackupServiceEnabled(android.content.ComponentName);
     method public boolean isCallerApplicationRestrictionsManagingPackage();
     method public boolean isDeviceOwnerApp(java.lang.String);
     method public boolean isLockTaskPermitted(java.lang.String);
@@ -6168,6 +6181,7 @@
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public void setAutoTimeRequired(android.content.ComponentName, boolean);
+    method public void setBackupServiceEnabled(android.content.ComponentName, boolean);
     method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
@@ -9532,6 +9546,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     method public final int getThemeResource();
+    field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000
     field public static final int CONFIG_DENSITY = 4096; // 0x1000
     field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
     field public static final int CONFIG_KEYBOARD = 16; // 0x10
@@ -9841,7 +9856,7 @@
     method public boolean accept(android.os.Bundle);
     method public boolean accept();
     method public int describeContents();
-    method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo();
+    method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context);
     method public int getRequestType();
     method public android.content.pm.ShortcutInfo getShortcutInfo();
     method public boolean isValid();
@@ -10527,7 +10542,9 @@
     method public int getLayoutDirection();
     method public android.os.LocaleList getLocales();
     method public boolean isLayoutSizeAtLeast(int);
+    method public boolean isScreenHdr();
     method public boolean isScreenRound();
+    method public boolean isScreenWideColorGamut();
     method public static boolean needNewResources(int, int);
     method public void readFromParcel(android.os.Parcel);
     method public void setLayoutDirection(java.util.Locale);
@@ -10537,6 +10554,16 @@
     method public void setToDefaults();
     method public int updateFrom(android.content.res.Configuration);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc
+    field public static final int COLORIMETRY_HDR_NO = 4; // 0x4
+    field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2
+    field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_HDR_YES = 8; // 0x8
+    field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2
     field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
     field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
     field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
@@ -10602,6 +10629,7 @@
     field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
     field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7
     field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6
+    field public int colorimetry;
     field public int densityDpi;
     field public float fontScale;
     field public int hardKeyboardHidden;
@@ -12587,7 +12615,6 @@
     method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
     method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
     method public float getFontSpacing();
-    method public java.lang.String getFontVariationSettings();
     method public int getHinting();
     method public float getLetterSpacing();
     method public android.graphics.MaskFilter getMaskFilter();
@@ -12645,7 +12672,6 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -21929,6 +21955,8 @@
     method public void setLocation(float, float);
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
+    method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
@@ -21947,7 +21975,9 @@
     field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
     field public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1; // 0x1
     field public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; // 0x320
+    field public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING = 802; // 0x322
     field public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801; // 0x321
+    field public static final int MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED = 803; // 0x323
     field public static final int MEDIA_RECORDER_INFO_UNKNOWN = 1; // 0x1
   }
 
@@ -24469,6 +24499,7 @@
   public class TrafficStats {
     ctor public TrafficStats();
     method public static void clearThreadStatsTag();
+    method public static int getAndSetThreadStatsTag(int);
     method public static long getMobileRxBytes();
     method public static long getMobileRxPackets();
     method public static long getMobileTxBytes();
@@ -30050,6 +30081,7 @@
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
+    method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();
@@ -35242,6 +35274,7 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
+    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
@@ -37180,6 +37213,7 @@
     method public void onReject();
     method public void onReject(java.lang.String);
     method public void onSeparate();
+    method public void onShowIncomingCallUi();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
@@ -37191,6 +37225,7 @@
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
+    method public final void setAudioRoute(int);
     method public final void setCallerDisplayName(java.lang.String, int);
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
     method public final void setConferenceables(java.util.List<android.telecom.Conferenceable>);
@@ -37239,6 +37274,7 @@
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
+    field public static final int PROPERTY_SELF_MANAGED = 128; // 0x80
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_DIALING = 3; // 0x3
     field public static final int STATE_DISCONNECTED = 6; // 0x6
@@ -37306,7 +37342,9 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConference(android.telecom.Connection, android.telecom.Connection);
     method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+    method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest);
     method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+    method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest);
     method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
     method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -37419,6 +37457,7 @@
     field public static final int CAPABILITY_CALL_SUBJECT = 64; // 0x40
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+    field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
@@ -37600,6 +37639,8 @@
     method public boolean handleMmi(java.lang.String);
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
+    method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
+    method public boolean isOutgoingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
     method public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
@@ -39023,6 +39064,7 @@
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
     method public android.content.ComponentName startService(android.content.Intent);
+    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean stopService(android.content.Intent);
     method public void unbindService(android.content.ServiceConnection);
     method public void unregisterReceiver(android.content.BroadcastReceiver);
@@ -42885,7 +42927,7 @@
     method public abstract android.view.SubMenu getSubMenu();
     method public abstract java.lang.CharSequence getTitle();
     method public abstract java.lang.CharSequence getTitleCondensed();
-    method public default java.lang.CharSequence getTooltip();
+    method public default java.lang.CharSequence getTooltipText();
     method public abstract boolean hasSubMenu();
     method public abstract boolean isActionViewExpanded();
     method public abstract boolean isCheckable();
@@ -42912,7 +42954,7 @@
     method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
     method public abstract android.view.MenuItem setTitle(int);
     method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
-    method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
+    method public default android.view.MenuItem setTooltipText(java.lang.CharSequence);
     method public abstract android.view.MenuItem setVisible(boolean);
     field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
     field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
@@ -43606,7 +43648,8 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
-    method public final java.lang.CharSequence getTooltip();
+    method public final deprecated java.lang.CharSequence getTooltip();
+    method public final java.lang.CharSequence getTooltipText();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
     method protected int getTopPaddingOffset();
@@ -43907,7 +43950,8 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
-    method public final void setTooltip(java.lang.CharSequence);
+    method public final deprecated void setTooltip(java.lang.CharSequence);
+    method public final void setTooltipText(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
     method public final void setTransitionName(java.lang.String);
@@ -49323,7 +49367,6 @@
     method public int getExtendedPaddingTop();
     method public android.text.InputFilter[] getFilters();
     method public java.lang.String getFontFeatureSettings();
-    method public java.lang.String getFontVariationSettings();
     method public boolean getFreezesText();
     method public int getGravity();
     method public int getHighlightColor();
@@ -49429,7 +49472,6 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 0b7ab38..e79ebdc 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -138,6 +138,7 @@
     field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
     field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
     field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
+    field public static final java.lang.String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
     field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
     field public static final java.lang.String MANAGE_USERS = "android.permission.MANAGE_USERS";
     field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
@@ -1162,6 +1163,7 @@
     field public static final int resizeable = 16843405; // 0x101028d
     field public static final int resizeableActivity = 16844022; // 0x10104f6
     field public static final int resource = 16842789; // 0x1010025
+    field public static final int restartOnConfigChanges = 16844105; // 0x1010549
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int restrictedAccountType = 16843733; // 0x10103d5
@@ -1490,7 +1492,7 @@
     field public static final int toYDelta = 16843209; // 0x10101c9
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int toolbarStyle = 16843946; // 0x10104aa
-    field public static final int tooltip = 16844084; // 0x1010534
+    field public static final int tooltipText = 16844084; // 0x1010534
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
     field public static final int topDark = 16842951; // 0x10100c7
@@ -2995,8 +2997,9 @@
   public class AccountManager {
     method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
-    method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, int[]);
+    method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
     method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
+    method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
     method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
     method public void clearPassword(android.accounts.Account);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
@@ -3004,7 +3007,9 @@
     method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSessionAsUser(android.os.Bundle, android.app.Activity, android.os.UserHandle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public static android.accounts.AccountManager get(android.content.Context);
+    method public int getAccountVisibility(android.accounts.Account, int);
     method public android.accounts.Account[] getAccounts();
+    method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
     method public android.accounts.Account[] getAccountsByType(java.lang.String);
     method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler);
     method public android.accounts.Account[] getAccountsByTypeForPackage(java.lang.String, java.lang.String);
@@ -3015,13 +3020,11 @@
     method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
     method public java.lang.String getPassword(android.accounts.Account);
     method public java.lang.String getPreviousName(android.accounts.Account);
-    method public int[] getRequestingUidsForType(java.lang.String);
+    method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
     method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
     method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
     method public void invalidateAuthToken(java.lang.String, java.lang.String);
-    method public boolean isAccountVisible(android.accounts.Account, int);
     method public android.accounts.AccountManagerFuture<java.lang.Boolean> isCredentialsUpdateSuggested(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
-    method public boolean makeAccountVisible(android.accounts.Account, int);
     method public static deprecated android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle);
     method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.List<android.accounts.Account>, java.lang.String[], java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle);
     method public boolean notifyAccountAuthenticated(android.accounts.Account);
@@ -3029,9 +3032,9 @@
     method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public boolean removeAccountExplicitly(android.accounts.Account);
-    method public boolean removeAccountVisibility(android.accounts.Account, int);
     method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
     method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
+    method public boolean setAccountVisibility(android.accounts.Account, int, int);
     method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
     method public void setPassword(android.accounts.Account, java.lang.String);
     method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -3070,7 +3073,14 @@
     field public static final java.lang.String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime";
     field public static final java.lang.String KEY_PASSWORD = "password";
     field public static final java.lang.String KEY_USERDATA = "userdata";
-    field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
+    field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
+    field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
+    field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
+    field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
+    field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
+    field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4
+    field public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2; // 0x2
+    field public static final int VISIBILITY_VISIBLE = 1; // 0x1
   }
 
   public abstract interface AccountManagerCallback<V> {
@@ -4985,11 +4995,13 @@
   public static class Instrumentation.ActivityMonitor {
     ctor public Instrumentation.ActivityMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
     ctor public Instrumentation.ActivityMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
+    ctor public Instrumentation.ActivityMonitor();
     method public final android.content.IntentFilter getFilter();
     method public final int getHits();
     method public final android.app.Activity getLastActivity();
     method public final android.app.Instrumentation.ActivityResult getResult();
     method public final boolean isBlocking();
+    method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent);
     method public final android.app.Activity waitForActivity();
     method public final android.app.Activity waitForActivityWithTimeout(long);
   }
@@ -5573,10 +5585,11 @@
     method public android.net.Uri getSound();
     method public int getUserLockedFields();
     method public long[] getVibrationPattern();
-    method public boolean isAllowed();
+    method public boolean isDeleted();
     method public void lockFields(int);
     method public void populateFromXml(org.xmlpull.v1.XmlPullParser);
     method public void setBypassDnd(boolean);
+    method public void setDeleted(boolean);
     method public void setImportance(int);
     method public void setLights(boolean);
     method public void setLockscreenVisibility(int);
@@ -5624,6 +5637,7 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
+    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -6339,6 +6353,7 @@
     method public boolean isActivePasswordSufficient();
     method public boolean isAdminActive(android.content.ComponentName);
     method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
+    method public boolean isBackupServiceEnabled(android.content.ComponentName);
     method public boolean isCallerApplicationRestrictionsManagingPackage();
     method public boolean isDeviceManaged();
     method public boolean isDeviceOwnerApp(java.lang.String);
@@ -6374,6 +6389,7 @@
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public void setAutoTimeRequired(android.content.ComponentName, boolean);
+    method public void setBackupServiceEnabled(android.content.ComponentName, boolean);
     method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
@@ -6738,6 +6754,7 @@
     method public boolean isBackupEnabled();
     method public java.lang.String[] listAllTransports();
     method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver);
+    method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver, int);
     method public int requestRestore(android.app.backup.RestoreObserver);
     method public java.lang.String selectBackupTransport(java.lang.String);
     method public void setAutoRestore(boolean);
@@ -6748,6 +6765,8 @@
     field public static final int ERROR_TRANSPORT_ABORTED = -1000; // 0xfffffc18
     field public static final int ERROR_TRANSPORT_PACKAGE_REJECTED = -1002; // 0xfffffc16
     field public static final int ERROR_TRANSPORT_QUOTA_EXCEEDED = -1005; // 0xfffffc13
+    field public static final int FLAG_NON_INCREMENTAL_BACKUP = 1; // 0x1
+    field public static final java.lang.String PACKAGE_MANAGER_SENTINEL = "@pm@";
     field public static final int SUCCESS = 0; // 0x0
   }
 
@@ -9926,6 +9945,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     method public final int getThemeResource();
+    field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000
     field public static final int CONFIG_DENSITY = 4096; // 0x1000
     field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
     field public static final int CONFIG_KEYBOARD = 16; // 0x10
@@ -10269,7 +10289,7 @@
     method public boolean accept(android.os.Bundle);
     method public boolean accept();
     method public int describeContents();
-    method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo();
+    method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context);
     method public int getRequestType();
     method public android.content.pm.ShortcutInfo getShortcutInfo();
     method public boolean isValid();
@@ -10616,6 +10636,7 @@
     field public static final java.lang.String FEATURE_SIP = "android.software.sip";
     field public static final java.lang.String FEATURE_SIP_VOIP = "android.software.sip.voip";
     field public static final java.lang.String FEATURE_TELEPHONY = "android.hardware.telephony";
+    field public static final java.lang.String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
     field public static final java.lang.String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
     field public static final java.lang.String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
     field public static final deprecated java.lang.String FEATURE_TELEVISION = "android.hardware.type.television";
@@ -11042,7 +11063,9 @@
     method public int getLayoutDirection();
     method public android.os.LocaleList getLocales();
     method public boolean isLayoutSizeAtLeast(int);
+    method public boolean isScreenHdr();
     method public boolean isScreenRound();
+    method public boolean isScreenWideColorGamut();
     method public static boolean needNewResources(int, int);
     method public void readFromParcel(android.os.Parcel);
     method public void setLayoutDirection(java.util.Locale);
@@ -11052,6 +11075,16 @@
     method public void setToDefaults();
     method public int updateFrom(android.content.res.Configuration);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc
+    field public static final int COLORIMETRY_HDR_NO = 4; // 0x4
+    field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2
+    field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_HDR_YES = 8; // 0x8
+    field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2
     field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
     field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
     field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
@@ -11117,6 +11150,7 @@
     field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
     field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7
     field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6
+    field public int colorimetry;
     field public int densityDpi;
     field public float fontScale;
     field public int hardKeyboardHidden;
@@ -13102,7 +13136,6 @@
     method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
     method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
     method public float getFontSpacing();
-    method public java.lang.String getFontVariationSettings();
     method public int getHinting();
     method public float getLetterSpacing();
     method public android.graphics.MaskFilter getMaskFilter();
@@ -13160,7 +13193,6 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -23486,6 +23518,8 @@
     method public void setLocation(float, float);
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
+    method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
@@ -23504,7 +23538,9 @@
     field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
     field public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1; // 0x1
     field public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; // 0x320
+    field public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING = 802; // 0x322
     field public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801; // 0x321
+    field public static final int MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED = 803; // 0x323
     field public static final int MEDIA_RECORDER_INFO_UNKNOWN = 1; // 0x1
   }
 
@@ -26344,6 +26380,8 @@
     method public android.net.wifi.WifiConfiguration[] getConnectableConfigs();
     method public android.net.wifi.WifiConfiguration getConnectedConfig();
     method public android.net.wifi.WifiConfiguration getDefaultWifiConfig();
+    method public int getLastSelectedNetworkId();
+    method public long getLastSelectedNetworkTimestamp();
     method public android.net.wifi.ScanResult[] getScanResults();
     method public void setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
     method public void setConnectedConfig(android.net.wifi.WifiConfiguration);
@@ -26357,6 +26395,7 @@
     method public android.net.RecommendationRequest.Builder setConnectableConfigs(android.net.wifi.WifiConfiguration[]);
     method public android.net.RecommendationRequest.Builder setConnectedWifiConfig(android.net.wifi.WifiConfiguration);
     method public android.net.RecommendationRequest.Builder setDefaultWifiConfig(android.net.wifi.WifiConfiguration);
+    method public android.net.RecommendationRequest.Builder setLastSelectedNetwork(int, long);
     method public android.net.RecommendationRequest.Builder setScanResults(android.net.wifi.ScanResult[]);
   }
 
@@ -26448,6 +26487,7 @@
     ctor public TrafficStats();
     method public static void clearThreadStatsTag();
     method public static void clearThreadStatsUid();
+    method public static int getAndSetThreadStatsTag(int);
     method public static long getMobileRxBytes();
     method public static long getMobileRxPackets();
     method public static long getMobileTxBytes();
@@ -27454,6 +27494,7 @@
     method public int describeContents();
     method public android.net.ProxyInfo getHttpProxy();
     method public boolean hasNoInternetAccess();
+    method public boolean isEphemeral();
     method public boolean isNoInternetAccessExpected();
     method public boolean isPasspoint();
     method public void setHttpProxy(android.net.ProxyInfo);
@@ -32694,6 +32735,7 @@
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
+    method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();
@@ -38145,6 +38187,7 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
+    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
@@ -40166,6 +40209,7 @@
     method public void onReject();
     method public void onReject(java.lang.String);
     method public void onSeparate();
+    method public void onShowIncomingCallUi();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
@@ -40177,6 +40221,7 @@
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
+    method public final void setAudioRoute(int);
     method public final void setCallerDisplayName(java.lang.String, int);
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
     method public final void setConferenceables(java.util.List<android.telecom.Conferenceable>);
@@ -40225,6 +40270,7 @@
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
+    field public static final int PROPERTY_SELF_MANAGED = 128; // 0x80
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_DIALING = 3; // 0x3
     field public static final int STATE_DISCONNECTED = 6; // 0x6
@@ -40292,7 +40338,9 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConference(android.telecom.Connection, android.telecom.Connection);
     method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+    method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest);
     method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+    method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest);
     method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
     method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -40529,6 +40577,7 @@
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+    field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
@@ -40767,6 +40816,8 @@
     method public boolean handleMmi(java.lang.String);
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
+    method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
+    method public boolean isOutgoingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isRinging();
     method public boolean isTtySupported();
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
@@ -41509,6 +41560,7 @@
     method public void enableVideoCalling(boolean);
     method public boolean endCall();
     method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+    method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
     method public int getCallState();
     method public android.os.PersistableBundle getCarrierConfig();
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
@@ -41584,6 +41636,7 @@
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
+    method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
     method public void setDataEnabled(boolean);
     method public void setDataEnabled(int, boolean);
     method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
@@ -42275,6 +42328,7 @@
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
     method public android.content.ComponentName startService(android.content.Intent);
+    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean stopService(android.content.Intent);
     method public void unbindService(android.content.ServiceConnection);
     method public void unregisterReceiver(android.content.BroadcastReceiver);
@@ -46145,7 +46199,7 @@
     method public abstract android.view.SubMenu getSubMenu();
     method public abstract java.lang.CharSequence getTitle();
     method public abstract java.lang.CharSequence getTitleCondensed();
-    method public default java.lang.CharSequence getTooltip();
+    method public default java.lang.CharSequence getTooltipText();
     method public abstract boolean hasSubMenu();
     method public abstract boolean isActionViewExpanded();
     method public abstract boolean isCheckable();
@@ -46172,7 +46226,7 @@
     method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
     method public abstract android.view.MenuItem setTitle(int);
     method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
-    method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
+    method public default android.view.MenuItem setTooltipText(java.lang.CharSequence);
     method public abstract android.view.MenuItem setVisible(boolean);
     field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
     field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
@@ -46866,7 +46920,8 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
-    method public final java.lang.CharSequence getTooltip();
+    method public final deprecated java.lang.CharSequence getTooltip();
+    method public final java.lang.CharSequence getTooltipText();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
     method protected int getTopPaddingOffset();
@@ -47167,7 +47222,8 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
-    method public final void setTooltip(java.lang.CharSequence);
+    method public final deprecated void setTooltip(java.lang.CharSequence);
+    method public final void setTooltipText(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
     method public final void setTransitionName(java.lang.String);
@@ -52943,7 +52999,6 @@
     method public int getExtendedPaddingTop();
     method public android.text.InputFilter[] getFilters();
     method public java.lang.String getFontFeatureSettings();
-    method public java.lang.String getFontVariationSettings();
     method public boolean getFreezesText();
     method public int getGravity();
     method public int getHighlightColor();
@@ -53049,7 +53104,6 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 30e35c5..f1144e9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -83,6 +83,7 @@
     field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
     field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
+    field public static final java.lang.String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
     field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
     field public static final java.lang.String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
     field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
@@ -1053,6 +1054,7 @@
     field public static final int resizeable = 16843405; // 0x101028d
     field public static final int resizeableActivity = 16844022; // 0x10104f6
     field public static final int resource = 16842789; // 0x1010025
+    field public static final int restartOnConfigChanges = 16844105; // 0x1010549
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int restrictedAccountType = 16843733; // 0x10103d5
@@ -1377,7 +1379,7 @@
     field public static final int toYDelta = 16843209; // 0x10101c9
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int toolbarStyle = 16843946; // 0x10104aa
-    field public static final int tooltip = 16844084; // 0x1010534
+    field public static final int tooltipText = 16844084; // 0x1010534
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
     field public static final int topDark = 16842951; // 0x10100c7
@@ -2879,15 +2881,18 @@
   public class AccountManager {
     method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
-    method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, int[]);
+    method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
     method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
+    method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
     method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
     method public void clearPassword(android.accounts.Account);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public static android.accounts.AccountManager get(android.content.Context);
+    method public int getAccountVisibility(android.accounts.Account, int);
     method public android.accounts.Account[] getAccounts();
+    method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
     method public android.accounts.Account[] getAccountsByType(java.lang.String);
     method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler);
     method public android.accounts.Account[] getAccountsByTypeForPackage(java.lang.String, java.lang.String);
@@ -2898,13 +2903,11 @@
     method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
     method public java.lang.String getPassword(android.accounts.Account);
     method public java.lang.String getPreviousName(android.accounts.Account);
-    method public int[] getRequestingUidsForType(java.lang.String);
+    method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
     method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
     method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
     method public void invalidateAuthToken(java.lang.String, java.lang.String);
-    method public boolean isAccountVisible(android.accounts.Account, int);
     method public android.accounts.AccountManagerFuture<java.lang.Boolean> isCredentialsUpdateSuggested(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
-    method public boolean makeAccountVisible(android.accounts.Account, int);
     method public static deprecated android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, java.lang.String[], boolean, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle);
     method public static android.content.Intent newChooseAccountIntent(android.accounts.Account, java.util.List<android.accounts.Account>, java.lang.String[], java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle);
     method public boolean notifyAccountAuthenticated(android.accounts.Account);
@@ -2912,9 +2915,9 @@
     method public deprecated android.accounts.AccountManagerFuture<java.lang.Boolean> removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public boolean removeAccountExplicitly(android.accounts.Account);
-    method public boolean removeAccountVisibility(android.accounts.Account, int);
     method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
     method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
+    method public boolean setAccountVisibility(android.accounts.Account, int, int);
     method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
     method public void setPassword(android.accounts.Account, java.lang.String);
     method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -2953,7 +2956,14 @@
     field public static final java.lang.String KEY_LAST_AUTHENTICATED_TIME = "lastAuthenticatedTime";
     field public static final java.lang.String KEY_PASSWORD = "password";
     field public static final java.lang.String KEY_USERDATA = "userdata";
-    field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
+    field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
+    field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
+    field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
+    field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
+    field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
+    field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4
+    field public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2; // 0x2
+    field public static final int VISIBILITY_VISIBLE = 1; // 0x1
   }
 
   public abstract interface AccountManagerCallback<V> {
@@ -4838,11 +4848,13 @@
   public static class Instrumentation.ActivityMonitor {
     ctor public Instrumentation.ActivityMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
     ctor public Instrumentation.ActivityMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
+    ctor public Instrumentation.ActivityMonitor();
     method public final android.content.IntentFilter getFilter();
     method public final int getHits();
     method public final android.app.Activity getLastActivity();
     method public final android.app.Instrumentation.ActivityResult getResult();
     method public final boolean isBlocking();
+    method public android.app.Instrumentation.ActivityResult onMatchIntent(android.content.Intent);
     method public final android.app.Activity waitForActivity();
     method public final android.app.Activity waitForActivityWithTimeout(long);
   }
@@ -5411,7 +5423,6 @@
     method public java.lang.CharSequence getName();
     method public android.net.Uri getSound();
     method public long[] getVibrationPattern();
-    method public boolean isAllowed();
     method public void setBypassDnd(boolean);
     method public void setImportance(int);
     method public void setLights(boolean);
@@ -5450,6 +5461,7 @@
     method public boolean removeAutomaticZenRule(java.lang.String);
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
+    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
@@ -6159,6 +6171,7 @@
     method public boolean isActivePasswordSufficient();
     method public boolean isAdminActive(android.content.ComponentName);
     method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
+    method public boolean isBackupServiceEnabled(android.content.ComponentName);
     method public boolean isCallerApplicationRestrictionsManagingPackage();
     method public boolean isDeviceManaged();
     method public boolean isDeviceOwnerApp(java.lang.String);
@@ -6190,6 +6203,7 @@
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setApplicationRestrictionsManagingPackage(android.content.ComponentName, java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public void setAutoTimeRequired(android.content.ComponentName, boolean);
+    method public void setBackupServiceEnabled(android.content.ComponentName, boolean);
     method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
@@ -9557,6 +9571,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, java.lang.String);
     method public final int getThemeResource();
+    field public static final int CONFIG_COLORIMETRY = 16384; // 0x4000
     field public static final int CONFIG_DENSITY = 4096; // 0x1000
     field public static final int CONFIG_FONT_SCALE = 1073741824; // 0x40000000
     field public static final int CONFIG_KEYBOARD = 16; // 0x10
@@ -9869,7 +9884,7 @@
     method public boolean accept(android.os.Bundle);
     method public boolean accept();
     method public int describeContents();
-    method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo();
+    method public android.appwidget.AppWidgetProviderInfo getAppWidgetProviderInfo(android.content.Context);
     method public int getRequestType();
     method public android.content.pm.ShortcutInfo getShortcutInfo();
     method public boolean isValid();
@@ -10559,7 +10574,9 @@
     method public int getLayoutDirection();
     method public android.os.LocaleList getLocales();
     method public boolean isLayoutSizeAtLeast(int);
+    method public boolean isScreenHdr();
     method public boolean isScreenRound();
+    method public boolean isScreenWideColorGamut();
     method public static boolean needNewResources(int, int);
     method public void readFromParcel(android.os.Parcel);
     method public void setLayoutDirection(java.util.Locale);
@@ -10569,6 +10586,16 @@
     method public void setToDefaults();
     method public int updateFrom(android.content.res.Configuration);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int COLORIMETRY_HDR_MASK = 12; // 0xc
+    field public static final int COLORIMETRY_HDR_NO = 4; // 0x4
+    field public static final int COLORIMETRY_HDR_SHIFT = 2; // 0x2
+    field public static final int COLORIMETRY_HDR_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_HDR_YES = 8; // 0x8
+    field public static final int COLORIMETRY_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 3; // 0x3
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 1; // 0x1
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0; // 0x0
+    field public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 2; // 0x2
     field public static final android.os.Parcelable.Creator<android.content.res.Configuration> CREATOR;
     field public static final int DENSITY_DPI_UNDEFINED = 0; // 0x0
     field public static final int HARDKEYBOARDHIDDEN_NO = 1; // 0x1
@@ -10634,6 +10661,7 @@
     field public static final int UI_MODE_TYPE_UNDEFINED = 0; // 0x0
     field public static final int UI_MODE_TYPE_VR_HEADSET = 7; // 0x7
     field public static final int UI_MODE_TYPE_WATCH = 6; // 0x6
+    field public int colorimetry;
     field public int densityDpi;
     field public float fontScale;
     field public int hardKeyboardHidden;
@@ -12619,7 +12647,6 @@
     method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
     method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
     method public float getFontSpacing();
-    method public java.lang.String getFontVariationSettings();
     method public int getHinting();
     method public float getLetterSpacing();
     method public android.graphics.MaskFilter getMaskFilter();
@@ -12677,7 +12704,6 @@
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
     method public void setHinting(int);
     method public void setLetterSpacing(float);
     method public void setLinearText(boolean);
@@ -22019,6 +22045,8 @@
     method public void setLocation(float, float);
     method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
     method public void setMaxFileSize(long) throws java.lang.IllegalArgumentException;
+    method public void setNextOutputFile(java.io.FileDescriptor) throws java.io.IOException, java.lang.IllegalStateException;
+    method public void setNextOutputFile(java.lang.String) throws java.io.IOException, java.lang.IllegalStateException;
     method public void setOnErrorListener(android.media.MediaRecorder.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaRecorder.OnInfoListener);
     method public void setOrientationHint(int);
@@ -22037,7 +22065,9 @@
     field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
     field public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1; // 0x1
     field public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; // 0x320
+    field public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING = 802; // 0x322
     field public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801; // 0x321
+    field public static final int MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED = 803; // 0x323
     field public static final int MEDIA_RECORDER_INFO_UNKNOWN = 1; // 0x1
   }
 
@@ -24559,6 +24589,7 @@
   public class TrafficStats {
     ctor public TrafficStats();
     method public static void clearThreadStatsTag();
+    method public static int getAndSetThreadStatsTag(int);
     method public static long getMobileRxBytes();
     method public static long getMobileRxPackets();
     method public static long getMobileTxBytes();
@@ -30162,6 +30193,7 @@
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
+    method public android.os.StrictMode.VmPolicy.Builder detectUntaggedSockets();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnCleartextNetwork();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeathOnFileUriExposure();
@@ -35363,6 +35395,7 @@
     field public static final int PURPOSE_ENCRYPT = 1; // 0x1
     field public static final int PURPOSE_SIGN = 4; // 0x4
     field public static final int PURPOSE_VERIFY = 8; // 0x8
+    field public static final int PURPOSE_WRAP_KEY = 16; // 0x10
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
     field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
   }
@@ -37301,6 +37334,7 @@
     method public void onReject();
     method public void onReject(java.lang.String);
     method public void onSeparate();
+    method public void onShowIncomingCallUi();
     method public void onStateChanged(int);
     method public void onStopDtmfTone();
     method public void onUnhold();
@@ -37312,6 +37346,7 @@
     method public final void setActive();
     method public final void setAddress(android.net.Uri, int);
     method public final void setAudioModeIsVoip(boolean);
+    method public final void setAudioRoute(int);
     method public final void setCallerDisplayName(java.lang.String, int);
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
     method public final void setConferenceables(java.util.List<android.telecom.Conferenceable>);
@@ -37360,6 +37395,7 @@
     field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
+    field public static final int PROPERTY_SELF_MANAGED = 128; // 0x80
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_DIALING = 3; // 0x3
     field public static final int STATE_DISCONNECTED = 6; // 0x6
@@ -37427,7 +37463,9 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConference(android.telecom.Connection, android.telecom.Connection);
     method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+    method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest);
     method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+    method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest);
     method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
     method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
     field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
@@ -37540,6 +37578,7 @@
     field public static final int CAPABILITY_CALL_SUBJECT = 64; // 0x40
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+    field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
@@ -37721,6 +37760,8 @@
     method public boolean handleMmi(java.lang.String);
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
     method public boolean isInCall();
+    method public boolean isIncomingCallPermitted(android.telecom.PhoneAccountHandle);
+    method public boolean isOutgoingCallPermitted(android.telecom.PhoneAccountHandle);
     method public boolean isVoiceMailNumber(android.telecom.PhoneAccountHandle, java.lang.String);
     method public void placeCall(android.net.Uri, android.os.Bundle);
     method public void registerPhoneAccount(android.telecom.PhoneAccount);
@@ -39145,6 +39186,7 @@
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
     method public void startIntentSender(android.content.IntentSender, android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
     method public android.content.ComponentName startService(android.content.Intent);
+    method public android.content.ComponentName startServiceInForeground(android.content.Intent, int, android.app.Notification);
     method public boolean stopService(android.content.Intent);
     method public void unbindService(android.content.ServiceConnection);
     method public void unregisterReceiver(android.content.BroadcastReceiver);
@@ -43174,7 +43216,7 @@
     method public abstract android.view.SubMenu getSubMenu();
     method public abstract java.lang.CharSequence getTitle();
     method public abstract java.lang.CharSequence getTitleCondensed();
-    method public default java.lang.CharSequence getTooltip();
+    method public default java.lang.CharSequence getTooltipText();
     method public abstract boolean hasSubMenu();
     method public abstract boolean isActionViewExpanded();
     method public abstract boolean isCheckable();
@@ -43201,7 +43243,7 @@
     method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
     method public abstract android.view.MenuItem setTitle(int);
     method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
-    method public default android.view.MenuItem setTooltip(java.lang.CharSequence);
+    method public default android.view.MenuItem setTooltipText(java.lang.CharSequence);
     method public abstract android.view.MenuItem setVisible(boolean);
     field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
     field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
@@ -43897,7 +43939,8 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
-    method public final java.lang.CharSequence getTooltip();
+    method public final deprecated java.lang.CharSequence getTooltip();
+    method public final java.lang.CharSequence getTooltipText();
     method public android.view.View getTooltipView();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
@@ -44199,7 +44242,8 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
-    method public final void setTooltip(java.lang.CharSequence);
+    method public final deprecated void setTooltip(java.lang.CharSequence);
+    method public final void setTooltipText(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
     method public final void setTransitionName(java.lang.String);
@@ -49627,7 +49671,6 @@
     method public int getExtendedPaddingTop();
     method public android.text.InputFilter[] getFilters();
     method public java.lang.String getFontFeatureSettings();
-    method public java.lang.String getFontVariationSettings();
     method public boolean getFreezesText();
     method public int getGravity();
     method public int getHighlightColor();
@@ -49733,7 +49776,6 @@
     method public void setExtractedText(android.view.inputmethod.ExtractedText);
     method public void setFilters(android.text.InputFilter[]);
     method public void setFontFeatureSettings(java.lang.String);
-    method public void setFontVariationSettings(java.lang.String);
     method protected boolean setFrame(int, int, int, int);
     method public void setFreezesText(boolean);
     method public void setGravity(int);
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 5bf8076..780db5e 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -270,7 +270,7 @@
         }
     }
 
-    private void backupNowAllPackages() {
+    private void backupNowAllPackages(boolean nonIncrementalBackup) {
         int userId = UserHandle.USER_SYSTEM;
         IPackageManager mPm =
                 IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
@@ -297,14 +297,19 @@
                     System.err.println(BMGR_NOT_RUNNING_ERR);
                 }
             }
-            backupNowPackages(packages);
+            backupNowPackages(packages, nonIncrementalBackup);
         }
     }
 
-    private void backupNowPackages(List<String> packages) {
+    private void backupNowPackages(List<String> packages, boolean nonIncrementalBackup) {
+        int flags = 0;
+        if (nonIncrementalBackup) {
+            flags |= BackupManager.FLAG_NON_INCREMENTAL_BACKUP;
+        }
         try {
             BackupObserver observer = new BackupObserver();
-            int err = mBmgr.requestBackup(packages.toArray(new String[packages.size()]), observer);
+            int err = mBmgr.requestBackup(packages.toArray(new String[packages.size()]), observer,
+                    flags);
             if (err == 0) {
                 // Off and running -- wait for the backup to complete
                 observer.waitForCompletion();
@@ -320,24 +325,31 @@
     private void doBackupNow() {
         String pkg;
         boolean backupAll = false;
+        boolean nonIncrementalBackup = false;
         ArrayList<String> allPkgs = new ArrayList<String>();
         while ((pkg = nextArg()) != null) {
             if (pkg.equals("--all")) {
                 backupAll = true;
+            } else if (pkg.equals("--non-incremental")) {
+                nonIncrementalBackup = true;
+            } else if (pkg.equals("--incremental")) {
+                nonIncrementalBackup = false;
             } else {
                 allPkgs.add(pkg);
             }
         }
         if (backupAll) {
             if (allPkgs.size() == 0) {
-                System.out.println("Running backup for all packages.");
-                backupNowAllPackages();
+                System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") +
+                        "incremental backup for all packages.");
+                backupNowAllPackages(nonIncrementalBackup);
             } else {
                 System.err.println("Provide only '--all' flag or list of packages.");
             }
         } else if (allPkgs.size() > 0) {
-            System.out.println("Running backup for " + allPkgs.size() +" requested packages.");
-            backupNowPackages(allPkgs);
+            System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") +
+                    "incremental backup for " + allPkgs.size() +" requested packages.");
+            backupNowPackages(allPkgs, nonIncrementalBackup);
         } else {
             System.err.println("Provide '--all' flag or list of packages.");
         }
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index de46b8c..f932388 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -36,8 +36,7 @@
 # Generate the stub source files
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(uiautomator.core_src_files)
-LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries)
-LOCAL_STATIC_JAVA_LIBRARIES := legacy-android-test
+LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries) legacy-android-test
 LOCAL_MODULE_CLASS := JAVA_LIBRARIES
 LOCAL_DROIDDOC_SOURCE_PATH := $(LOCAL_PATH)/core-src \
 	$(LOCAL_PATH)/testrunner-src
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 8185818..b27fa24 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -286,46 +286,31 @@
 
     /**
      * Account visibility was not set.
-     * @hide
      */
     public static final int VISIBILITY_UNDEFINED = 0;
 
     /**
      * Account is always visible to given application and only authenticator can revoke visibility.
-     * @hide
      */
     public static final int VISIBILITY_VISIBLE = 1;
 
     /**
      * Account is visible to given application, but user can revoke visibility.
-     * @hide
      */
     public static final int VISIBILITY_USER_MANAGED_VISIBLE = 2;
 
     /**
      * Account is not visible to given application and only authenticator can grant visibility.
-     * @hide
      */
     public static final int VISIBILITY_NOT_VISIBLE = 3;
 
     /**
      * Account is not visible to given application, but user can reveal it, for example, using
      * {@link #newChooseAccountIntent(Account, List, String[], String, String, String[], Bundle)}
-     * @hide
      */
     public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4;
 
     /**
-     * Key to manifest entry with a list of account types in which application is interested.
-     * Example value: "com.google;com.customtype". If it is  specified then the application
-     * will only get notifications related to the types in the list (see
-     * {@link #ACTION_VISIBLE_ACCOUNTS_CHANGED}). Authenticators managing whitelisted types will be
-     * able to know about the application using {@link #ACTION_ACCOUNTS_LISTENER_PACKAGE_INSTALLED}
-     * @hide
-     */
-    public static final String SUPPORTED_ACCOUNT_TYPES = "android.accounts.SupportedAccountTypes";
-
-    /**
      * Token type for the special case where a UID has access only to an account
      * but no authenticator specific auth token types.
      *
@@ -344,48 +329,27 @@
      *
      * @see #addOnAccountsUpdatedListener
      *
-     * Deprecated - use ACTION_VISIBLE_ACCOUNTS_CHANGED instead.
+     * @deprecated use #addOnAccountsUpdatedListener to get account updates in runtime.
      */
     public static final String LOGIN_ACCOUNTS_CHANGED_ACTION =
         "android.accounts.LOGIN_ACCOUNTS_CHANGED";
 
     /**
-     * Action sent as a broadcast Intent by the AccountsService when accounts potentially visible to
-     * the applications are added, accounts are removed, or an account's credentials (saved
-     * password, etc) are changed. List of supported account types shoud be specified in the
-     * Manifest file using {@link #SUPPORTED_ACCOUNT_TYPES}
-     *
-     * @see #addOnAccountsUpdatedListener
-     * @hide
-     */
-    public static final String ACTION_VISIBLE_ACCOUNTS_CHANGED =
-            "android.accounts.action.VISIBLE_ACCOUNTS_CHANGED";
-
-    /**
-     * Authenticators may subscribe to get notifications about apps interested in their managed account
-     * types using {@link #SUPPORTED_ACCOUNT_TYPES}.
-     * @hide
-     */
-    public static final String ACTION_ACCOUNTS_LISTENER_PACKAGE_INSTALLED =
-            "android.accounts.action.ACCOUNTS_LISTENER_PACKAGE_INSTALLED";
-
-    /**
      * Uid key to set default visibility for applications targeting API level
-     * {@link android.os.Build.VERSION_CODES#O} or above. See {@link #getAccountVisibility}. If the
-     * value was not set by authenticator USER_MANAGED_NOT_VISIBLE is used.
-     * @hide
+     * {@link android.os.Build.VERSION_CODES#O} or above and don't have the same signature as
+     * authenticator See {@link #getAccountVisibility}. If the value was not set by authenticator
+     * USER_MANAGED_NOT_VISIBLE is used.
      */
-    public static final int DEFAULT_VISIBILITY = -2;
+    public static final int UID_KEY_DEFAULT_VISIBILITY = -2;
 
     /**
      * Uid key to set visibility for applications targeting API level below
-     * {@link android.os.Build.VERSION_CODES#O}, which were able to see the account before. It
-     * includes applications with GET_ACCOUNTS permission or with the same signature as
-     * authenticator. See {@link #getAccountVisibility}. If the value was not set by authenticator
-     * USER_MANAGED_VISIBLE is used.
-     * @hide
+     * {@link android.os.Build.VERSION_CODES#O} with GET_ACCOUNS permission, or applications with
+     * any targeting API level with the same signature as authenticator. See
+     * {@link #getAccountVisibility}. If the value was not set by authenticator USER_MANAGED_VISIBLE
+     * is used.
      */
-    public static final int DEFAULT_LEGACY_VISIBILITY = -3;
+    public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3;
 
     /**
      * @hide
@@ -874,43 +838,11 @@
      * @param account The {@link Account} to add
      * @param password The password to associate with the account, null for none
      * @param extras String values to use for the account's userdata, null for none
-     * @param selectedUids Array of uids whose associated applications can access this account
-     *        without any additional user approval.
-     *
-     * @return True if the account was successfully added, false if the account already exists, the
-     *         account is null, or another error occurs.
-     */
-    public boolean addAccountExplicitly(Account account, String password, Bundle extras,
-            int[] selectedUids) {
-        return false; // TODO remove this method.
-    }
-
-    /**
-     * Adds an account directly to the AccountManager. Additionally this makes the Account visible
-     * to desired UIDs of applications on the device, and sends directed broadcasts to these
-     * individual applications.
-     * <p>
-     * Normally used by sign-up wizards associated with authenticators, not directly by
-     * applications.
-     * <p>
-     * Calling this method does not update the last authenticated timestamp, referred by
-     * {@link #KEY_LAST_AUTHENTICATED_TIME}. To update it, call
-     * {@link #notifyAccountAuthenticated(Account)} after getting success.
-     * <p>
-     * It is safe to call this method from the main thread.
-     * <p>
-     * This method requires the caller to have a signature match with the authenticator that owns
-     * the specified account.
-     *
-     * @param account The {@link Account} to add
-     * @param password The password to associate with the account, null for none
-     * @param extras String values to use for the account's userdata, null for none
      * @param visibility Map from uid to visibility values which will be set before account is
      *        added. See getAccountVisibility for possilbe values.
      *
      * @return True if the account was successfully added, false if the account already exists, the
      *         account is null, or another error occurs.
-     * @hide
      */
     public boolean addAccountExplicitly(Account account, String password, Bundle extras,
             Map<Integer, Integer> visibility) {
@@ -925,22 +857,18 @@
     }
 
     /**
-     * Returns all UIDs for applications that requested the account type.
-     * <p>This method requires the caller to have a signature match with the authenticator
-     * that owns the specified account.
+     * Returns UIDs of applications for which visibility of given account was explicitly set.
+     * <p>
+     * This method requires the caller to have a signature match with the authenticator that owns
+     * the specified account.
      *
-     * @param accountType The account type to be authenticated.
+     * @param account The account for which visibility data should be returned.
      *
-     * @return array of all UIDs that support accounts of this
-     * account type that seek approval (to be used to know which accounts for
-     * the authenticator to include in addAccountExplicitly). Null if none.
+     * @return Map from uid to visibility for given account
      */
-    public int[] getRequestingUidsForType(String accountType) {
-        try {
-            return mService.getRequestingUidsForType(accountType);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
+    public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) {
+        // TODO implement.
+        return null;
     }
 
     /**
@@ -954,9 +882,8 @@
      * @param packageName Package name.
      * @param accountType Account type.
      *
-     * @return Map with visibility for all accounts of given type. See {@link #getAccountVisibility}
-     *         for possilbe values.
-     * @hide
+     * @return Map with visibility for all accounts of given type.
+     * See {@link #getAccountVisibility} for possilbe values.
      */
     public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
             String accountType) {
@@ -971,67 +898,6 @@
     }
 
     /**
-     * Gives a certain UID, represented a application, access to an account
-     * <p>
-     * This method requires the caller to have a signature match with the authenticator that owns
-     * the specified account.
-     *
-     * @param account Account to make visible.
-     * @param uid The UID of the application to add account access.
-     *
-     * @return True if account made visible to application and was not previously visible.
-     */
-    public boolean makeAccountVisible(Account account, int uid) {
-        try {
-            return mService.setAccountVisibility(account, uid, VISIBILITY_USER_MANAGED_VISIBLE);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Removes visibility of certain account of a process identified by a given UID to an
-     * application. This is called by the Authenticator.
-     * <p>
-     * This method requires the caller to have a signature match with the authenticator that owns
-     * the specified account.
-     *
-     * @param account Remove visibility of this account..
-     * @param uid The UID of the application to remove account access.
-     *
-     * @return True if application access to account removed and was previously visible.
-     */
-    public boolean removeAccountVisibility(Account account, int uid) {
-        try {
-            return mService.setAccountVisibility(account, uid, VISIBILITY_USER_MANAGED_NOT_VISIBLE);
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Checks visibility of certain account of a process identified by a given UID. This is called
-     * by the Authenticator.
-     * <p>
-     * This method requires the caller to have a signature match with the authenticator that owns
-     * the specified account.
-     *
-     * @param account Account to check visibility.
-     * @param uid The UID of the application to check account access.
-     *
-     * @return True if application has access to the account
-     */
-    public boolean isAccountVisible(Account account, int uid) {
-        try {
-            Integer visibility = mService.getAccountVisibility(account, uid);
-            return visibility == VISIBILITY_USER_MANAGED_NOT_VISIBLE
-                    || visibility == VISIBILITY_VISIBLE;
-        } catch (RemoteException re) {
-            throw re.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Set visibility value of given account to certain UID.
      * <p>
      * See {@link #getAccountVisibility} for possible values.
@@ -1044,7 +910,6 @@
      * @param visibility - new visibility value.
      *
      * @return True if visibility value was succesfully updated.
-     * @hide
      */
     public boolean setAccountVisibility(Account account, int uid,
             @AccountVisibility int visibility) {
@@ -1058,6 +923,7 @@
     /**
      * Gets visibility of certain account for given UID. Possible returned values are:
      * <ul>
+     * <li>{@link #VISIBILITY_UNDEFINED}</li>
      * <li>{@link #VISIBILITY_VISIBLE}</li>
      * <li>{@link #VISIBILITY_USER_MANAGED_VISIBLE}</li>
      * <li>{@link #VISIBILITY_NOT_VISIBLE}
@@ -1072,7 +938,6 @@
      * @param uid The UID of the application to get account visibility.
      *
      * @return int Visibility for given account and uid.
-     * @hide
      */
     public @AccountVisibility int getAccountVisibility(Account account, int uid) {
         try {
@@ -2916,20 +2781,29 @@
     /**
      * Adds an {@link OnAccountsUpdateListener} to this instance of the {@link AccountManager}. This
      * listener will be notified whenever user or AbstractAcccountAuthenticator made changes to
-     * accounts related to the caller - either list of accounts returned by {@link #getAccounts()}
-     * was changed, or new account was added for which user can grant access to the caller.
+     * accounts of any type related to the caller. This method is equivalent to
+     * addOnAccountsUpdatedListener(listener, handler, updateImmediately, null)
      *
+     * @see #addOnAccountsUpdatedListener(OnAccountsUpdateListener, Handler, boolean, Handler,
+     *      String[])
+     */
+    public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
+            Handler handler, boolean updateImmediately) {
+        addOnAccountsUpdatedListener(listener, handler,updateImmediately, null);
+    }
+
+    /**
+     * Adds an {@link OnAccountsUpdateListener} to this instance of the {@link AccountManager}. This
+     * listener will be notified whenever user or AbstractAcccountAuthenticator made changes to
+     * accounts of given types related to the caller -
+     * either list of accounts returned by {@link #getAccounts()}
+     * was changed, or new account was added for which user can grant access to the caller.
      * <p>
      * As long as this listener is present, the AccountManager instance will not be
      * garbage-collected, and neither will the {@link Context} used to retrieve it, which may be a
      * large Activity instance. To avoid memory leaks, you must remove this listener before then.
      * Normally listeners are added in an Activity or Service's {@link Activity#onCreate} and
      * removed in {@link Activity#onDestroy}.
-     *
-     *
-     * If SUPPORTED_ACCOUNT_TYPES is specified in the manifest file, listener will only be
-     * notified about whitelisted types.
-     *
      * <p>
      * It is safe to call this method from the main thread.
      *
@@ -2938,11 +2812,12 @@
      *        main thread
      * @param updateImmediately If true, the listener will be invoked (on the handler thread) right
      *        away with the current account list
+     * @param accountTypes If set, only changes to accounts of given types will be reported.
      * @throws IllegalArgumentException if listener is null
      * @throws IllegalStateException if listener was already added
      */
     public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
-            Handler handler, boolean updateImmediately) {
+            Handler handler, boolean updateImmediately, String[] accountTypes) {
         if (listener == null) {
             throw new IllegalArgumentException("the listener is null");
         }
@@ -2958,11 +2833,11 @@
             if (wasEmpty) {
                 // Register a broadcast receiver to monitor account changes
                 IntentFilter intentFilter = new IntentFilter();
-                if (isVisibleAccountsChangedBroadcastSupported()) {
-                    intentFilter.addAction(ACTION_VISIBLE_ACCOUNTS_CHANGED);
-                } else {
-                    intentFilter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION);
-                }
+                // TODO get rid of the broadcast receiver
+                // create android.os.ResultReceiver
+                // send it to the service via aidl
+                // handle onReceiveResult
+                intentFilter.addAction(LOGIN_ACCOUNTS_CHANGED_ACTION);
                 // To recover from disk-full.
                 intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
                 // Register a broadcast receiver to monitor account changes
@@ -2975,26 +2850,6 @@
     }
 
     /**
-     * @hide
-     */
-    private boolean isVisibleAccountsChangedBroadcastSupported() {
-        String interestedTypes = null;
-        try {
-            String packageName = mContext.getOpPackageName();
-            ApplicationInfo ai = mContext.getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_META_DATA);
-            Bundle b = ai.metaData;
-            if (b == null) {
-                return false;
-            }
-            interestedTypes = b.getString(SUPPORTED_ACCOUNT_TYPES);
-        } catch (PackageManager.NameNotFoundException e) {
-            return false;
-        }
-        return !TextUtils.isEmpty(interestedTypes);
-    }
-
-    /**
      * Removes an {@link OnAccountsUpdateListener} previously registered with
      * {@link #addOnAccountsUpdatedListener}.  The listener will no longer
      * receive notifications of account changes.
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2e3c100..1d4b038 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -526,9 +526,13 @@
     /** @hide Mode for {@link IActivityManager#getAppStartMode}: delay running until later. */
     public static final int APP_START_MODE_DELAYED = 1;
 
+    /** @hide Mode for {@link IActivityManager#getAppStartMode}: delay running until later, with
+     * rigid errors (throwing exception). */
+    public static final int APP_START_MODE_DELAYED_RIGID = 2;
+
     /** @hide Mode for {@link IActivityManager#getAppStartMode}: disable/cancel pending
-     * launches. */
-    public static final int APP_START_MODE_DISABLED = 2;
+     * launches; this is the mode for ephemeral apps. */
+    public static final int APP_START_MODE_DISABLED = 3;
 
     /**
      * Lock task mode is not active.
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 87700dc..b1cba42 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -201,6 +201,17 @@
     public abstract void setPendingIntentWhitelistDuration(IIntentSender target, long duration);
 
     /**
+     * Allow DeviceIdleController to tell us about what apps are whitelisted.
+     */
+    public abstract void setDeviceIdleWhitelist(int[] appids);
+
+    /**
+     * Update information about which app IDs are on the temp whitelist.
+     */
+    public abstract void updateDeviceIdleTempWhitelist(int[] appids, int changingAppId,
+            boolean adding);
+
+    /**
      * Updates and persists the {@link Configuration} for a given user.
      *
      * @param values the configuration to update
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0b3ae3a..d814ddc 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -245,7 +245,7 @@
     boolean mSomeActivitiesChanged = false;
     boolean mUpdatingSystemConfig = false;
 
-    // These can be accessed by multiple threads; mPackages is the lock.
+    // These can be accessed by multiple threads; mResourcesManager is the lock.
     // XXX For now we keep around information about all packages we have
     // seen, not removing entries from this map.
     // NOTE: The activity and window managers need to call in to
@@ -254,12 +254,13 @@
     // holds their own lock.  Thus you MUST NEVER call back into the activity manager
     // or window manager or anything that depends on them while holding this lock.
     // These LoadedApk are only valid for the userId that we're running as.
-    final ArrayMap<String, WeakReference<LoadedApk>> mPackages
-            = new ArrayMap<String, WeakReference<LoadedApk>>();
-    final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages
-            = new ArrayMap<String, WeakReference<LoadedApk>>();
-    final ArrayList<ActivityClientRecord> mRelaunchingActivities
-            = new ArrayList<ActivityClientRecord>();
+    @GuardedBy("mResourcesManager")
+    final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<>();
+    @GuardedBy("mResourcesManager")
+    final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages = new ArrayMap<>();
+    @GuardedBy("mResourcesManager")
+    final ArrayList<ActivityClientRecord> mRelaunchingActivities = new ArrayList<>();
+    @GuardedBy("mResourcesManager")
     Configuration mPendingConfiguration = null;
     // Because we merge activity relaunch operations we can't depend on the ordering provided by
     // the handler messages. We need to introduce secondary ordering mechanism, which will allow
@@ -904,6 +905,10 @@
             sendMessage(H.CONFIGURATION_CHANGED, config);
         }
 
+        public void scheduleApplicationInfoChanged(ApplicationInfo ai) {
+            sendMessage(H.APPLICATION_INFO_CHANGED, ai);
+        }
+
         public void updateTimeZone() {
             TimeZone.setDefault(null);
         }
@@ -1448,6 +1453,7 @@
         public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153;
         public static final int LOCAL_VOICE_INTERACTION_STARTED = 154;
         public static final int ATTACH_AGENT = 155;
+        public static final int APPLICATION_INFO_CHANGED = 156;
 
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
@@ -1505,6 +1511,7 @@
                     case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED";
                     case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED";
                     case ATTACH_AGENT: return "ATTACH_AGENT";
+                    case APPLICATION_INFO_CHANGED: return "APPLICATION_INFO_CHANGED";
                 }
             }
             return Integer.toString(code);
@@ -1636,8 +1643,11 @@
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
                     mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
                     mUpdatingSystemConfig = true;
-                    handleConfigurationChanged((Configuration)msg.obj, null);
-                    mUpdatingSystemConfig = false;
+                    try {
+                        handleConfigurationChanged((Configuration) msg.obj, null);
+                    } finally {
+                        mUpdatingSystemConfig = false;
+                    }
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
                 case CLEAN_UP_CONTEXT:
@@ -1763,6 +1773,14 @@
                 case ATTACH_AGENT:
                     handleAttachAgent((String) msg.obj);
                     break;
+                case APPLICATION_INFO_CHANGED:
+                    mUpdatingSystemConfig = true;
+                    try {
+                        handleApplicationInfoChanged((ApplicationInfo) msg.obj);
+                    } finally {
+                        mUpdatingSystemConfig = false;
+                    }
+                    break;
             }
             Object obj = msg.obj;
             if (obj instanceof SomeArgs) {
@@ -3500,15 +3518,17 @@
                 }
                 r.activity.performResume();
 
-                // If there is a pending local relaunch that was requested when the activity was
-                // paused, it will put the activity into paused state when it finally happens.
-                // Since the activity resumed before being relaunched, we don't want that to happen,
-                // so we need to clear the request to relaunch paused.
-                for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) {
-                    final ActivityClientRecord relaunching = mRelaunchingActivities.get(i);
-                    if (relaunching.token == r.token
-                            && relaunching.onlyLocalRequest && relaunching.startsNotResumed) {
-                        relaunching.startsNotResumed = false;
+                synchronized (mResourcesManager) {
+                    // If there is a pending local relaunch that was requested when the activity was
+                    // paused, it will put the activity into paused state when it finally happens.
+                    // Since the activity resumed before being relaunched, we don't want that to
+                    // happen, so we need to clear the request to relaunch paused.
+                    for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) {
+                        final ActivityClientRecord relaunching = mRelaunchingActivities.get(i);
+                        if (relaunching.token == r.token
+                                && relaunching.onlyLocalRequest && relaunching.startsNotResumed) {
+                            relaunching.startsNotResumed = false;
+                        }
                     }
                 }
 
@@ -4898,6 +4918,53 @@
         }
     }
 
+    void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
+        // Updates triggered by package installation go through a package update
+        // receiver. Here we try to capture ApplicationInfo changes that are
+        // caused by other sources, such as overlays. That means we want to be as conservative
+        // about code changes as possible. Take the diff of the old ApplicationInfo and the new
+        // to see if anything needs to change.
+        synchronized (mResourcesManager) {
+            // Update all affected loaded packages with new package information
+            WeakReference<LoadedApk> ref = mPackages.get(ai.packageName);
+            LoadedApk apk = ref != null ? ref.get() : null;
+            if (apk != null) {
+                final ArrayList<String> oldPaths = new ArrayList<>();
+                LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths, null /*outLibPaths*/);
+                apk.updateApplicationInfo(ai, oldPaths);
+            }
+
+            ref = mResourcePackages.get(ai.packageName);
+            apk = ref != null ? ref.get() : null;
+            if (apk != null) {
+                final ArrayList<String> oldPaths = new ArrayList<>();
+                LoadedApk.makePaths(this, apk.getApplicationInfo(), oldPaths, null /*outLibPaths*/);
+                apk.updateApplicationInfo(ai, oldPaths);
+            }
+
+            // Update all affected Resources objects to use new ResourcesImpl
+            mResourcesManager.applyNewResourceDirsLocked(ai.sourceDir, ai.resourceDirs);
+        }
+
+        ApplicationPackageManager.configurationChanged();
+
+        // Trigger a regular Configuration change event, only with a different assetsSeq number
+        // so that we actually call through to all components.
+        Configuration newConfig = new Configuration();
+        newConfig.unset();
+        newConfig.assetsSeq = mConfiguration.assetsSeq + 1;
+        handleConfigurationChanged(newConfig, null);
+
+        // Schedule all activities to reload
+        for (final Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
+            final Activity activity = entry.getValue().activity;
+            if (!activity.mFinished) {
+                requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false,
+                        false);
+            }
+        }
+    }
+
     static void freeTextLayoutCachesIfNeeded(int configDiff) {
         if (configDiff != 0) {
             // Ask text layout engine to free its caches if there is a locale change
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 67fbc5a..9cc13ab 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -243,8 +243,10 @@
     public static final int OP_AUDIO_ACCESSIBILITY_VOLUME = 64;
     /** @hide Read the phone number. */
     public static final int OP_READ_PHONE_NUMBER = 65;
+    /** @hide Request package installs through package installer */
+    public static final int OP_REQUEST_INSTALL_PACKAGES = 66;
     /** @hide */
-    public static final int _NUM_OP = 66;
+    public static final int _NUM_OP = 67;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -461,6 +463,7 @@
             OP_RUN_IN_BACKGROUND,
             OP_AUDIO_ACCESSIBILITY_VOLUME,
             OP_READ_PHONE_NUMBER,
+            OP_REQUEST_INSTALL_PACKAGES,
     };
 
     /**
@@ -534,6 +537,7 @@
             null,
             null, // OP_AUDIO_ACCESSIBILITY_VOLUME
             OPSTR_READ_PHONE_NUMBER,
+            null, // OP_REQUEST_INSTALL_PACKAGES
     };
 
     /**
@@ -607,6 +611,7 @@
             "RUN_IN_BACKGROUND",
             "AUDIO_ACCESSIBILITY_VOLUME",
             "READ_PHONE_NUMBER",
+            "REQUEST_INSTALL_PACKAGES",
     };
 
     /**
@@ -680,6 +685,7 @@
             null, // no permission for running in background
             null, // no permission for changing accessibility volume
             Manifest.permission.READ_PHONE_NUMBER,
+            Manifest.permission.REQUEST_INSTALL_PACKAGES,
     };
 
     /**
@@ -754,6 +760,7 @@
             null, // RUN_IN_BACKGROUND
             UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ACCESSIBILITY_VOLUME
             null, // READ_PHONE_NUMBER
+            null, // REQUEST_INSTALL_PACKAGES
     };
 
     /**
@@ -827,6 +834,7 @@
             false, // RUN_IN_BACKGROUND
             false, // AUDIO_ACCESSIBILITY_VOLUME
             false, // READ_PHONE_NUMBER
+            false, // REQUEST_INSTALL_PACKAGES
     };
 
     /**
@@ -899,6 +907,7 @@
             AppOpsManager.MODE_ALLOWED,  // OP_RUN_IN_BACKGROUND
             AppOpsManager.MODE_ALLOWED,  // OP_AUDIO_ACCESSIBILITY_VOLUME
             AppOpsManager.MODE_ALLOWED,
+            AppOpsManager.MODE_DEFAULT, // OP_REQUEST_INSTALL_PACKAGES
     };
 
     /**
@@ -975,6 +984,7 @@
             false,
             false, // OP_AUDIO_ACCESSIBILITY_VOLUME
             false,
+            false, // OP_REQUEST_INSTALL_PACKAGES
     };
 
     /**
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f3185a8..20f7e63 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -24,6 +24,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
@@ -1386,7 +1387,7 @@
         }
     }
 
-    ApplicationPackageManager(ContextImpl context,
+    protected ApplicationPackageManager(ContextImpl context,
                               IPackageManager pm) {
         mContext = context;
         mPM = pm;
@@ -1820,6 +1821,12 @@
     @Override
     public @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app) {
         final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        return getPackageCurrentVolume(app, storage);
+    }
+
+    @VisibleForTesting
+    protected @Nullable VolumeInfo getPackageCurrentVolume(ApplicationInfo app,
+            StorageManager storage) {
         if (app.isInternal()) {
             return storage.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL);
         } else if (app.isExternalAsec()) {
@@ -1831,25 +1838,43 @@
 
     @Override
     public @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) {
-        final StorageManager storage = mContext.getSystemService(StorageManager.class);
-        final VolumeInfo currentVol = getPackageCurrentVolume(app);
-        final List<VolumeInfo> vols = storage.getVolumes();
+        final StorageManager storageManager = mContext.getSystemService(StorageManager.class);
+        return getPackageCandidateVolumes(app, storageManager, mPM);
+    }
+
+    @VisibleForTesting
+    protected @NonNull List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app,
+            StorageManager storageManager, IPackageManager pm) {
+        final VolumeInfo currentVol = getPackageCurrentVolume(app, storageManager);
+        final List<VolumeInfo> vols = storageManager.getVolumes();
         final List<VolumeInfo> candidates = new ArrayList<>();
         for (VolumeInfo vol : vols) {
-            if (Objects.equals(vol, currentVol) || isPackageCandidateVolume(mContext, app, vol)) {
+            if (Objects.equals(vol, currentVol)
+                    || isPackageCandidateVolume(mContext, app, vol, pm)) {
                 candidates.add(vol);
             }
         }
         return candidates;
     }
 
-    private boolean isPackageCandidateVolume(
-            ContextImpl context, ApplicationInfo app, VolumeInfo vol) {
-        final boolean forceAllowOnExternal = Settings.Global.getInt(
+    @VisibleForTesting
+    protected boolean isForceAllowOnExternal(Context context) {
+        return Settings.Global.getInt(
                 context.getContentResolver(), Settings.Global.FORCE_ALLOW_ON_EXTERNAL, 0) != 0;
-        // Private internal is always an option
+    }
+
+    @VisibleForTesting
+    protected boolean isAllow3rdPartyOnInternal(Context context) {
+        return context.getResources().getBoolean(
+                com.android.internal.R.bool.config_allow3rdPartyAppOnInternal);
+    }
+
+    private boolean isPackageCandidateVolume(
+            ContextImpl context, ApplicationInfo app, VolumeInfo vol, IPackageManager pm) {
+        final boolean forceAllowOnExternal = isForceAllowOnExternal(context);
+
         if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
-            return true;
+            return app.isSystemApp() || isAllow3rdPartyOnInternal(context);
         }
 
         // System apps and apps demanding internal storage can't be moved
@@ -1875,7 +1900,7 @@
 
         // Some apps can't be moved. (e.g. device admins)
         try {
-            if (mPM.isPackageDeviceAdminOnAnyUser(app.packageName)) {
+            if (pm.isPackageDeviceAdminOnAnyUser(app.packageName)) {
                 return false;
             }
         } catch (RemoteException e) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d08bee5..5e7d46f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1385,7 +1385,14 @@
     @Override
     public ComponentName startService(Intent service) {
         warnIfCallingFromSystemProcess();
-        return startServiceCommon(service, mUser);
+        return startServiceCommon(service, -1, null, mUser);
+    }
+
+    @Override
+    public ComponentName startServiceInForeground(Intent service,
+            int id, Notification notification) {
+        warnIfCallingFromSystemProcess();
+        return startServiceCommon(service, id, notification, mUser);
     }
 
     @Override
@@ -1396,16 +1403,24 @@
 
     @Override
     public ComponentName startServiceAsUser(Intent service, UserHandle user) {
-        return startServiceCommon(service, user);
+        return startServiceCommon(service, -1, null, user);
     }
 
-    private ComponentName startServiceCommon(Intent service, UserHandle user) {
+    @Override
+    public ComponentName startServiceInForegroundAsUser(Intent service,
+            int id, Notification notification, UserHandle user) {
+        return startServiceCommon(service, id, notification, user);
+    }
+
+    private ComponentName startServiceCommon(Intent service, int id, Notification notification,
+            UserHandle user) {
         try {
             validateServiceIntent(service);
             service.prepareToLeaveProcess(this);
             ComponentName cn = ActivityManager.getService().startService(
                 mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
-                            getContentResolver()), getOpPackageName(), user.getIdentifier());
+                            getContentResolver()), id, notification, getOpPackageName(),
+                            user.getIdentifier());
             if (cn != null) {
                 if (cn.getPackageName().equals("!")) {
                     throw new SecurityException(
@@ -1415,6 +1430,9 @@
                     throw new SecurityException(
                             "Unable to start service " + service
                             + ": " + cn.getClassName());
+                } else if (cn.getPackageName().equals("?")) {
+                    throw new IllegalStateException(
+                            "Not allowed to start service " + service + ": " + cn.getClassName());
                 }
             }
             return cn;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 5824c32..70b3f84 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -128,7 +128,8 @@
     void finishSubActivity(in IBinder token, in String resultWho, int requestCode);
     PendingIntent getRunningServiceControlPanel(in ComponentName service);
     ComponentName startService(in IApplicationThread caller, in Intent service,
-            in String resolvedType, in String callingPackage, int userId);
+            in String resolvedType, int id, in Notification notification,
+            in String callingPackage, int userId);
     int stopService(in IApplicationThread caller, in Intent service,
             in String resolvedType, int userId);
     int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
@@ -601,6 +602,8 @@
      */
     ActivityManager.TaskSnapshot getTaskSnapshot(int taskId);
 
+    void scheduleApplicationInfoChanged(in List<String> packageNames, int userId);
+
     // WARNING: when these transactions are updated, check if they are any callers on the native
     // side. If so, make sure they are using the correct transaction ids and arguments.
     // If a transaction which will also be used on the native side is being inserted, add it
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 7f168c9..41d1255 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -152,4 +152,5 @@
             IVoiceInteractor voiceInteractor);
     void handleTrustStorageUpdate();
     void attachAgent(String path);
+    void scheduleApplicationInfoChanged(in ApplicationInfo ai);
 }
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 07c21a5..f909af0 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -40,6 +40,7 @@
 {
     void cancelAllNotifications(String pkg, int userId);
 
+    void clearData(String pkg, int uid);
     void enqueueToast(String pkg, ITransientNotification callback, int duration);
     void cancelToast(String pkg, ITransientNotification callback);
     void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
@@ -54,10 +55,10 @@
     void createNotificationChannels(String pkg, in ParceledListSlice channelsList);
     void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
     NotificationChannel getNotificationChannel(String pkg, String channelId);
-    NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId);
+    NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, boolean includeDeleted);
     void deleteNotificationChannel(String pkg, String channelId);
     ParceledListSlice getNotificationChannels(String pkg);
-    ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid);
+    ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
 
     // TODO: Remove this when callers have been migrated to the equivalent
     // INotificationListener method.
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 6deedb6..5e420c0 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -31,8 +31,10 @@
      * Called whenever IActivityManager.startActivity is called on an activity that is already
      * running in the pinned stack and the activity is not actually started, but the task is either
      * brought to the front or a new Intent is delivered to it.
+     *
+     * @param sourceComponent the component name of the activity that initiated the restart attempt
      */
-    void onPinnedActivityRestartAttempt();
+    void onPinnedActivityRestartAttempt(in ComponentName sourceComponent);
 
     /**
      * Called whenever the pinned stack is done animating a resize.
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index cc7981c..b1bdea1 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -443,6 +443,7 @@
         private final String mClass;
         private final ActivityResult mResult;
         private final boolean mBlock;
+        private final boolean mIgnoreMatchingSpecificIntents;
 
 
         // This is protected by 'Instrumentation.this.mSync'.
@@ -454,7 +455,7 @@
         /**
          * Create a new ActivityMonitor that looks for a particular kind of 
          * intent to be started.
-         *  
+         *
          * @param which The set of intents this monitor is responsible for.
          * @param result A canned result to return if the monitor is hit; can 
          *               be null.
@@ -470,6 +471,7 @@
             mClass = null;
             mResult = result;
             mBlock = block;
+            mIgnoreMatchingSpecificIntents = false;
         }
 
         /**
@@ -491,6 +493,34 @@
             mClass = cls;
             mResult = result;
             mBlock = block;
+            mIgnoreMatchingSpecificIntents = false;
+        }
+
+        /**
+         * Create a new ActivityMonitor that can be used for intercepting any activity to be
+         * started.
+         *
+         * <p> When an activity is started, {@link #onMatchIntent(Intent)} will be called on
+         * instances created using this constructor to see if it is a hit.
+         *
+         * @see #onMatchIntent(Intent)
+         */
+        public ActivityMonitor() {
+            mWhich = null;
+            mClass = null;
+            mResult = null;
+            mBlock = false;
+            mIgnoreMatchingSpecificIntents = true;
+        }
+
+        /**
+         * @return true if this monitor is used for intercepting any started activity by calling
+         *         into {@link #onMatchIntent(Intent)}, false if this monitor is only used
+         *         for specific intents corresponding to the intent filter or activity class
+         *         passed in the constructor.
+         */
+        final boolean ignoreMatchingSpecificIntents() {
+            return mIgnoreMatchingSpecificIntents;
         }
 
         /**
@@ -577,10 +607,31 @@
                 }
             }
         }
-        
+
+        /**
+         * Used for intercepting any started activity.
+         *
+         * <p> A non-null return value here will be considered a hit for this monitor.
+         * By default this will return {@code null} and subclasses can override this to return
+         * a non-null value if the intent needs to be intercepted.
+         *
+         * <p> Whenever a new activity is started, this method will be called on instances created
+         * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case
+         * of a match, the activity start will be blocked and the returned result will be used.
+         *
+         * @param intent The intent used for starting the activity.
+         * @return The {@link ActivityResult} that needs to be used in case of a match.
+         */
+        public ActivityResult onMatchIntent(Intent intent) {
+            return null;
+        }
+
         final boolean match(Context who,
                             Activity activity,
                             Intent intent) {
+            if (mIgnoreMatchingSpecificIntents) {
+                return false;
+            }
             synchronized (this) {
                 if (mWhich != null
                     && mWhich.match(who.getContentResolver(), intent,
@@ -1492,7 +1543,14 @@
                 final int N = mActivityMonitors.size();
                 for (int i=0; i<N; i++) {
                     final ActivityMonitor am = mActivityMonitors.get(i);
-                    if (am.match(who, null, intent)) {
+                    ActivityResult result = null;
+                    if (am.ignoreMatchingSpecificIntents()) {
+                        result = am.onMatchIntent(intent);
+                    }
+                    if (result != null) {
+                        am.mHits++;
+                        return result;
+                    } else if (am.match(who, null, intent)) {
                         am.mHits++;
                         if (am.isBlocking()) {
                             return requestCode >= 0 ? am.getResult() : null;
@@ -1548,7 +1606,14 @@
                 final int N = mActivityMonitors.size();
                 for (int i=0; i<N; i++) {
                     final ActivityMonitor am = mActivityMonitors.get(i);
-                    if (am.match(who, null, intents[0])) {
+                    ActivityResult result = null;
+                    if (am.ignoreMatchingSpecificIntents()) {
+                        result = am.onMatchIntent(intents[0]);
+                    }
+                    if (result != null) {
+                        am.mHits++;
+                        return;
+                    } else if (am.match(who, null, intents[0])) {
                         am.mHits++;
                         if (am.isBlocking()) {
                             return;
@@ -1611,7 +1676,14 @@
                 final int N = mActivityMonitors.size();
                 for (int i=0; i<N; i++) {
                     final ActivityMonitor am = mActivityMonitors.get(i);
-                    if (am.match(who, null, intent)) {
+                    ActivityResult result = null;
+                    if (am.ignoreMatchingSpecificIntents()) {
+                        result = am.onMatchIntent(intent);
+                    }
+                    if (result != null) {
+                        am.mHits++;
+                        return result;
+                    } else if (am.match(who, null, intent)) {
                         am.mHits++;
                         if (am.isBlocking()) {
                             return requestCode >= 0 ? am.getResult() : null;
@@ -1671,7 +1743,14 @@
                 final int N = mActivityMonitors.size();
                 for (int i=0; i<N; i++) {
                     final ActivityMonitor am = mActivityMonitors.get(i);
-                    if (am.match(who, null, intent)) {
+                    ActivityResult result = null;
+                    if (am.ignoreMatchingSpecificIntents()) {
+                        result = am.onMatchIntent(intent);
+                    }
+                    if (result != null) {
+                        am.mHits++;
+                        return result;
+                    } else if (am.match(who, null, intent)) {
                         am.mHits++;
                         if (am.isBlocking()) {
                             return requestCode >= 0 ? am.getResult() : null;
@@ -1710,7 +1789,14 @@
                 final int N = mActivityMonitors.size();
                 for (int i=0; i<N; i++) {
                     final ActivityMonitor am = mActivityMonitors.get(i);
-                    if (am.match(who, null, intent)) {
+                    ActivityResult result = null;
+                    if (am.ignoreMatchingSpecificIntents()) {
+                        result = am.onMatchIntent(intent);
+                    }
+                    if (result != null) {
+                        am.mHits++;
+                        return result;
+                    } else if (am.match(who, null, intent)) {
                         am.mHits++;
                         if (am.isBlocking()) {
                             return requestCode >= 0 ? am.getResult() : null;
@@ -1748,7 +1834,14 @@
                 final int N = mActivityMonitors.size();
                 for (int i=0; i<N; i++) {
                     final ActivityMonitor am = mActivityMonitors.get(i);
-                    if (am.match(who, null, intent)) {
+                    ActivityResult result = null;
+                    if (am.ignoreMatchingSpecificIntents()) {
+                        result = am.onMatchIntent(intent);
+                    }
+                    if (result != null) {
+                        am.mHits++;
+                        return;
+                    } else if (am.match(who, null, intent)) {
                         am.mHits++;
                         if (am.isBlocking()) {
                             return;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index db1162a..4ab0743 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -262,7 +264,15 @@
         return ai.sharedLibraryFiles;
     }
 
-    public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
+    /**
+     * Update the ApplicationInfo for an app. If oldPaths is null, all the paths are considered
+     * new.
+     * @param aInfo The new ApplicationInfo to use for this LoadedApk
+     * @param oldPaths The code paths for the old ApplicationInfo object. null means no paths can
+     *                 be reused.
+     */
+    public void updateApplicationInfo(@NonNull ApplicationInfo aInfo,
+            @Nullable List<String> oldPaths) {
         setApplicationInfo(aInfo);
 
         final List<String> newPaths = new ArrayList<>();
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 09e95df..d2d7b6d 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -174,7 +174,7 @@
     @Override
     public void setContentDescription(CharSequence contentDescription) {
         super.setContentDescription(contentDescription);
-        setTooltip(contentDescription);
+        setTooltipText(contentDescription);
     }
 
     @Override
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index bdccb8a..56ef791 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -44,6 +44,7 @@
     private static final String TAG_CHANNEL = "channel";
     private static final String ATT_NAME = "name";
     private static final String ATT_ID = "id";
+    private static final String ATT_DELETED = "deleted";
     private static final String ATT_PRIORITY = "priority";
     private static final String ATT_VISIBILITY = "visibility";
     private static final String ATT_IMPORTANCE = "importance";
@@ -120,7 +121,7 @@
             NotificationManager.VISIBILITY_NO_OVERRIDE;
     private static final int DEFAULT_IMPORTANCE =
             NotificationManager.IMPORTANCE_UNSPECIFIED;
-    private static final boolean DEFAULT_ALLOWED = true;
+    private static final boolean DEFAULT_DELETED = false;
 
     private final String mId;
     private CharSequence mName;
@@ -133,7 +134,7 @@
     private int mUserLockedFields;
     private boolean mVibrationEnabled;
     private boolean mShowBadge;
-    private boolean mAllowed = DEFAULT_ALLOWED;
+    private boolean mDeleted = DEFAULT_DELETED;
 
     /**
      * Creates a notification channel.
@@ -170,7 +171,7 @@
         mUserLockedFields = in.readInt();
         mVibrationEnabled = in.readByte() != 0;
         mShowBadge = in.readByte() != 0;
-        mAllowed = in.readByte() != 0;
+        mDeleted = in.readByte() != 0;
     }
 
     @Override
@@ -196,7 +197,7 @@
         dest.writeInt(mUserLockedFields);
         dest.writeByte(mVibrationEnabled ? (byte) 1 : (byte) 0);
         dest.writeByte(mShowBadge ? (byte) 1 : (byte) 0);
-        dest.writeByte(mAllowed ? (byte) 1 : (byte) 0);
+        dest.writeByte(mDeleted ? (byte) 1 : (byte) 0);
     }
 
     /**
@@ -207,6 +208,14 @@
         mUserLockedFields |= field;
     }
 
+    /**
+     * @hide
+     */
+    @SystemApi
+    public void setDeleted(boolean deleted) {
+        mDeleted = deleted;
+    }
+
     // Modifiable by a notification ranker.
 
     /**
@@ -365,10 +374,11 @@
     }
 
     /**
-     * Returns whether notifications are allowed to post to this channel.
+     * @hide
      */
-    public boolean isAllowed() {
-        return mAllowed;
+    @SystemApi
+    public boolean isDeleted() {
+        return mDeleted;
     }
 
     /**
@@ -393,6 +403,7 @@
         enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false));
         setVibrationPattern(safeLongArray(parser, ATT_VIBRATION, null));
         setShowBadge(safeBool(parser, ATT_SHOW_BADGE, false));
+        setDeleted(safeBool(parser, ATT_DELETED, false));
         lockFields(safeInt(parser, ATT_USER_LOCKED, 0));
     }
 
@@ -434,6 +445,9 @@
         if (canShowBadge()) {
             out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
         }
+        if (isDeleted()) {
+            out.attribute(null, ATT_DELETED, Boolean.toString(isDeleted()));
+        }
 
         out.endTag(null, TAG_CHANNEL);
     }
@@ -464,6 +478,7 @@
         record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
         record.put(ATT_VIBRATION, longArrayToString(getVibrationPattern()));
         record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
+        record.put(ATT_DELETED, Boolean.toString(isDeleted()));
         return record;
     }
 
@@ -547,7 +562,7 @@
         if (mUserLockedFields != that.mUserLockedFields) return false;
         if (mVibrationEnabled != that.mVibrationEnabled) return false;
         if (mShowBadge != that.mShowBadge) return false;
-        if (mAllowed != that.mAllowed) return false;
+        if (mDeleted != that.mDeleted) return false;
         if (mId != null ? !mId.equals(that.mId) : that.mId != null) return false;
         if (mName != null ? !mName.equals(that.mName) : that.mName != null) return false;
         if (mSound != null ? !mSound.equals(that.mSound) : that.mSound != null) return false;
@@ -568,7 +583,7 @@
         result = 31 * result + mUserLockedFields;
         result = 31 * result + (mVibrationEnabled ? 1 : 0);
         result = 31 * result + (mShowBadge ? 1 : 0);
-        result = 31 * result + (mAllowed ? 1 : 0);
+        result = 31 * result + (mDeleted ? 1 : 0);
         return result;
     }
 
@@ -586,7 +601,7 @@
                 ", mUserLockedFields=" + mUserLockedFields +
                 ", mVibrationEnabled=" + mVibrationEnabled +
                 ", mShowBadge=" + mShowBadge +
-                ", mAllowed=" + mAllowed +
+                ", mDeleted=" + mDeleted +
                 '}';
     }
 }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 3551691..c0aae6d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -24,6 +24,7 @@
 import android.app.Notification.Builder;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
@@ -1085,4 +1086,38 @@
             default: return defValue;
         }
     }
+
+    /**
+     * Start a service directly into the "foreground service" state.  Unlike
+     * {@link android.content.Context#startService(Intent)}, this method
+     * can be used from within background operations like broadcast receivers
+     * or scheduled jobs.
+     *
+     * @param service Description of the service to be stopped.  The Intent must be either
+     *      fully explicit (supplying a component name) or specify a specific package
+     *      name it is targeted to.
+     * @param id The identifier for this notification as per
+     *      {@link #notify(int, Notification) NotificationManager.notify(int, Notification)};
+     *      must not be 0.
+     * @param notification The Notification to be displayed.
+     * @return If the service is being started or is already running, the
+     *      {@link ComponentName} of the actual service that was started is
+     *      returned; else if the service does not exist null is returned.
+     */
+    @Nullable
+    public ComponentName startServiceInForeground(Intent service,
+            int id, Notification notification) {
+        return mContext.startServiceInForeground(service, id, notification);
+    }
+
+    /**
+     * @hide like {@link #startServiceInForeground(Intent, int, Notification)}
+     * but for a specific user.
+     */
+    @Nullable
+    public ComponentName startServiceInForegroundAsUser(Intent service,
+            int id, Notification notification, UserHandle user) {
+        return mContext.startServiceInForegroundAsUser(service, id, notification, user);
+    }
+
 }
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 45831a3..94a8990 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -916,44 +916,85 @@
                 }
             }
 
-            // Bail early if there is no work to do.
-            if (updatedResourceKeys.isEmpty()) {
-                return;
+            redirectResourcesToNewImplLocked(updatedResourceKeys);
+        }
+    }
+
+    // TODO(adamlesinski): Make this accept more than just overlay directories.
+    final void applyNewResourceDirsLocked(@NonNull final String baseCodePath,
+            @NonNull final String[] newResourceDirs) {
+        try {
+            Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
+                    "ResourcesManager#applyNewResourceDirsLocked");
+
+            final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>();
+            final int implCount = mResourceImpls.size();
+            for (int i = 0; i < implCount; i++) {
+                final ResourcesKey key = mResourceImpls.keyAt(i);
+                final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
+                final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
+                if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) {
+                    updatedResourceKeys.put(impl, new ResourcesKey(
+                            key.mResDir,
+                            key.mSplitResDirs,
+                            newResourceDirs,
+                            key.mLibDirs,
+                            key.mDisplayId,
+                            key.mOverrideConfiguration,
+                            key.mCompatInfo));
+                }
             }
 
-            // 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();
+            invalidatePath("/");
+
+            redirectResourcesToNewImplLocked(updatedResourceKeys);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+        }
+    }
+
+    private void redirectResourcesToNewImplLocked(
+            @NonNull final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys) {
+        // 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 WeakReference<Resources> ref = mResourceReferences.get(i);
+            final Resources r = ref != null ? ref.get() : null;
+            if (r != null) {
+                final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
+                if (key != null) {
+                    final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
+                    if (impl == null) {
+                        throw new Resources.NotFoundException("failed to redirect ResourcesImpl");
+                    }
+                    r.setImpl(impl);
+                }
+            }
+        }
+
+        // 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 WeakReference<Resources> ref = activityResources.activityResources.get(i);
+                final Resources r = ref != null ? ref.get() : null;
                 if (r != null) {
                     final ResourcesKey key = updatedResourceKeys.get(r.getImpl());
                     if (key != null) {
                         final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
                         if (impl == null) {
-                            throw new Resources.NotFoundException("failed to load " + libAsset);
+                            throw new Resources.NotFoundException(
+                                    "failed to redirect ResourcesImpl");
                         }
                         r.setImpl(impl);
                     }
                 }
             }
-
-            // 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) {
-                            final ResourcesImpl impl = findOrCreateResourcesImplForKeyLocked(key);
-                            if (impl == null) {
-                                throw new Resources.NotFoundException("failed to load " + libAsset);
-                            }
-                            r.setImpl(impl);
-                        }
-                    }
-                }
-            }
         }
     }
 }
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index fd766bf..35c67d3 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -35,7 +35,7 @@
     }
 
     @Override
-    public void onPinnedActivityRestartAttempt() throws RemoteException {
+    public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) throws RemoteException {
     }
 
     @Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2701698..e26a256 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -7137,15 +7137,14 @@
     }
 
     /**
-     * @hide
-     * Enable backup service.
-     * <p>This includes all backup and restore mechanisms.
-     * Setting this to {@code false} will make backup service no-op or return empty results.
+     * Allows the device owner to enable or disable the backup service.
      *
-     * <p>There must be only one user on the device, managed by the device owner.
-     * Otherwise a {@link SecurityException} will be thrown.
+     * <p> Backup service manages all backup and restore mechanisms on the device. Setting this to
+     * false will prevent data from being backed up or restored.
      *
-     * <p>Backup service is off by default when device owner is present.
+     * <p> Backup service is off by default when device owner is present.
+     *
+     * @throws SecurityException if {@code admin} is not a device owner.
      */
     public void setBackupServiceEnabled(@NonNull ComponentName admin, boolean enabled) {
         try {
@@ -7156,8 +7155,12 @@
     }
 
     /**
-     * @hide
+     * Return whether the backup service is enabled by the device owner.
+     *
+     * <p> Backup service manages all backup and restore mechanisms on the device.
+     *
      * @return {@code true} if backup service is enabled, {@code false} otherwise.
+     * @see #setBackupServiceEnabled
      */
     public boolean isBackupServiceEnabled(@NonNull ComponentName admin) {
         try {
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 80bc136..540683d 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -136,6 +136,27 @@
      */
     public static final String EXTRA_BACKUP_SERVICES_AVAILABLE = "backup_services_available";
 
+    /**
+     * If this flag is passed to {@link #requestBackup(String[], BackupObserver, int)},
+     * BackupManager will pass a blank old state to BackupAgents of requested packages.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int FLAG_NON_INCREMENTAL_BACKUP = 1;
+
+    /**
+     * Use with {@link #requestBackup} to force backup of
+     * package meta data. Typically you do not need to explicitly request this be backed up as it is
+     * handled internally by the BackupManager. If you are requesting backups with
+     * FLAG_NON_INCREMENTAL, this package won't automatically be backed up and you have to
+     * explicitly request for its backup.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String PACKAGE_MANAGER_SENTINEL = "@pm@";
+
     private Context mContext;
     private static IBackupManager sService;
 
@@ -484,13 +505,34 @@
      */
     @SystemApi
     public int requestBackup(String[] packages, BackupObserver observer) {
+        return requestBackup(packages, observer, 0);
+    }
+
+    /**
+     * Request an immediate backup, providing an observer to which results of the backup operation
+     * will be published. The Android backup system will decide for each package whether it will
+     * be full app data backup or key/value-pair-based backup.
+     *
+     * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all
+     * provided packages using the remote transport.
+     *
+     * @param packages List of package names to backup.
+     * @param observer The {@link BackupObserver} to receive callbacks during the backup
+     *                 operation. Could be {@code null}.
+     * @param flags    {@link #FLAG_NON_INCREMENTAL_BACKUP}.
+     * @return {@link BackupManager#SUCCESS} on success; nonzero on error.
+     * @throws IllegalArgumentException on null or empty {@code packages} param.
+     * @hide
+     */
+    @SystemApi
+    public int requestBackup(String[] packages, BackupObserver observer, int flags) {
         checkServiceBinder();
         if (sService != null) {
             try {
                 BackupObserverWrapper observerWrapper = observer == null
                         ? null
                         : new BackupObserverWrapper(mContext, observer);
-                return sService.requestBackup(packages, observerWrapper);
+                return sService.requestBackup(packages, observerWrapper, flags);
             } catch (RemoteException e) {
                 Log.e(TAG, "requestBackup() couldn't connect");
             }
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index a320bbf..fe23c28 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -357,7 +357,9 @@
      * @param observer The {@link BackupObserver} to receive callbacks during the backup
      * operation.
      *
+     * @param flags {@link BackupManager#FLAG_NON_INCREMENTAL_BACKUP}.
+     *
      * @return Zero on success; nonzero on error.
      */
-    int requestBackup(in String[] packages, IBackupObserver observer);
+    int requestBackup(in String[] packages, IBackupObserver observer, int flags);
 }
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index cd14469..6ba52b7 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -36,7 +36,6 @@
 import android.os.ServiceManager;
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
-import android.util.TypedValue;
 import android.widget.RemoteViews;
 import android.widget.RemoteViews.OnClickHandler;
 
@@ -381,15 +380,7 @@
         // Convert complex to dp -- we are getting the AppWidgetProviderInfo from the
         // AppWidgetService, which doesn't have our context, hence we need to do the
         // conversion here.
-        appWidget.minWidth =
-            TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);
-        appWidget.minHeight =
-            TypedValue.complexToDimensionPixelSize(appWidget.minHeight, mDisplayMetrics);
-        appWidget.minResizeWidth =
-            TypedValue.complexToDimensionPixelSize(appWidget.minResizeWidth, mDisplayMetrics);
-        appWidget.minResizeHeight =
-            TypedValue.complexToDimensionPixelSize(appWidget.minResizeHeight, mDisplayMetrics);
-
+        appWidget.updateDimensions(mDisplayMetrics);
         synchronized (mViews) {
             v = mViews.get(appWidgetId);
         }
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 31e779f..9980e966 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -31,7 +31,6 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.DisplayMetrics;
-import android.util.TypedValue;
 import android.widget.RemoteViews;
 
 import com.android.internal.appwidget.IAppWidgetService;
@@ -760,7 +759,7 @@
             }
             for (AppWidgetProviderInfo info : providers.getList()) {
                 // Converting complex to dp.
-                convertSizesToPixels(info);
+                info.updateDimensions(mDisplayMetrics);
             }
             return providers.getList();
         } catch (RemoteException e) {
@@ -782,7 +781,7 @@
             AppWidgetProviderInfo info = mService.getAppWidgetInfo(mPackageName, appWidgetId);
             if (info != null) {
                 // Converting complex to dp.
-                convertSizesToPixels(info);
+                info.updateDimensions(mDisplayMetrics);
             }
             return info;
         } catch (RemoteException e) {
@@ -1072,18 +1071,6 @@
         }
     }
 
-    private void convertSizesToPixels(AppWidgetProviderInfo info) {
-        // Converting complex to dp.
-        info.minWidth = TypedValue.complexToDimensionPixelSize(info.minWidth,
-                mDisplayMetrics);
-        info.minHeight = TypedValue.complexToDimensionPixelSize(info.minHeight,
-                mDisplayMetrics);
-        info.minResizeWidth = TypedValue.complexToDimensionPixelSize(info.minResizeWidth,
-                mDisplayMetrics);
-        info.minResizeHeight = TypedValue.complexToDimensionPixelSize(info.minResizeHeight,
-                mDisplayMetrics);
-    }
-
     /**
      * Request to pin an app widget on the current launcher. It's up to the launcher to accept this
      * request (optionally showing a user confirmation). If the request is accepted, the caller will
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index b4d79b4..06fdb32 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -26,6 +26,8 @@
 import android.os.Parcelable;
 import android.content.ComponentName;
 import android.os.UserHandle;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
 
 /**
  * Describes the meta data for an installed AppWidget provider.  The fields in this class
@@ -379,6 +381,17 @@
     }
 
     /**
+     * @hide
+     */
+    public void updateDimensions(DisplayMetrics displayMetrics) {
+        // Converting complex to dp.
+        minWidth = TypedValue.complexToDimensionPixelSize(minWidth, displayMetrics);
+        minHeight = TypedValue.complexToDimensionPixelSize(minHeight, displayMetrics);
+        minResizeWidth = TypedValue.complexToDimensionPixelSize(minResizeWidth, displayMetrics);
+        minResizeHeight = TypedValue.complexToDimensionPixelSize(minResizeHeight, displayMetrics);
+    }
+
+    /**
      * Parcelable.Creator that instantiates AppWidgetProviderInfo objects
      */
     public static final Parcelable.Creator<AppWidgetProviderInfo> CREATOR
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index af5e643..596a9fd 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -35,6 +35,7 @@
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
 import android.app.LoadedApk;
+import android.app.Notification;
 import android.app.admin.DevicePolicyManager;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -2508,7 +2509,10 @@
      * {@link ComponentName} of the actual service that was started is
      * returned; else if the service does not exist null is returned.
      *
-     * @throws SecurityException &nbsp;
+     * @throws SecurityException If the caller does not permission to access the service
+     * or the service can not be found.
+     * @throws IllegalStateException If the application is in a state where the service
+     * can not be started (such as not in the foreground in a state when services are allowed).
      *
      * @see #stopService
      * @see #bindService
@@ -2517,6 +2521,17 @@
     public abstract ComponentName startService(Intent service);
 
     /**
+     * Start a service directly into the "foreground service" state.  Unlike {@link #startService},
+     * this method can be used from within background operations like broadcast receivers
+     * or scheduled jobs.  The API entry point for this is in NotificationManager in order to
+     * preserve appropriate public package layering.
+     * @hide
+     */
+    @Nullable
+    public abstract ComponentName startServiceInForeground(Intent service,
+            int id, Notification notification);
+
+    /**
      * Request that a given application service be stopped.  If the service is
      * not running, nothing happens.  Otherwise it is stopped.  Note that calls
      * to startService() are not counted -- this stops the service no matter
@@ -2538,7 +2553,10 @@
      * @return If there is a service matching the given Intent that is already
      * running, then it is stopped and {@code true} is returned; else {@code false} is returned.
      *
-     * @throws SecurityException &nbsp;
+     * @throws SecurityException If the caller does not permission to access the service
+     * or the service can not be found.
+     * @throws IllegalStateException If the application is in a state where the service
+     * can not be started (such as not in the foreground in a state when services are allowed).
      *
      * @see #startService
      */
@@ -2547,9 +2565,18 @@
     /**
      * @hide like {@link #startService(Intent)} but for a specific user.
      */
+    @Nullable
     public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
 
     /**
+     * @hide like {@link #startServiceInForeground(Intent, int, Notification)}
+     * but for a specific user.
+     */
+    @Nullable
+    public abstract ComponentName startServiceInForegroundAsUser(Intent service,
+            int id, Notification notification, UserHandle user);
+
+    /**
      * @hide like {@link #stopService(Intent)} but for a specific user.
      */
     public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
@@ -2591,7 +2618,8 @@
      *         {@code false} is returned if the connection is not made so you will not
      *         receive the service object.
      *
-     * @throws SecurityException &nbsp;
+     * @throws SecurityException If the caller does not permission to access the service
+     * or the service can not be found.
      *
      * @see #unbindService
      * @see #startService
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index e437de0..b131ecc 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -20,6 +20,7 @@
 import android.annotation.SystemApi;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
+import android.app.Notification;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.AssetManager;
@@ -623,6 +624,13 @@
         return mBase.startService(service);
     }
 
+    /** @hide */
+    @Override
+    public ComponentName startServiceInForeground(Intent service,
+            int id, Notification notification) {
+        return mBase.startServiceInForeground(service, id, notification);
+    }
+
     @Override
     public boolean stopService(Intent name) {
         return mBase.stopService(name);
@@ -636,6 +644,13 @@
 
     /** @hide */
     @Override
+    public ComponentName startServiceInForegroundAsUser(Intent service,
+            int id, Notification notification, UserHandle user) {
+        return mBase.startServiceInForegroundAsUser(service, id, notification, user);
+    }
+
+    /** @hide */
+    @Override
     public boolean stopServiceAsUser(Intent name, UserHandle user) {
         return mBase.stopServiceAsUser(name, user);
     }
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 44dff00..4bd091d 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -566,6 +566,7 @@
                     CONFIG_SMALLEST_SCREEN_SIZE,
                     CONFIG_DENSITY,
                     CONFIG_LAYOUT_DIRECTION,
+                    CONFIG_COLORIMETRY,
                     CONFIG_FONT_SCALE,
             })
     @Retention(RetentionPolicy.SOURCE)
@@ -671,6 +672,20 @@
     public static final int CONFIG_LAYOUT_DIRECTION = 0x2000;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle the change to the display color gamut or dynamic
+     * range. Set from the {@link android.R.attr#configChanges} attribute.
+     */
+    public static final int CONFIG_COLORIMETRY = 0x4000;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle asset path changes.  Set from the {@link android.R.attr#configChanges}
+     * attribute. This is not a core resource configuration, but a higher-level value, so its
+     * constant starts at the high bits.
+     * @hide We do not want apps handling this yet, but we do need some kind of bit for diffs.
+     */
+    public static final int CONFIG_ASSETS_PATHS = 0x80000000;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
      * can itself handle changes to the font scaling factor.  Set from the
      * {@link android.R.attr#configChanges} attribute.  This is
      * not a core resource configuration, but a higher-level value, so its
@@ -698,6 +713,7 @@
         Configuration.NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,   // SMALLEST SCREEN SIZE
         Configuration.NATIVE_CONFIG_DENSITY,                // DENSITY
         Configuration.NATIVE_CONFIG_LAYOUTDIR,              // LAYOUT DIRECTION
+        Configuration.NATIVE_CONFIG_COLORIMETRY,            // COLORIMETRY
     };
 
     /**
@@ -753,7 +769,8 @@
      * {@link #CONFIG_LOCALE}, {@link #CONFIG_TOUCHSCREEN},
      * {@link #CONFIG_KEYBOARD}, {@link #CONFIG_NAVIGATION},
      * {@link #CONFIG_ORIENTATION}, {@link #CONFIG_SCREEN_LAYOUT},
-     * {@link #CONFIG_DENSITY}, and {@link #CONFIG_LAYOUT_DIRECTION}.
+     * {@link #CONFIG_DENSITY}, {@link #CONFIG_LAYOUT_DIRECTION} and
+     * {@link #CONFIG_COLORIMETRY}.
      * Set from the {@link android.R.attr#configChanges} attribute.
      */
     public int configChanges;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 19cca8e..01f4e00 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -138,6 +138,8 @@
 
     ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
 
+    ResolveInfo findPersistentPreferredActivity(in Intent intent, int userId);
+
     boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId);
 
     ParceledListSlice queryIntentActivities(in Intent intent,
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index ba54f44..c6a8674 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -1206,6 +1206,13 @@
      * Represents a "pin shortcut" request made by an app, which is sent with
      * an {@link #ACTION_CONFIRM_PIN_ITEM} intent to the default launcher app.
      *
+     * <p>Note the launcher may receive a request to pin a shortcut that is already pinned, because
+     * the user may actually want to have multiple icons of the same shortcut on the launcher.
+     * The launcher can tell this case by calling {@link ShortcutInfo#isPinned()} on the shortcut
+     * returned by {@link #getShortcutInfo()}.  In this case, calling {@link #accept()} is optional;
+     * even if the launcher does not call it, the shortcut is already pinned.  Also in this case,
+     * the {@code options} argument to {@link #accept(Bundle)} will be ignored.
+     *
      * @see #EXTRA_PIN_ITEM_REQUEST
      * @see #getPinItemRequest(Intent)
      */
@@ -1270,8 +1277,13 @@
          * {@link #REQUEST_TYPE_APPWIDGET} request.
          */
         @Nullable
-        public AppWidgetProviderInfo getAppWidgetProviderInfo() {
-            return mAppWidgetInfo;
+        public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
+            if (mAppWidgetInfo != null) {
+                AppWidgetProviderInfo info = mAppWidgetInfo.clone();
+                info.updateDimensions(context.getResources().getDisplayMetrics());
+                return info;
+            }
+            return null;
         }
 
         /**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 04e649c..507608a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1360,6 +1360,14 @@
     public static final int MOVE_FAILED_DEVICE_ADMIN = -8;
 
     /**
+     * Error code that is passed to the {@link IPackageMoveObserver} if system does not allow
+     * non-system apps to be moved to internal storage.
+     *
+     * @hide
+     */
+    public static final int MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL = -9;
+
+    /**
      * Flag parameter for {@link #movePackage} to indicate that
      * the package should be moved to internal storage if its
      * been installed on external media.
@@ -1854,6 +1862,20 @@
     public static final String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+     * The device supports telephony carrier restriction mechanism.
+     *
+     * <p>Devices declaring this feature must have an implementation of the
+     * {@link android.telephony.TelephonyManager#getAllowedCarriers} and
+     * {@link android.telephony.TelephonyManager#setAllowedCarriers}.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_TELEPHONY_CARRIERLOCK =
+            "android.hardware.telephony.carrierlock";
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports connecting to USB devices
      * as the USB host.
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 2590a6b..a1747c7 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -138,9 +138,8 @@
      * @param userId The user under which to check.
      *
      * @return An {@link ApplicationInfo} containing information about the
-     *         package.
-     * @throws NameNotFoundException if a package with the given name cannot be
-     *             found on the system.
+     *         package, or {@code null} if no application exists with that
+     *         package name.
      */
     public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
 
@@ -223,6 +222,27 @@
             int userId);
 
     /**
+     * Grants access to the package metadata for an ephemeral application.
+     * <p>
+     * When an ephemeral application explicitly tries to interact with a full
+     * install application [via an activity, service or provider that has been
+     * exposed using the {@code visibleToInstantApp} attribute], the normal
+     * application must be able to see metadata about the connecting ephemeral
+     * app. If the ephemeral application uses an implicit intent [ie action VIEW,
+     * category BROWSABLE], it remains hidden from the launched activity.
+     * <p>
+     * If the {@code sourceUid} is not for an ephemeral app or {@code targetUid}
+     * is not for a fully installed app, this method will be a no-op.
+     *
+     * @param userId the user
+     * @param intent the intent that triggered the grant
+     * @param targetAppId The app ID of the fully installed application
+     * @param ephemeralAppId The app ID of the ephemeral application
+     */
+    public abstract void grantEphemeralAccess(int userId, Intent intent,
+            int targetAppId, int ephemeralAppId);
+
+    /**
      * @return The SetupWizard package name.
      */
     public abstract String getSetupWizardPackageName();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 083e4cc6..2fdc527 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -179,6 +179,13 @@
     private static final String TAG_PACKAGE = "package";
     private static final String TAG_RESTRICT_UPDATE = "restrict-update";
 
+    /**
+     * Bit mask of all the valid bits that can be set in restartOnConfigChanges.
+     * @hide
+     */
+    private static final int RESTART_ON_CONFIG_CHANGES_MASK =
+            ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC;
+
     // These are the tags supported by child packages
     private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>();
     static {
@@ -3855,7 +3862,9 @@
             a.info.maxRecents = sa.getInt(
                     R.styleable.AndroidManifestActivity_maxRecents,
                     ActivityManager.getDefaultAppRecentsLimitStatic());
-            a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
+            a.info.configChanges = getActivityConfigChanges(
+                    sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
+                    sa.getInt(R.styleable.AndroidManifestActivity_restartOnConfigChanges, 0));
             a.info.softInputMode = sa.getInt(
                     R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
 
@@ -4083,6 +4092,17 @@
         }
     }
 
+    /**
+     * @param configChanges The bit mask of configChanges fetched from AndroidManifest.xml.
+     * @param restartOnConfigChanges The bit mask restartOnConfigChanges fetched from
+     *                               AndroidManifest.xml.
+     * @hide Exposed for unit testing only.
+     */
+    @TestApi
+    public static int getActivityConfigChanges(int configChanges, int restartOnConfigChanges) {
+        return configChanges | ((~restartOnConfigChanges) & RESTART_ON_CONFIG_CHANGES_MASK);
+    }
+
     private void parseLayout(Resources res, AttributeSet attrs, Activity a) {
         TypedArray sw = res.obtainAttributes(attrs,
                 com.android.internal.R.styleable.AndroidManifestLayout);
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 48860f7..a81329d 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -101,6 +101,68 @@
      */
     public boolean userSetLocale;
 
+
+    /** Constant for {@link #colorimetry}: bits that encode whether the screen is wide gamut. */
+    public static final int COLORIMETRY_WIDE_COLOR_GAMUT_MASK = 0x3;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value
+     * indicating that it is unknown whether or not the screen is wide gamut.
+     */
+    public static final int COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED = 0x0;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value
+     * indicating that the screen is not wide gamut.
+     * <p>Corresponds to the <code>-nowidecg</code> resource qualifier.</p>
+     */
+    public static final int COLORIMETRY_WIDE_COLOR_GAMUT_NO = 0x1;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} value
+     * indicating that the screen is wide gamut.
+     * <p>Corresponds to the <code>-widecg</code> resource qualifier.</p>
+     */
+    public static final int COLORIMETRY_WIDE_COLOR_GAMUT_YES = 0x2;
+
+    /** Constant for {@link #colorimetry}: bits that encode whether the dynamic range of the screen. */
+    public static final int COLORIMETRY_HDR_MASK = 0xc;
+    /** Constant for {@link #colorimetry}: bits shift to get the screen dynamic range. */
+    public static final int COLORIMETRY_HDR_SHIFT = 2;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value
+     * indicating that it is unknown whether or not the screen is HDR.
+     */
+    public static final int COLORIMETRY_HDR_UNDEFINED = 0x0;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value
+     * indicating that the screen is not HDR (low/standard dynamic range).
+     * <p>Corresponds to the <code>-lowdr</code> resource qualifier.</p>
+     */
+    public static final int COLORIMETRY_HDR_NO = 0x1 << COLORIMETRY_HDR_SHIFT;
+    /**
+     * Constant for {@link #colorimetry}: a {@link #COLORIMETRY_HDR_MASK} value
+     * indicating that the screen is HDR (dynamic range).
+     * <p>Corresponds to the <code>-highdr</code> resource qualifier.</p>
+     */
+    public static final int COLORIMETRY_HDR_YES = 0x2 << COLORIMETRY_HDR_SHIFT;
+
+    /** Constant for {@link #colorimetry}: a value indicating that colorimetry is undefined */
+    @SuppressWarnings("PointlessBitwiseExpression")
+    public static final int COLORIMETRY_UNDEFINED = COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED |
+            COLORIMETRY_HDR_UNDEFINED;
+
+    /**
+     * Bit mask of for color capabilities of the screen. Currently there are two fields:
+     * <p>The {@link #COLORIMETRY_WIDE_COLOR_GAMUT_MASK} bits define the color gamut of
+     * the screen. They may be one of
+     * {@link #COLORIMETRY_WIDE_COLOR_GAMUT_NO} or {@link #COLORIMETRY_WIDE_COLOR_GAMUT_YES}.</p>
+     *
+     * <p>The {@link #COLORIMETRY_HDR_MASK} defines the dynamic range of the screen. They may be
+     * one of {@link #COLORIMETRY_HDR_NO} or {@link #COLORIMETRY_HDR_YES}.</p>
+     *
+     * <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
+     * Multiple Screens</a> for more information.</p>
+     */
+    public int colorimetry;
+
     /** Constant for {@link #screenLayout}: bits that encode the size. */
     public static final int SCREENLAYOUT_SIZE_MASK = 0x0f;
     /** Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_SIZE_MASK}
@@ -331,6 +393,9 @@
         if ((diff & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
             list.add("CONFIG_SCREEN_LAYOUT");
         }
+        if ((diff & ActivityInfo.CONFIG_COLORIMETRY) != 0) {
+            list.add("CONFIG_COLORIMETRY");
+        }
         if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0) {
             list.add("CONFIG_UI_MODE");
         }
@@ -346,6 +411,9 @@
         if ((diff & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
             list.add("CONFIG_FONT_SCALE");
         }
+        if ((diff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
+            list.add("CONFIG_ASSETS_PATHS");
+        }
         StringBuilder builder = new StringBuilder("{");
         for (int i = 0, n = list.size(); i < n; i++) {
             builder.append(list.get(i));
@@ -671,6 +739,21 @@
     public int compatSmallestScreenWidthDp;
 
     /**
+     * An undefined assetsSeq. This will not override an existing assetsSeq.
+     * @hide
+     */
+    public static final int ASSETS_SEQ_UNDEFINED = 0;
+
+    /**
+     * Internal counter that allows us to piggyback off the configuration change mechanism to
+     * signal to apps that the the assets for an Application have changed. A difference in these
+     * between two Configurations will yield a diff flag of
+     * {@link ActivityInfo#CONFIG_ASSETS_PATHS}.
+     * @hide
+     */
+    public int assetsSeq;
+
+    /**
      * @hide Internal book-keeping.
      */
     public int seq;
@@ -693,6 +776,7 @@
                     NATIVE_CONFIG_UI_MODE,
                     NATIVE_CONFIG_SMALLEST_SCREEN_SIZE,
                     NATIVE_CONFIG_LAYOUTDIR,
+                    NATIVE_CONFIG_COLORIMETRY,
             })
     @Retention(RetentionPolicy.SOURCE)
     public @interface NativeConfig {}
@@ -729,6 +813,8 @@
     public static final int NATIVE_CONFIG_SMALLEST_SCREEN_SIZE = 0x2000;
     /** @hide Native-specific bit mask for LAYOUTDIR config ; DO NOT USE UNLESS YOU ARE SURE.*/
     public static final int NATIVE_CONFIG_LAYOUTDIR = 0x4000;
+    /** @hide Native-specific bit mask for COLORIMETRY config ; DO NOT USE UNLESS YOU ARE SURE.*/
+    public static final int NATIVE_CONFIG_COLORIMETRY = 0x10000;
 
     /**
      * <p>Construct an invalid Configuration. This state is only suitable for constructing a
@@ -787,6 +873,7 @@
         navigationHidden = o.navigationHidden;
         orientation = o.orientation;
         screenLayout = o.screenLayout;
+        colorimetry = o.colorimetry;
         uiMode = o.uiMode;
         screenWidthDp = o.screenWidthDp;
         screenHeightDp = o.screenHeightDp;
@@ -795,6 +882,7 @@
         compatScreenWidthDp = o.compatScreenWidthDp;
         compatScreenHeightDp = o.compatScreenHeightDp;
         compatSmallestScreenWidthDp = o.compatSmallestScreenWidthDp;
+        assetsSeq = o.assetsSeq;
         seq = o.seq;
     }
 
@@ -866,6 +954,20 @@
             default: sb.append(" layoutLong=");
                     sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
         }
+        switch ((colorimetry&COLORIMETRY_HDR_MASK)) {
+            case COLORIMETRY_HDR_UNDEFINED: sb.append(" ?ldr"); break; // most likely not HDR
+            case COLORIMETRY_HDR_NO: /* ldr is not interesting to print */ break;
+            case COLORIMETRY_HDR_YES: sb.append(" hdr"); break;
+            default: sb.append(" dynamicRange=");
+                sb.append(colorimetry&COLORIMETRY_HDR_MASK); break;
+        }
+        switch ((colorimetry&COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) {
+            case COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED: sb.append(" ?wideColorGamut"); break;
+            case COLORIMETRY_WIDE_COLOR_GAMUT_NO: /* not wide is not interesting to print */ break;
+            case COLORIMETRY_WIDE_COLOR_GAMUT_YES: sb.append(" widecg"); break;
+            default: sb.append(" wideColorGamut=");
+                sb.append(colorimetry&COLORIMETRY_WIDE_COLOR_GAMUT_MASK); break;
+        }
         switch (orientation) {
             case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
             case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
@@ -930,9 +1032,11 @@
             case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
             default: sb.append("/"); sb.append(navigationHidden); break;
         }
+        if (assetsSeq != 0) {
+            sb.append(" as.").append(assetsSeq);
+        }
         if (seq != 0) {
-            sb.append(" s.");
-            sb.append(seq);
+            sb.append(" s.").append(seq);
         }
         sb.append('}');
         return sb.toString();
@@ -955,11 +1059,13 @@
         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
         screenLayout = SCREENLAYOUT_UNDEFINED;
+        colorimetry = COLORIMETRY_UNDEFINED;
         uiMode = UI_MODE_TYPE_UNDEFINED;
         screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
         screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
         smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
         densityDpi = DENSITY_DPI_UNDEFINED;
+        assetsSeq = ASSETS_SEQ_UNDEFINED;
         seq = 0;
     }
 
@@ -1089,6 +1195,23 @@
                 | (delta.screenLayout & SCREENLAYOUT_COMPAT_NEEDED);
         }
 
+        if (((delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) !=
+                     COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED)
+                && (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)
+                != (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) {
+            changed |= ActivityInfo.CONFIG_COLORIMETRY;
+            colorimetry = (colorimetry & ~COLORIMETRY_WIDE_COLOR_GAMUT_MASK)
+                    | (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK);
+        }
+
+        if (((delta.colorimetry & COLORIMETRY_HDR_MASK) != COLORIMETRY_HDR_UNDEFINED)
+                && (delta.colorimetry & COLORIMETRY_HDR_MASK)
+                != (colorimetry & COLORIMETRY_HDR_MASK)) {
+            changed |= ActivityInfo.CONFIG_COLORIMETRY;
+            colorimetry = (colorimetry & ~COLORIMETRY_HDR_MASK)
+                    | (delta.colorimetry & COLORIMETRY_HDR_MASK);
+        }
+
         if (delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED)
                 && uiMode != delta.uiMode) {
             changed |= ActivityInfo.CONFIG_UI_MODE;
@@ -1130,6 +1253,10 @@
         if (delta.compatSmallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
             compatSmallestScreenWidthDp = delta.compatSmallestScreenWidthDp;
         }
+        if (delta.assetsSeq != ASSETS_SEQ_UNDEFINED) {
+            changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
+            assetsSeq = delta.assetsSeq;
+        }
         if (delta.seq != 0) {
             seq = delta.seq;
         }
@@ -1234,6 +1361,19 @@
                 getScreenLayoutNoDirection(delta.screenLayout)) {
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
         }
+        if ((compareUndefined ||
+                     (delta.colorimetry & COLORIMETRY_HDR_MASK) != COLORIMETRY_HDR_UNDEFINED)
+                && (colorimetry & COLORIMETRY_HDR_MASK) !=
+                        (delta.colorimetry & COLORIMETRY_HDR_MASK)) {
+            changed |= ActivityInfo.CONFIG_COLORIMETRY;
+        }
+        if ((compareUndefined ||
+                     (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) !=
+                             COLORIMETRY_WIDE_COLOR_GAMUT_UNDEFINED)
+                && (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) !=
+                        (delta.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) {
+            changed |= ActivityInfo.CONFIG_COLORIMETRY;
+        }
         if ((compareUndefined || delta.uiMode != (UI_MODE_TYPE_UNDEFINED|UI_MODE_NIGHT_UNDEFINED))
                 && uiMode != delta.uiMode) {
             changed |= ActivityInfo.CONFIG_UI_MODE;
@@ -1254,6 +1394,10 @@
                 && densityDpi != delta.densityDpi) {
             changed |= ActivityInfo.CONFIG_DENSITY;
         }
+        if ((compareUndefined || delta.assetsSeq != ASSETS_SEQ_UNDEFINED)
+                && assetsSeq != delta.assetsSeq) {
+            changed |= ActivityInfo.CONFIG_ASSETS_PATHS;
+        }
 
         return changed;
     }
@@ -1272,7 +1416,11 @@
      */
     public static boolean needNewResources(@Config int configChanges,
             @Config int interestingChanges) {
-        return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
+        // CONFIG_ASSETS_PATHS and CONFIG_FONT_SCALE are higher level configuration changes that
+        // all resources are subject to change with.
+        interestingChanges = interestingChanges | ActivityInfo.CONFIG_ASSETS_PATHS
+                | ActivityInfo.CONFIG_FONT_SCALE;
+        return (configChanges & interestingChanges) != 0;
     }
 
     /**
@@ -1337,6 +1485,7 @@
         dest.writeInt(navigationHidden);
         dest.writeInt(orientation);
         dest.writeInt(screenLayout);
+        dest.writeInt(colorimetry);
         dest.writeInt(uiMode);
         dest.writeInt(screenWidthDp);
         dest.writeInt(screenHeightDp);
@@ -1345,6 +1494,7 @@
         dest.writeInt(compatScreenWidthDp);
         dest.writeInt(compatScreenHeightDp);
         dest.writeInt(compatSmallestScreenWidthDp);
+        dest.writeInt(assetsSeq);
         dest.writeInt(seq);
     }
 
@@ -1370,6 +1520,7 @@
         navigationHidden = source.readInt();
         orientation = source.readInt();
         screenLayout = source.readInt();
+        colorimetry = source.readInt();
         uiMode = source.readInt();
         screenWidthDp = source.readInt();
         screenHeightDp = source.readInt();
@@ -1378,6 +1529,7 @@
         compatScreenWidthDp = source.readInt();
         compatScreenHeightDp = source.readInt();
         compatSmallestScreenWidthDp = source.readInt();
+        assetsSeq = source.readInt();
         seq = source.readInt();
     }
 
@@ -1450,6 +1602,8 @@
         if (n != 0) return n;
         n = this.orientation - that.orientation;
         if (n != 0) return n;
+        n = this.colorimetry - that.colorimetry;
+        if (n != 0) return n;
         n = this.screenLayout - that.screenLayout;
         if (n != 0) return n;
         n = this.uiMode - that.uiMode;
@@ -1461,6 +1615,8 @@
         n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
         if (n != 0) return n;
         n = this.densityDpi - that.densityDpi;
+        if (n != 0) return n;
+        n = this.assetsSeq - that.assetsSeq;
         //if (n != 0) return n;
         return n;
     }
@@ -1493,11 +1649,13 @@
         result = 31 * result + navigationHidden;
         result = 31 * result + orientation;
         result = 31 * result + screenLayout;
+        result = 31 * result + colorimetry;
         result = 31 * result + uiMode;
         result = 31 * result + screenWidthDp;
         result = 31 * result + screenHeightDp;
         result = 31 * result + smallestScreenWidthDp;
         result = 31 * result + densityDpi;
+        result = 31 * result + assetsSeq;
         return result;
     }
 
@@ -1600,6 +1758,24 @@
     }
 
     /**
+     * Return whether the screen has a wide color gamut.
+     *
+     * @return true if the screen has a wide color gamut, false otherwise
+     */
+    public boolean isScreenWideColorGamut() {
+        return (colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) == COLORIMETRY_WIDE_COLOR_GAMUT_YES;
+    }
+
+    /**
+     * Return whether the screen has a high dynamic range.
+     *
+     * @return true if the screen has a high dynamic range, false otherwise
+     */
+    public boolean isScreenHdr() {
+        return (colorimetry & COLORIMETRY_HDR_MASK) == COLORIMETRY_HDR_YES;
+    }
+
+    /**
      *
      * @hide
      */
@@ -1731,6 +1907,28 @@
                 break;
         }
 
+        switch (config.colorimetry & Configuration.COLORIMETRY_HDR_MASK) {
+            case Configuration.COLORIMETRY_HDR_YES:
+                parts.add("highdr");
+                break;
+            case Configuration.COLORIMETRY_HDR_NO:
+                parts.add("lowdr");
+                break;
+            default:
+                break;
+        }
+
+        switch (config.colorimetry & Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_MASK) {
+            case Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_YES:
+                parts.add("widecg");
+                break;
+            case Configuration.COLORIMETRY_WIDE_COLOR_GAMUT_NO:
+                parts.add("nowidecg");
+                break;
+            default:
+                break;
+        }
+
         switch (config.orientation) {
             case Configuration.ORIENTATION_LANDSCAPE:
                 parts.add("land");
@@ -1956,6 +2154,16 @@
             delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK;
         }
 
+        if ((base.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK) !=
+                (change.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK)) {
+            delta.colorimetry |= change.colorimetry & COLORIMETRY_WIDE_COLOR_GAMUT_MASK;
+        }
+
+        if ((base.colorimetry & COLORIMETRY_HDR_MASK) !=
+                (change.colorimetry & COLORIMETRY_HDR_MASK)) {
+            delta.colorimetry |= change.colorimetry & COLORIMETRY_HDR_MASK;
+        }
+
         if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
             delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
         }
@@ -1979,6 +2187,10 @@
         if (base.densityDpi != change.densityDpi) {
             delta.densityDpi = change.densityDpi;
         }
+
+        if (base.assetsSeq != change.assetsSeq) {
+            delta.assetsSeq = change.assetsSeq;
+        }
         return delta;
     }
 
@@ -1994,6 +2206,7 @@
     private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
     private static final String XML_ATTR_ORIENTATION = "ori";
     private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
+    private static final String XML_ATTR_COLORIMETRY = "clrMtry";
     private static final String XML_ATTR_UI_MODE = "ui";
     private static final String XML_ATTR_SCREEN_WIDTH = "width";
     private static final String XML_ATTR_SCREEN_HEIGHT = "height";
@@ -2036,6 +2249,8 @@
                 ORIENTATION_UNDEFINED);
         configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
                 SCREENLAYOUT_UNDEFINED);
+        configOut.colorimetry = XmlUtils.readIntAttribute(parser, XML_ATTR_COLORIMETRY,
+                COLORIMETRY_UNDEFINED);
         configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
         configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
                 SCREEN_WIDTH_DP_UNDEFINED);
@@ -2046,6 +2261,8 @@
                         SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
         configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
                 DENSITY_DPI_UNDEFINED);
+
+        // For persistence, we don't care about assetsSeq, so do not read it out.
     }
 
 
@@ -2096,6 +2313,9 @@
         if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
             XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
         }
+        if (config.colorimetry != COLORIMETRY_UNDEFINED) {
+            XmlUtils.writeIntAttribute(xml, XML_ATTR_COLORIMETRY, config.colorimetry);
+        }
         if (config.uiMode != 0) {
             XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
         }
@@ -2111,5 +2331,7 @@
         if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
             XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
         }
+
+        // For persistence, we do not care about assetsSeq, so do not write it out.
     }
 }
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
index ffbc401..1a128e0 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.annotation.SystemApi;
+import android.net.wifi.ScanResult;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -52,6 +53,18 @@
     public final WifiKey wifiKey;
 
     /**
+     * Constructs a new NetworkKey for the given wifi {@link ScanResult}.
+     *
+     * @throws IllegalArgumentException if the given ScanResult is malformed
+     * @hide
+     */
+    public static NetworkKey createFromScanResult(ScanResult result) {
+        return new NetworkKey(
+                new WifiKey(
+                        '"' + result.wifiSsid.toString() + '"', result.BSSID));
+    }
+
+    /**
      * Construct a new {@link NetworkKey} for a Wi-Fi network.
      * @param wifiKey the {@link WifiKey} identifying this Wi-Fi network.
      */
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index 23d5af5..9e4dd87 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -226,16 +226,6 @@
         return false;
     }
 
-    /** Determine whether the application with the given UID is the enabled scorer. */
-    @Deprecated // Use NetworkScoreManager.isCallerActiveScorer()
-    public boolean isCallerActiveScorer(int callingUid) {
-        NetworkScorerAppData defaultApp = getActiveScorer();
-        if (defaultApp == null) {
-            return false;
-        }
-        return callingUid == defaultApp.packageUid;
-    }
-
     private boolean isNetworkRecommendationsDisabled() {
         final ContentResolver cr = mContext.getContentResolver();
         // A value of 1 indicates enabled.
diff --git a/core/java/android/net/RecommendationRequest.java b/core/java/android/net/RecommendationRequest.java
index a227f18..b89a245 100644
--- a/core/java/android/net/RecommendationRequest.java
+++ b/core/java/android/net/RecommendationRequest.java
@@ -37,6 +37,8 @@
     private final WifiConfiguration mDefaultConfig;
     private WifiConfiguration mConnectedConfig;
     private WifiConfiguration[] mConnectableConfigs;
+    private final int mLastSelectedNetworkId;
+    private final long mLastSelectedNetworkTimestamp;
 
     /**
      * Builder class for constructing {@link RecommendationRequest} instances.
@@ -48,17 +50,9 @@
         private WifiConfiguration mDefaultConfig;
         private WifiConfiguration mConnectedConfig;
         private WifiConfiguration[] mConnectableConfigs;
+        private int mLastSelectedNetworkId;
+        private long mLastSelectedTimestamp;
 
-        /**
-         * @param scanResults the array of {@link ScanResult}s the recommendation must be
-         *                    constrained to i.e. if a non-null wifi config recommendation is
-         *                    returned then it must be able to connect to one of the networks in
-         *                    the results list.
-         *
-         *                    If the array is {@code null} or empty then there is no constraint.
-         *
-         * @return this
-         */
         public Builder setScanResults(ScanResult[] scanResults) {
             mScanResults = scanResults;
             return this;
@@ -89,7 +83,20 @@
          * @return this
          */
         public Builder setConnectableConfigs(WifiConfiguration[] connectableConfigs) {
-            mConnectableConfigs = connectableConfigs;
+            this.mConnectableConfigs = connectableConfigs;
+            return this;
+        }
+
+        /**
+         * @param networkId The {@link WifiConfiguration#networkId} of the last user selected
+         *                  network.
+         * @param timestamp The {@link android.os.SystemClock#elapsedRealtime()} when the user
+         *                  selected {@code networkId}.
+         * @return this
+         */
+        public Builder setLastSelectedNetwork(int networkId, long timestamp) {
+            this.mLastSelectedNetworkId = networkId;
+            this.mLastSelectedTimestamp = timestamp;
             return this;
         }
 
@@ -97,10 +104,8 @@
          * @return a new {@link RecommendationRequest} instance
          */
         public RecommendationRequest build() {
-            return new RecommendationRequest(mScanResults,
-                    mDefaultConfig,
-                    mConnectedConfig,
-                    mConnectableConfigs);
+            return new RecommendationRequest(mScanResults, mDefaultConfig, mConnectedConfig,
+                    mConnectableConfigs, mLastSelectedNetworkId, mLastSelectedTimestamp);
         }
     }
 
@@ -154,15 +159,35 @@
         mConnectableConfigs = connectableConfigs;
     }
 
+    /**
+     * @return The {@link WifiConfiguration#networkId} of the last user selected network.
+     *         {@code 0} if not set.
+     */
+    public int getLastSelectedNetworkId() {
+        return mLastSelectedNetworkId;
+    }
+
+    /**
+     * @return The {@link android.os.SystemClock#elapsedRealtime()} when the user selected
+     *         {@link #getLastSelectedNetworkId()}. {@code 0} if not set.
+     */
+    public long getLastSelectedNetworkTimestamp() {
+        return mLastSelectedNetworkTimestamp;
+    }
+
     @VisibleForTesting
     RecommendationRequest(ScanResult[] scanResults,
             WifiConfiguration defaultWifiConfig,
             WifiConfiguration connectedWifiConfig,
-            WifiConfiguration[] connectableConfigs) {
+            WifiConfiguration[] connectableConfigs,
+            int lastSelectedNetworkId,
+            long lastSelectedNetworkTimestamp) {
         mScanResults = scanResults;
         mDefaultConfig = defaultWifiConfig;
         mConnectedConfig = connectedWifiConfig;
         mConnectableConfigs = connectableConfigs;
+        mLastSelectedNetworkId = lastSelectedNetworkId;
+        mLastSelectedNetworkTimestamp = lastSelectedNetworkTimestamp;
     }
 
     protected RecommendationRequest(Parcel in) {
@@ -190,6 +215,9 @@
         } else {
             mConnectableConfigs = null;
         }
+
+        mLastSelectedNetworkId = in.readInt();
+        mLastSelectedNetworkTimestamp = in.readLong();
     }
 
     @Override
@@ -220,7 +248,8 @@
             dest.writeInt(0);
         }
 
-
+        dest.writeInt(mLastSelectedNetworkId);
+        dest.writeLong(mLastSelectedNetworkTimestamp);
     }
 
     public static final Creator<RecommendationRequest> CREATOR =
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index cea56b5..ffc735c 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -96,6 +96,7 @@
 
     public boolean requestTime(InetAddress address, int port, int timeout) {
         DatagramSocket socket = null;
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NTP);
         try {
             socket = new DatagramSocket();
             socket.setSoTimeout(timeout);
@@ -161,6 +162,7 @@
             if (socket != null) {
                 socket.close();
             }
+            TrafficStats.setThreadStatsTag(oldTag);
         }
 
         return true;
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index e7436be..fc66395 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -168,6 +168,24 @@
 
     /**
      * Set active tag to use when accounting {@link Socket} traffic originating
+     * from the current thread. Only one active tag per thread is supported.
+     * <p>
+     * Changes only take effect during subsequent calls to
+     * {@link #tagSocket(Socket)}.
+     * <p>
+     * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
+     * used internally by system services like {@link DownloadManager} when
+     * performing traffic on behalf of an application.
+     *
+     * @return the current tag for the calling thread, which can be used to
+     *         restore any existing values after a nested operation is finished
+     */
+    public static int getAndSetThreadStatsTag(int tag) {
+        return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+    }
+
+    /**
+     * Set active tag to use when accounting {@link Socket} traffic originating
      * from the current thread. The tag used internally is well-defined to
      * distinguish all backup-related traffic.
      *
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 73c9462..7c015de 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -38,7 +38,6 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
-import java.io.FileWriter;
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
@@ -334,12 +333,7 @@
      * @throws IOException
      */
     public static void stringToFile(String filename, String string) throws IOException {
-        FileWriter out = new FileWriter(filename);
-        try {
-            out.write(string);
-        } finally {
-            out.close();
-        }
+        bytesToFile(filename, string.getBytes(StandardCharsets.UTF_8));
     }
 
     /**
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index e15f086..d6d5cb6 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -27,6 +27,8 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
+import libcore.util.SneakyThrow;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
@@ -250,6 +252,7 @@
     private static final int EX_NETWORK_MAIN_THREAD = -6;
     private static final int EX_UNSUPPORTED_OPERATION = -7;
     private static final int EX_SERVICE_SPECIFIC = -8;
+    private static final int EX_PARCELABLE = -9;
     private static final int EX_HAS_REPLY_HEADER = -128;  // special; see below
     // EX_TRANSACTION_FAILED is used exclusively in native code.
     // see libbinder's binder/Status.h
@@ -1597,7 +1600,12 @@
      */
     public final void writeException(Exception e) {
         int code = 0;
-        if (e instanceof SecurityException) {
+        if (e instanceof Parcelable
+                && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) {
+            // We only send Parcelable exceptions that are in the
+            // BootClassLoader to ensure that the receiver can unpack them
+            code = EX_PARCELABLE;
+        } else if (e instanceof SecurityException) {
             code = EX_SECURITY;
         } else if (e instanceof BadParcelableException) {
             code = EX_BAD_PARCELABLE;
@@ -1623,8 +1631,20 @@
             throw new RuntimeException(e);
         }
         writeString(e.getMessage());
-        if (e instanceof ServiceSpecificException) {
-            writeInt(((ServiceSpecificException)e).errorCode);
+        switch (code) {
+            case EX_SERVICE_SPECIFIC:
+                writeInt(((ServiceSpecificException) e).errorCode);
+                break;
+            case EX_PARCELABLE:
+                // Write parceled exception prefixed by length
+                final int sizePosition = dataPosition();
+                writeInt(0);
+                writeParcelable((Parcelable) e, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+                final int payloadPosition = dataPosition();
+                setDataPosition(sizePosition);
+                writeInt(payloadPosition - sizePosition);
+                setDataPosition(payloadPosition);
+                break;
         }
     }
 
@@ -1722,6 +1742,13 @@
      */
     public final void readException(int code, String msg) {
         switch (code) {
+            case EX_PARCELABLE:
+                if (readInt() > 0) {
+                    SneakyThrow.sneakyThrow(
+                            (Exception) readParcelable(Parcelable.class.getClassLoader()));
+                } else {
+                    throw new RuntimeException(msg + " [missing Parcelable]");
+                }
             case EX_SECURITY:
                 throw new SecurityException(msg);
             case EX_BAD_PARCELABLE:
diff --git a/core/java/android/os/ParcelableException.java b/core/java/android/os/ParcelableException.java
new file mode 100644
index 0000000..d84d629
--- /dev/null
+++ b/core/java/android/os/ParcelableException.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.io.IOException;
+
+/**
+ * Wrapper class that offers to transport typical {@link Throwable} across a
+ * {@link Binder} call. This class is typically used to transport exceptions
+ * that cannot be modified to add {@link Parcelable} behavior, such as
+ * {@link IOException}.
+ * <ul>
+ * <li>The wrapped throwable must be defined as system class (that is, it must
+ * be in the same {@link ClassLoader} as {@link Parcelable}).
+ * <li>The wrapped throwable must support the
+ * {@link Throwable#Throwable(String)} constructor.
+ * <li>The receiver side must catch any thrown {@link ParcelableException} and
+ * call {@link #maybeRethrow(Class)} for all expected exception types.
+ * </ul>
+ *
+ * @hide
+ */
+public final class ParcelableException extends RuntimeException implements Parcelable {
+    public ParcelableException(Throwable t) {
+        super(t);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T extends Throwable> void maybeRethrow(Class<T> clazz) throws T {
+        if (clazz.isAssignableFrom(getCause().getClass())) {
+            throw (T) getCause();
+        }
+    }
+
+    /** {@hide} */
+    public static Throwable readFromParcel(Parcel in) {
+        final String name = in.readString();
+        final String msg = in.readString();
+        try {
+            final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader());
+            return (Throwable) clazz.getConstructor(String.class).newInstance(msg);
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(name + ": " + msg);
+        }
+    }
+
+    /** {@hide} */
+    public static void writeToParcel(Parcel out, Throwable t) {
+        out.writeString(t.getClass().getName());
+        out.writeString(t.getMessage());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        writeToParcel(dest, getCause());
+    }
+
+    public static final Creator<ParcelableException> CREATOR = new Creator<ParcelableException>() {
+        @Override
+        public ParcelableException createFromParcel(Parcel source) {
+            return new ParcelableException(readFromParcel(source));
+        }
+
+        @Override
+        public ParcelableException[] newArray(int size) {
+            return new ParcelableException[size];
+        }
+    };
+}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 0da4bd1..ae981b7 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.net.TrafficStats;
 import android.net.Uri;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -245,11 +246,17 @@
      */
     private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8;  // for VmPolicy
 
+    /**
+     * @hide
+     */
+    private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24;  // for VmPolicy
+
     private static final int ALL_VM_DETECT_BITS =
             DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
             DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
             DETECT_VM_REGISTRATION_LEAKS | DETECT_VM_FILE_URI_EXPOSURE |
-            DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
+            DETECT_VM_CLEARTEXT_NETWORK | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION |
+            DETECT_VM_UNTAGGED_SOCKET;
 
     // Byte 3: Penalty
 
@@ -300,6 +307,8 @@
      */
     public static final int PENALTY_DEATH_ON_FILE_URI_EXPOSURE = 0x04 << 24;
 
+    // CAUTION: we started stealing the top bits of Byte 4 for VM above
+
     /**
      * Mask of all the penalty bits valid for thread policies.
      */
@@ -715,7 +724,8 @@
             public Builder detectAll() {
                 int flags = DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
                         | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS
-                        | DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION;
+                        | DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION
+                        | DETECT_VM_UNTAGGED_SOCKET;
 
                 // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have facility
                 // for apps to mark sockets that should be ignored
@@ -820,6 +830,22 @@
             }
 
             /**
+             * Detect any sockets in the calling app which have not been tagged
+             * using {@link TrafficStats}. Tagging sockets can help you
+             * investigate network usage inside your app, such as a narrowing
+             * down heavy usage to a specific library or component.
+             * <p>
+             * This currently does not detect sockets created in native code.
+             *
+             * @see TrafficStats#setThreadStatsTag(int)
+             * @see TrafficStats#tagSocket(java.net.Socket)
+             * @see TrafficStats#tagDatagramSocket(java.net.DatagramSocket)
+             */
+            public Builder detectUntaggedSockets() {
+                return enable(DETECT_VM_UNTAGGED_SOCKET);
+            }
+
+            /**
              * Crashes the whole process on violation. This penalty runs at the
              * end of all enabled penalties so you'll still get your logging or
              * other violations before the process dies.
@@ -1152,6 +1178,11 @@
             if (IS_ENG_BUILD) {
                 policyBuilder.penaltyLog();
             }
+            // All core system components need to tag their sockets to aid
+            // system health investigations
+            if (android.os.Process.myUid() < android.os.Process.FIRST_APPLICATION_UID) {
+                policyBuilder.detectUntaggedSockets();
+            }
             setVmPolicy(policyBuilder.build());
             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
         }
@@ -1832,6 +1863,13 @@
     /**
      * @hide
      */
+    public static boolean vmUntaggedSocketEnabled() {
+        return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0;
+    }
+
+    /**
+     * @hide
+     */
     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
         onVmPolicyViolation(message, originStack);
     }
@@ -1911,6 +1949,14 @@
                 forceDeath);
     }
 
+    /**
+     * @hide
+     */
+    public static void onUntaggedSocket() {
+        onVmPolicyViolation(null, new Throwable("Untagged socket detected; use"
+                + " TrafficStats.setThreadSocketTag() to track all network usage"));
+    }
+
     // Map from VM violation fingerprint to uptime millis.
     private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 371c0f3..d136ec5 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -50,6 +50,7 @@
 import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.os.BatteryManager;
+import android.os.Binder;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.DropBoxManager;
@@ -286,6 +287,21 @@
             "android.settings.SECURITY_SETTINGS";
 
     /**
+     * Activity Action: Show settings to allow configuration of trusted external sources
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_EXTERNAL_SOURCES =
+            "android.settings.action.MANAGE_EXTERNAL_SOURCES";
+
+    /**
      * Activity Action: Show trusted credentials settings, opening to the user tab,
      * to allow management of installed credentials.
      * <p>
@@ -1581,6 +1597,24 @@
     // with a partial enable/disable state in multi-threaded situations.
     private static final Object mLocationSettingsLock = new Object();
 
+    // Used in system server calling uid workaround in call()
+    private static boolean sInSystemServer = false;
+    private static final Object sInSystemServerLock = new Object();
+
+    /** @hide */
+    public static void setInSystemServer() {
+        synchronized (sInSystemServerLock) {
+            sInSystemServer = true;
+        }
+    }
+
+    /** @hide */
+    public static boolean isInSystemServer() {
+        synchronized (sInSystemServerLock) {
+            return sInSystemServer;
+        }
+    }
+
     public static class SettingNotFoundException extends AndroidException {
         public SettingNotFoundException(String msg) {
             super(msg);
@@ -1789,7 +1823,23 @@
                             }
                         }
                     }
-                    Bundle b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
+                    Bundle b;
+                    // If we're in system server and in a binder transaction we need to clear the
+                    // calling uid. This works around code in system server that did not call
+                    // clearCallingIdentity, previously this wasn't needed because reading settings
+                    // did not do permission checking but thats no longer the case.
+                    // Long term this should be removed and callers should properly call
+                    // clearCallingIdentity or use a ContentResolver from the caller as needed.
+                    if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
+                        final long token = Binder.clearCallingIdentity();
+                        try {
+                            b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
+                        } finally {
+                            Binder.restoreCallingIdentity(token);
+                        }
+                    } else {
+                        b = cp.call(cr.getPackageName(), mCallGetCommand, name, args);
+                    }
                     if (b != null) {
                         String value = b.getString(Settings.NameValueTable.VALUE);
                         // Don't update our cache for reads of other users' data
@@ -1849,7 +1899,19 @@
             try {
                 Bundle queryArgs = ContentResolver.createSqlQueryBundle(
                         NAME_EQ_PLACEHOLDER, new String[]{name}, null);
-                c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs, null);
+                // Same workaround as above.
+                if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs,
+                                null);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                } else {
+                    c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs,
+                            null);
+                }
                 if (c == null) {
                     Log.w(TAG, "Can't get key " + name + " from " + mUri);
                     return null;
@@ -4006,6 +4068,22 @@
         }
 
         /**
+         * System settings which can be accessed by ephemeral apps.
+         * @hide
+         */
+        public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>();
+        static {
+            EPHEMERAL_SETTINGS.add(TEXT_AUTO_REPLACE);
+            EPHEMERAL_SETTINGS.add(TEXT_AUTO_CAPS);
+            EPHEMERAL_SETTINGS.add(TEXT_AUTO_PUNCTUATE);
+            EPHEMERAL_SETTINGS.add(TEXT_SHOW_PASSWORD);
+            EPHEMERAL_SETTINGS.add(DATE_FORMAT);
+            EPHEMERAL_SETTINGS.add(FONT_SCALE);
+            EPHEMERAL_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED);
+            EPHEMERAL_SETTINGS.add(TIME_12_24);
+        }
+
+        /**
          * When to use Wi-Fi calling
          *
          * @see android.telephony.TelephonyManager.WifiCallingChoices
@@ -6884,6 +6962,20 @@
         }
 
         /**
+         * Secure settings which can be accessed by ephemeral apps.
+         * @hide
+         */
+        public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>();
+        static {
+            EPHEMERAL_SETTINGS.add(ENABLED_ACCESSIBILITY_SERVICES);
+            EPHEMERAL_SETTINGS.add(ACCESSIBILITY_SPEAK_PASSWORD);
+            EPHEMERAL_SETTINGS.add(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
+
+            EPHEMERAL_SETTINGS.add(DEFAULT_INPUT_METHOD);
+            EPHEMERAL_SETTINGS.add(ENABLED_INPUT_METHODS);
+        }
+
+        /**
          * Helper method for determining if a location provider is enabled.
          *
          * @param cr the content resolver to use
@@ -9891,6 +9983,20 @@
          * @hide
          */
         public static final String CELL_ON = "cell_on";
+
+        /**
+         * Global settings which can be accessed by ephemeral apps.
+         * @hide
+         */
+        public static final Set<String> EPHEMERAL_SETTINGS = new ArraySet<>();
+        static {
+            EPHEMERAL_SETTINGS.add(WAIT_FOR_DEBUGGER);
+            EPHEMERAL_SETTINGS.add(DEVICE_PROVISIONED);
+            EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES);
+            EPHEMERAL_SETTINGS.add(DEVELOPMENT_FORCE_RTL);
+            EPHEMERAL_SETTINGS.add(EPHEMERAL_COOKIE_MAX_SIZE_BYTES);
+        }
+
     }
 
     /**
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index c3cbcdc..a4b6807 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -30,6 +30,7 @@
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.Voicemail;
+
 import java.util.List;
 
 /**
@@ -279,6 +280,48 @@
         public static final String LAST_MODIFIED = "last_modified";
 
         /**
+         * Flag to indicate the voicemail was backed up. The value will be 1 if backed up, 0 if
+         * not.
+         *
+         * <P>Type: INTEGER (boolean)</P>
+         *
+         * @hide
+         */
+        public static final String BACKED_UP = "backed_up";
+
+        /**
+         * Flag to indicate the voicemail was restored from a backup. The value will be 1 if
+         * restored, 0 if not.
+         *
+         * <P>Type: INTEGER (boolean)</P>
+         *
+         * @hide
+         */
+        public static final String RESTORED = "restored";
+
+        /**
+         * Flag to indicate the voicemail was marked as archived. Archived voicemail should not be
+         * deleted even if it no longer exist on the server. The value will be 1 if archived true, 0
+         * if not.
+         *
+         * <P>Type: INTEGER (boolean)</P>
+         *
+         * @hide
+         */
+        public static final String ARCHIVED = "archived";
+
+        /**
+         * Flag to indicate the voicemail is a OMTP voicemail handled by the {@link
+         * android.telephony.VisualVoicemailService}. The UI should only show OMTP voicemails from
+         * the current visual voicemail package.
+         *
+         * <P>Type: INTEGER (boolean)</P>
+         *
+         * @hide
+         */
+        public static final String IS_OMTP_VOICEMAIL = "is_omtp_voicmail";
+
+        /**
          * A convenience method to build voicemail URI specific to a source package by appending
          * {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI.
          */
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index eb3d031..22f1bed 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -132,6 +132,8 @@
     public static final int KM_PURPOSE_DECRYPT = 1;
     public static final int KM_PURPOSE_SIGN = 2;
     public static final int KM_PURPOSE_VERIFY = 3;
+    public static final int KM_PURPOSE_DERIVE_KEY = 4;
+    public static final int KM_PURPOSE_WRAP_KEY = 5;
 
     // Key formats.
     public static final int KM_KEY_FORMAT_X509 = 0;
diff --git a/core/java/android/util/ExceptionUtils.java b/core/java/android/util/ExceptionUtils.java
index f5d515d..da0b609 100644
--- a/core/java/android/util/ExceptionUtils.java
+++ b/core/java/android/util/ExceptionUtils.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.os.ParcelableException;
+
 import java.io.IOException;
 
 /**
@@ -24,19 +26,13 @@
  * @hide
  */
 public class ExceptionUtils {
-    // TODO: longer term these should be replaced with first-class
-    // Parcel.read/writeException() and AIDL support, but for now do this using
-    // a nasty hack.
-
-    private static final String PREFIX_IO = "\u2603";
-
     public static RuntimeException wrap(IOException e) {
-        throw new IllegalStateException(PREFIX_IO + e.getMessage());
+        throw new ParcelableException(e);
     }
 
     public static void maybeUnwrapIOException(RuntimeException e) throws IOException {
-        if ((e instanceof IllegalStateException) && e.getMessage().startsWith(PREFIX_IO)) {
-            throw new IOException(e.getMessage().substring(PREFIX_IO.length()));
+        if (e instanceof ParcelableException) {
+            ((ParcelableException) e).maybeRethrow(IOException.class);
         }
     }
 
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index f3f3d40..7a5c65f 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -335,7 +335,7 @@
         private ActionProvider itemActionProvider;
 
         private CharSequence itemContentDescription;
-        private CharSequence itemTooltip;
+        private CharSequence itemTooltipText;
 
         private static final int defaultGroupId = NO_ID;
         private static final int defaultItemId = NO_ID;
@@ -429,7 +429,7 @@
 
             itemContentDescription =
                     a.getText(com.android.internal.R.styleable.MenuItem_contentDescription);
-            itemTooltip = a.getText(com.android.internal.R.styleable.MenuItem_tooltip);
+            itemTooltipText = a.getText(com.android.internal.R.styleable.MenuItem_tooltipText);
 
             a.recycle();
 
@@ -495,7 +495,7 @@
             }
 
             item.setContentDescription(itemContentDescription);
-            item.setTooltip(itemTooltip);
+            item.setTooltipText(itemTooltipText);
         }
 
         public MenuItem addItem() {
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 5ced765..3f8d089 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -621,9 +621,9 @@
     /**
      * Change the tooltip text associated with this menu item.
      *
-     * @param tooltip The new tooltip text.
+     * @param tooltipText The new tooltip text.
      */
-    default MenuItem setTooltip(CharSequence tooltip) {
+    default MenuItem setTooltipText(CharSequence tooltipText) {
         return this;
     }
 
@@ -632,7 +632,7 @@
      *
      * @return The tooltip text.
      */
-    default CharSequence getTooltip() {
+    default CharSequence getTooltipText() {
         return null;
     }
 }
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f3ebcb4..b0826a8 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -360,6 +360,7 @@
     void destroy() {
         mInitialized = false;
         updateEnabledState(null);
+        mRootNode.discardDisplayList();
         nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
     }
 
@@ -491,20 +492,12 @@
      */
     void destroyHardwareResources(View view) {
         destroyResources(view);
+        mRootNode.discardDisplayList();
         nDestroyHardwareResources(mNativeProxy);
     }
 
     private static void destroyResources(View view) {
         view.destroyHardwareResources();
-
-        if (view instanceof ViewGroup) {
-            ViewGroup group = (ViewGroup) view;
-
-            int count = group.getChildCount();
-            for (int i = 0; i < count; i++) {
-                destroyResources(group.getChildAt(i));
-            }
-        }
     }
 
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 37dfdb9..26e311c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3718,7 +3718,7 @@
          * Text to be displayed in a tooltip popup.
          */
         @Nullable
-        CharSequence mTooltip;
+        CharSequence mTooltipText;
 
         /**
          * View-relative position of the tooltip anchor point.
@@ -4761,8 +4761,8 @@
                         forceHasOverlappingRendering(a.getBoolean(attr, true));
                     }
                     break;
-                case R.styleable.View_tooltip:
-                    setTooltip(a.getText(attr));
+                case R.styleable.View_tooltipText:
+                    setTooltipText(a.getText(attr));
                     break;
                 case R.styleable.View_keyboardNavigationCluster:
                     if (a.peekValue(attr) != null) {
@@ -16641,6 +16641,12 @@
         // safe to free its copy of the display list as it knows that we will
         // push an updated DisplayList if we try to draw again
         resetDisplayList();
+        if (mOverlay != null) {
+            mOverlay.getOverlayView().destroyHardwareResources();
+        }
+        if (mGhostView != null) {
+            mGhostView.destroyHardwareResources();
+        }
     }
 
     /**
@@ -16811,11 +16817,9 @@
     }
 
     private void resetDisplayList() {
-        if (mRenderNode.isValid()) {
-            mRenderNode.discardDisplayList();
-        }
+        mRenderNode.discardDisplayList();
 
-        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
+        if (mBackgroundRenderNode != null) {
             mBackgroundRenderNode.discardDisplayList();
         }
     }
@@ -24638,10 +24642,10 @@
      * menu). </li>
      * <li>On hover, after a brief delay since the pointer has stopped moving </li>
      *
-     * @param tooltip the tooltip text, or null if no tooltip is required
+     * @param tooltipText the tooltip text, or null if no tooltip is required
      */
-    public final void setTooltip(@Nullable CharSequence tooltip) {
-        if (TextUtils.isEmpty(tooltip)) {
+    public final void setTooltipText(@Nullable CharSequence tooltipText) {
+        if (TextUtils.isEmpty(tooltipText)) {
             setFlags(0, TOOLTIP);
             hideTooltip();
             mTooltipInfo = null;
@@ -24652,21 +24656,42 @@
                 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
                 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
             }
-            mTooltipInfo.mTooltip = tooltip;
+            mTooltipInfo.mTooltipText = tooltipText;
             if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
-                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltip);
+                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
             }
         }
     }
 
     /**
+     * To be removed once the support library has stopped using it.
+     *
+     * @deprecated use {@link #setTooltipText} instead
+     */
+    @Deprecated
+    public final void setTooltip(@Nullable CharSequence tooltipText) {
+        setTooltipText(tooltipText);
+    }
+
+    /**
      * Returns the view's tooltip text.
      *
      * @return the tooltip text
      */
     @Nullable
+    public final CharSequence getTooltipText() {
+        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
+    }
+
+    /**
+     * To be removed once the support library has stopped using it.
+     *
+     * @deprecated use {@link #getTooltipText} instead
+     */
+    @Deprecated
+    @Nullable
     public final CharSequence getTooltip() {
-        return mTooltipInfo != null ? mTooltipInfo.mTooltip : null;
+        return getTooltipText();
     }
 
     private boolean showTooltip(int x, int y, boolean fromLongClick) {
@@ -24676,7 +24701,7 @@
         if ((mViewFlags & ENABLED_MASK) != ENABLED) {
             return false;
         }
-        final CharSequence tooltipText = getTooltip();
+        final CharSequence tooltipText = getTooltipText();
         if (TextUtils.isEmpty(tooltipText)) {
             return false;
         }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a479bb3..d252d75 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3450,6 +3450,16 @@
         super.dispatchDetachedFromWindow();
     }
 
+    /** @hide */
+    @Override
+    protected void destroyHardwareResources() {
+        super.destroyHardwareResources();
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            getChildAt(i).destroyHardwareResources();
+        }
+    }
+
     /**
      * @hide
      */
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b6693c7..08b18a4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3257,20 +3257,6 @@
     }
 
     /**
-     * Returns the font variation settings.
-     *
-     * @return the currently set font variation settings.  Returns null if no variation is
-     * specified.
-     *
-     * @see #setFontVariationSettings(String)
-     * @see Paint#setFontVariationSettings(String) Paint.setFontVariationSettings(String)
-     */
-    @Nullable
-    public String getFontVariationSettings() {
-        return mTextPaint.getFontVariationSettings();
-    }
-
-    /**
      * Sets the break strategy for breaking paragraphs into lines. The default value for
      * TextView is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}, and the default value for
      * EditText is {@link Layout#BREAK_STRATEGY_SIMPLE}, the latter to avoid the
@@ -3377,41 +3363,6 @@
 
 
     /**
-     * Sets TrueType or OpenType font variation settings. The settings string is constructed from
-     * multiple pairs of axis tag and style values. The axis tag must contain four ASCII characters
-     * and must be wrapped with single quotes (U+0027) or double quotes (U+0022). Axis strings that
-     * are longer or shorter than four characters, or contain characters outside of U+0020..U+007E
-     * are invalid. If a specified axis name is not defined in the font, the settings will be
-     * ignored.
-     *
-     * <pre>
-     *   textView.setFontVariationSettings("'wdth' 1.0");
-     *   textView.setFontVariationSettings("'AX  ' 1.8, 'FB  ' 2.0");
-     * </pre>
-     *
-     * @param fontVariationSettings font variation settings. You can pass null or empty string as
-     *                              no variation settings.
-     *
-     * @see #getFontVariationSettings()
-     * @see Paint#getFontVariationSettings() Paint.getFontVariationSettings()
-     */
-    public void setFontVariationSettings(@Nullable String fontVariationSettings) {
-        final String existingSettings = mTextPaint.getFontVariationSettings();
-        if (fontVariationSettings == existingSettings
-                || (fontVariationSettings != null
-                        && fontVariationSettings.equals(existingSettings))) {
-            return;
-        }
-        mTextPaint.setFontVariationSettings(fontVariationSettings);
-
-        if (mLayout != null) {
-            nullLayouts();
-            requestLayout();
-            invalidate();
-        }
-    }
-
-    /**
      * Sets the text color for all the states (normal, selected,
      * focused) to be this color.
      *
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index d9ab47e..096fcb8 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -343,53 +343,42 @@
     class LogisticRegressionAppRanker {
         private static final String PARAM_SHARED_PREF_NAME = "resolver_ranker_params";
         private static final String BIAS_PREF_KEY = "bias";
-        private static final float LEARNING_RATE = 0.02f;
-        private static final float REGULARIZER_PARAM = 0.1f;
+        private static final String VERSION_PREF_KEY = "version";
+
+        // parameters for a pre-trained model, to initialize the app ranker. When updating the
+        // pre-trained model, please update these params, as well as initModel().
+        private static final int CURRENT_VERSION = 1;
+        private static final float LEARNING_RATE = 0.0001f;
+        private static final float REGULARIZER_PARAM = 0.0001f;
+
         private SharedPreferences mParamSharedPref;
         private ArrayMap<String, Float> mFeatureWeights;
         private float mBias;
 
         public LogisticRegressionAppRanker(Context context) {
             mParamSharedPref = getParamSharedPref(context);
+            initModel();
         }
 
         public float predict(ArrayMap<String, Float> target) {
-            if (target == null || mParamSharedPref == null) {
+            if (target == null) {
                 return 0.0f;
             }
             final int featureSize = target.size();
-            if (featureSize == 0) {
-                return 0.0f;
-            }
             float sum = 0.0f;
-            if (mFeatureWeights == null) {
-                mBias = mParamSharedPref.getFloat(BIAS_PREF_KEY, 0.0f);
-                mFeatureWeights = new ArrayMap<>(featureSize);
-                for (int i = 0; i < featureSize; i++) {
-                    String featureName = target.keyAt(i);
-                    float weight = mParamSharedPref.getFloat(featureName, 0.0f);
-                    sum += weight * target.valueAt(i);
-                    mFeatureWeights.put(featureName, weight);
-                }
-            } else {
-                for (int i = 0; i < featureSize; i++) {
-                    String featureName = target.keyAt(i);
-                    float weight = mFeatureWeights.getOrDefault(featureName, 0.0f);
-                    sum += weight * target.valueAt(i);
-                }
+            for (int i = 0; i < featureSize; i++) {
+                String featureName = target.keyAt(i);
+                float weight = mFeatureWeights.getOrDefault(featureName, 0.0f);
+                sum += weight * target.valueAt(i);
             }
             return (float) (1.0 / (1.0 + Math.exp(-mBias - sum)));
         }
 
         public void update(ArrayMap<String, Float> target, float predict, boolean isSelected) {
-            if (target == null || target.size() == 0) {
+            if (target == null) {
                 return;
             }
             final int featureSize = target.size();
-            if (mFeatureWeights == null) {
-                mBias = 0.0f;
-                mFeatureWeights = new ArrayMap<>(featureSize);
-            }
             float error = isSelected ? 1.0f - predict : -predict;
             for (int i = 0; i < featureSize; i++) {
                 String featureName = target.keyAt(i);
@@ -405,15 +394,13 @@
         }
 
         public void commitUpdate() {
-            if (mFeatureWeights == null || mFeatureWeights.size() == 0) {
-                return;
-            }
             SharedPreferences.Editor editor = mParamSharedPref.edit();
             editor.putFloat(BIAS_PREF_KEY, mBias);
             final int size = mFeatureWeights.size();
             for (int i = 0; i < size; i++) {
                 editor.putFloat(mFeatureWeights.keyAt(i), mFeatureWeights.valueAt(i));
             }
+            editor.putInt(VERSION_PREF_KEY, CURRENT_VERSION);
             editor.apply();
         }
 
@@ -431,5 +418,27 @@
                     PARAM_SHARED_PREF_NAME + ".xml");
             return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
         }
+
+        private void initModel() {
+            mFeatureWeights = new ArrayMap<>(4);
+            if (mParamSharedPref == null ||
+                    mParamSharedPref.getInt(VERSION_PREF_KEY, 0) < CURRENT_VERSION) {
+                // Initializing the app ranker to a pre-trained model. When updating the pre-trained
+                // model, please increment CURRENT_VERSION, and update LEARNING_RATE and
+                // REGULARIZER_PARAM.
+                mBias = -1.6568f;
+                mFeatureWeights.put(LAUNCH_SCORE, 2.5543f);
+                mFeatureWeights.put(TIME_SPENT_SCORE, 2.8412f);
+                mFeatureWeights.put(RECENCY_SCORE, 0.269f);
+                mFeatureWeights.put(CHOOSER_SCORE, 4.2222f);
+            } else {
+                mBias = mParamSharedPref.getFloat(BIAS_PREF_KEY, 0.0f);
+                mFeatureWeights.put(LAUNCH_SCORE, mParamSharedPref.getFloat(LAUNCH_SCORE, 0.0f));
+                mFeatureWeights.put(
+                        TIME_SPENT_SCORE, mParamSharedPref.getFloat(TIME_SPENT_SCORE, 0.0f));
+                mFeatureWeights.put(RECENCY_SCORE, mParamSharedPref.getFloat(RECENCY_SCORE, 0.0f));
+                mFeatureWeights.put(CHOOSER_SCORE, mParamSharedPref.getFloat(CHOOSER_SCORE, 0.0f));
+            }
+        }
     }
 }
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index c828d11..e8919ed 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -120,7 +120,7 @@
                             sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
                             sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms");
-                            Slog.wtf(TAG, sb.toString());
+                            Slog.e(TAG, sb.toString());
 
                             userTimeDeltaUs = 0;
                             systemTimeDeltaUs = 0;
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index 4dd3360..6d13743 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -128,11 +128,14 @@
     /**
      * Applies the offset to the {@param stackBounds} to adjust it to a minimized state.
      */
-    public void applyMinimizedOffset(Rect stackBounds, Rect movementBounds, Point displaySize) {
+    public void applyMinimizedOffset(Rect stackBounds, Rect movementBounds, Point displaySize,
+            Rect stableInsets) {
         if (stackBounds.left <= movementBounds.centerX()) {
-            stackBounds.offsetTo(-stackBounds.width() + mMinimizedVisibleSize, stackBounds.top);
+            stackBounds.offsetTo(stableInsets.left + mMinimizedVisibleSize - stackBounds.width(),
+                    stackBounds.top);
         } else {
-            stackBounds.offsetTo(displaySize.x - mMinimizedVisibleSize, stackBounds.top);
+            stackBounds.offsetTo(displaySize.x - stableInsets.right - mMinimizedVisibleSize,
+                    stackBounds.top);
         }
     }
 
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index c8697dd..1fce0b7 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -48,7 +48,7 @@
     private MenuItem.OnMenuItemClickListener mClickListener;
 
     private CharSequence mContentDescription;
-    private CharSequence mTooltip;
+    private CharSequence mTooltipText;
 
     private static final int NO_ICON = 0;
 
@@ -290,13 +290,13 @@
     }
 
     @Override
-    public MenuItem setTooltip(CharSequence tooltip) {
-        mTooltip = tooltip;
+    public MenuItem setTooltipText(CharSequence tooltipText) {
+        mTooltipText = tooltipText;
         return this;
     }
 
     @Override
-    public CharSequence getTooltip() {
-        return mTooltip;
+    public CharSequence getTooltipText() {
+        return mTooltipText;
     }
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 4ee5993..92e1d80 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -193,12 +193,12 @@
             setContentDescription(contentDescription);
         }
 
-        final CharSequence tooltip = mItemData.getTooltip();
-        if (TextUtils.isEmpty(tooltip)) {
+        final CharSequence tooltipText = mItemData.getTooltipText();
+        if (TextUtils.isEmpty(tooltipText)) {
             // Use the uncondensed title for tooltip, but only if the title is not shown already.
-            setTooltip(visible ? null : mItemData.getTitle());
+            setTooltipText(visible ? null : mItemData.getTitle());
         } else {
-            setTooltip(tooltip);
+            setTooltipText(tooltipText);
         }
     }
 
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index f9ebdbc..6c8f330 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -113,7 +113,7 @@
             } else {
                 setContentDescription(contentDescription);
             }
-            setTooltip(mItemData.getTooltip());
+            setTooltipText(mItemData.getTooltipText());
         }
     }
 
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index 7c9f709..43005e6 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -115,7 +115,7 @@
         setEnabled(itemData.isEnabled());
         setSubMenuArrowVisible(itemData.hasSubMenu());
         setContentDescription(itemData.getContentDescription());
-        setTooltip(itemData.getTooltip());
+        setTooltipText(itemData.getTooltipText());
     }
 
     public void setForceShowIcon(boolean forceShow) {
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index cad0276..342943f 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -94,7 +94,7 @@
     private ContextMenuInfo mMenuInfo;
 
     private CharSequence mContentDescription;
-    private CharSequence mTooltip;
+    private CharSequence mTooltipText;
 
     private static String sLanguage;
     private static String sPrependShortcutLabel;
@@ -689,8 +689,8 @@
     }
 
     @Override
-    public MenuItem setTooltip(CharSequence tooltip) {
-        mTooltip = tooltip;
+    public MenuItem setTooltipText(CharSequence tooltipText) {
+        mTooltipText = tooltipText;
 
         mMenu.onItemsChanged(false);
 
@@ -698,7 +698,7 @@
     }
 
     @Override
-    public CharSequence getTooltip() {
-        return mTooltip;
+    public CharSequence getTooltipText() {
+        return mTooltipText;
     }
 }
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 04e09a8..58e694a 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1591,7 +1591,7 @@
                     } else {
                         menuButton.setContentDescription(contentDescription);
                     }
-                    menuButton.setTooltip(menuItem.getTooltip());
+                    menuButton.setTooltipText(menuItem.getTooltipText());
                     menuButton.setMinimumWidth(minimumWidth);
                 }
                 return menuButton;
@@ -1642,17 +1642,17 @@
             ((ImageButton) menuItemButton
                     .findViewById(R.id.floating_toolbar_menu_item_image_button))
                     .setImageDrawable(menuItem.getIcon());
-            final CharSequence tooltip = menuItem.getTooltip();
-            if (TextUtils.isEmpty(tooltip)) {
-                menuItemButton.setTooltip(menuItem.getTitle());
+            final CharSequence tooltipText = menuItem.getTooltipText();
+            if (TextUtils.isEmpty(tooltipText)) {
+                menuItemButton.setTooltipText(menuItem.getTitle());
             } else {
-                menuItemButton.setTooltip(tooltip);
+                menuItemButton.setTooltipText(tooltipText);
             }
         } else {
             menuItemButton = LayoutInflater.from(context)
                     .inflate(R.layout.floating_popup_menu_button, null);
             ((Button) menuItemButton).setText(menuItem.getTitle());
-            menuItemButton.setTooltip(menuItem.getTooltip());
+            menuItemButton.setTooltipText(menuItem.getTooltipText());
         }
         final CharSequence contentDescription = menuItem.getContentDescription();
         if (TextUtils.isEmpty(contentDescription)) {
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 4466575..311bfac 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -471,7 +471,7 @@
                 if (mIconView != null) {
                     mIconView.setContentDescription(tab.getContentDescription());
                 }
-                setTooltip(hasText? null : tab.getContentDescription());
+                setTooltipText(hasText? null : tab.getContentDescription());
             }
         }
 
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
index 06ef4c9..03f2bc1 100644
--- a/core/java/com/android/server/NetworkManagementSocketTagger.java
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.os.StrictMode;
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Slog;
@@ -50,16 +51,20 @@
         SocketTagger.set(new NetworkManagementSocketTagger());
     }
 
-    public static void setThreadSocketStatsTag(int tag) {
+    public static int setThreadSocketStatsTag(int tag) {
+        final int old = threadSocketTags.get().statsTag;
         threadSocketTags.get().statsTag = tag;
+        return old;
     }
 
     public static int getThreadSocketStatsTag() {
         return threadSocketTags.get().statsTag;
     }
 
-    public static void setThreadSocketStatsUid(int uid) {
+    public static int setThreadSocketStatsUid(int uid) {
+        final int old = threadSocketTags.get().statsUid;
         threadSocketTags.get().statsUid = uid;
+        return old;
     }
 
     @Override
@@ -69,6 +74,9 @@
             Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
                     + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid);
         }
+        if (options.statsTag == -1 && StrictMode.vmUntaggedSocketEnabled()) {
+            StrictMode.onUntaggedSocket();
+        }
         // TODO: skip tagging when options would be no-op
         tagSocketFd(fd, options.statsTag, options.statsUid);
     }
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 168da5f..fcb4c7b 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -109,6 +109,10 @@
     // background while in data-usage save mode, as read from the configuration files.
     final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
 
+    // These are the action strings of broadcasts which are whitelisted to
+    // be delivered anonymously even to apps which target O+.
+    final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
+
     // These are the package names of apps which should be in the 'always'
     // URL-handling state upon factory reset.
     final ArraySet<String> mLinkedApps = new ArraySet<>();
@@ -162,6 +166,10 @@
         return mPermissions;
     }
 
+    public ArraySet<String> getAllowImplicitBroadcasts() {
+        return mAllowImplicitBroadcasts;
+    }
+
     public ArraySet<String> getAllowInPowerSaveExceptIdle() {
         return mAllowInPowerSaveExceptIdle;
     }
@@ -438,6 +446,17 @@
                     XmlUtils.skipCurrentTag(parser);
                     continue;
 
+                } else if ("allow-implicit-broadcast".equals(name) && allowAll) {
+                    String action = parser.getAttributeValue(null, "action");
+                    if (action == null) {
+                        Slog.w(TAG, "<allow-implicit-broadcast> without action in " + permFile
+                                + " at " + parser.getPositionDescription());
+                    } else {
+                        mAllowImplicitBroadcasts.add(action);
+                    }
+                    XmlUtils.skipCurrentTag(parser);
+                    continue;
+
                 } else if ("app-link".equals(name) && allowAppConfigs) {
                     String pkgname = parser.getAttributeValue(null, "package");
                     if (pkgname == null) {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 6a9ed8e..0d3ccdc 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -118,7 +118,6 @@
     android/graphics/ColorFilter.cpp \
     android/graphics/DrawFilter.cpp \
     android/graphics/FontFamily.cpp \
-    android/graphics/FontUtils.cpp \
     android/graphics/CreateJavaOutputStreamAdaptor.cpp \
     android/graphics/GIFMovie.cpp \
     android/graphics/GraphicBuffer.cpp \
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 685c93d..15e7165 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -30,7 +30,6 @@
 #include <android_runtime/android_util_AssetManager.h>
 #include <androidfw/AssetManager.h>
 #include "Utils.h"
-#include "FontUtils.h"
 
 #include <hwui/MinikinSkia.h>
 #include <hwui/Typeface.h>
@@ -40,54 +39,27 @@
 
 namespace android {
 
-struct NativeFamilyBuilder {
-    uint32_t langId;
-    int variant;
-    std::vector<minikin::Font> fonts;
-};
-
-static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring lang, jint variant) {
-    NativeFamilyBuilder* builder = new NativeFamilyBuilder();
-    if (lang != nullptr) {
-        ScopedUtfChars str(env, lang);
-        builder->langId = minikin::FontStyle::registerLanguageList(str.c_str());
-    } else {
-        builder->langId = minikin::FontStyle::registerLanguageList("");
+static jlong FontFamily_create(JNIEnv* env, jobject clazz, jstring lang, jint variant) {
+    if (lang == NULL) {
+        return (jlong)new minikin::FontFamily(variant);
     }
-    builder->variant = variant;
-    return reinterpret_cast<jlong>(builder);
+    ScopedUtfChars str(env, lang);
+    uint32_t langId = minikin::FontStyle::registerLanguageList(str.c_str());
+    return (jlong)new minikin::FontFamily(langId, variant);
 }
 
-static jlong FontFamily_create(jlong builderPtr) {
-    if (builderPtr == 0) {
-        return 0;
-    }
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    minikin::FontFamily* family = new minikin::FontFamily(
-            builder->langId, builder->variant, std::move(builder->fonts));
-    delete builder;
-    return reinterpret_cast<jlong>(family);
-}
-
-static void FontFamily_unref(jlong familyPtr) {
+static void FontFamily_unref(JNIEnv* env, jobject clazz, jlong familyPtr) {
     minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr);
     fontFamily->Unref();
 }
 
-static void addSkTypeface(jlong builderPtr, sk_sp<SkTypeface> face, const void* fontData,
-        size_t fontSize, int ttcIndex) {
+static jboolean addSkTypeface(minikin::FontFamily* family, sk_sp<SkTypeface> face,
+        const void* fontData, size_t fontSize, int ttcIndex) {
     minikin::MinikinFont* minikinFont =
             new MinikinFontSkia(std::move(face), fontData, fontSize, ttcIndex);
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    int weight;
-    bool italic;
-    if (!minikin::FontFamily::analyzeStyle(minikinFont, &weight, &italic)) {
-        ALOGE("analyzeStyle failed. Using default style");
-        weight = 400;
-        italic = false;
-    }
-    builder->fonts.push_back(minikin::Font(minikinFont, minikin::FontStyle(weight / 100, italic)));
+    bool result = family->addFont(minikinFont);
     minikinFont->Unref();
+    return result;
 }
 
 static void release_global_ref(const void* /*data*/, void* context) {
@@ -113,7 +85,7 @@
     }
 }
 
-static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong builderPtr, jobject bytebuf,
+static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jobject bytebuf,
         jint ttcIndex) {
     NPE_CHECK_RETURN_ZERO(env, bytebuf);
     const void* fontPtr = env->GetDirectBufferAddress(bytebuf);
@@ -140,11 +112,21 @@
         ALOGE("addFont failed to create font");
         return false;
     }
-    addSkTypeface(builderPtr, std::move(face), fontPtr, (size_t)fontSize, ttcIndex);
-    return true;
+    minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr);
+    return addSkTypeface(fontFamily, std::move(face), fontPtr, (size_t)fontSize, ttcIndex);
 }
 
-static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong builderPtr,
+static struct {
+    jmethodID mGet;
+    jmethodID mSize;
+} gListClassInfo;
+
+static struct {
+    jfieldID mTag;
+    jfieldID mStyleValue;
+} gAxisClassInfo;
+
+static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr,
         jobject font, jint ttcIndex, jobject listOfAxis, jint weight, jboolean isItalic) {
     NPE_CHECK_RETURN_ZERO(env, font);
 
@@ -152,22 +134,20 @@
     std::unique_ptr<SkFontMgr::FontParameters::Axis[]> skiaAxes;
     int skiaAxesLength = 0;
     if (listOfAxis) {
-        ListHelper list(env, listOfAxis);
-        jint listSize = list.size();
+        jint listSize = env->CallIntMethod(listOfAxis, gListClassInfo.mSize);
 
         skiaAxes.reset(new SkFontMgr::FontParameters::Axis[listSize]);
         skiaAxesLength = listSize;
         for (jint i = 0; i < listSize; ++i) {
-            jobject axisObject = list.get(i);
+            jobject axisObject = env->CallObjectMethod(listOfAxis, gListClassInfo.mGet, i);
             if (!axisObject) {
                 skiaAxes[i].fTag = 0;
                 skiaAxes[i].fStyleValue = 0;
                 continue;
             }
-            AxisHelper axis(env, axisObject);
 
-            jint tag = axis.getTag();
-            jfloat stylevalue = axis.getStyleValue();
+            jint tag = env->GetIntField(axisObject, gAxisClassInfo.mTag);
+            jfloat stylevalue = env->GetFloatField(axisObject, gAxisClassInfo.mStyleValue);
             skiaAxes[i].fTag = tag;
             skiaAxes[i].fStyleValue = SkFloatToScalar(stylevalue);
         }
@@ -198,11 +178,10 @@
         ALOGE("addFont failed to create font, invalid request");
         return false;
     }
+    minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr);
     minikin::MinikinFont* minikinFont =
-            new MinikinFontSkia(std::move(face), fontPtr, fontSize, ttcIndex);
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    builder->fonts.push_back(minikin::Font(minikinFont,
-            minikin::FontStyle(weight / 100, isItalic)));
+            new MinikinFontSkia(std::move(face), fontPtr, (size_t)fontSize, ttcIndex);
+    fontFamily->addFont(minikinFont, minikin::FontStyle(weight / 100, isItalic));
     minikinFont->Unref();
     return true;
 }
@@ -211,7 +190,7 @@
     delete static_cast<Asset*>(context);
 }
 
-static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong builderPtr,
+static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr,
         jobject jassetMgr, jstring jpath) {
     NPE_CHECK_RETURN_ZERO(env, jassetMgr);
     NPE_CHECK_RETURN_ZERO(env, jpath);
@@ -243,16 +222,14 @@
         ALOGE("addFontFromAsset failed to create font %s", str.c_str());
         return false;
     }
-
-    addSkTypeface(builderPtr, std::move(face), buf, bufSize, 0 /* ttc index */);
-    return true;
+    minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr);
+    return addSkTypeface(fontFamily, std::move(face), buf, bufSize, /* ttcIndex */ 0);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 static const JNINativeMethod gFontFamilyMethods[] = {
-    { "nInitBuilder",          "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
-    { "nCreateFamily",         "(J)J", (void*)FontFamily_create },
+    { "nCreateFamily",         "(Ljava/lang/String;I)J", (void*)FontFamily_create },
     { "nUnrefFamily",          "(J)V", (void*)FontFamily_unref },
     { "nAddFont",              "(JLjava/nio/ByteBuffer;I)Z", (void*)FontFamily_addFont },
     { "nAddFontWeightStyle",   "(JLjava/nio/ByteBuffer;ILjava/util/List;IZ)Z",
@@ -266,7 +243,14 @@
     int err = RegisterMethodsOrDie(env, "android/graphics/FontFamily", gFontFamilyMethods,
             NELEM(gFontFamilyMethods));
 
-    init_FontUtils(env);
+    jclass listClass = FindClassOrDie(env, "java/util/List");
+    gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;");
+    gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I");
+
+    jclass axisClass = FindClassOrDie(env, "android/graphics/FontListParser$Axis");
+    gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "tag", "I");
+    gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "styleValue", "F");
+
     return err;
 }
 
diff --git a/core/jni/android/graphics/FontUtils.cpp b/core/jni/android/graphics/FontUtils.cpp
deleted file mode 100644
index 11c2d29..0000000
--- a/core/jni/android/graphics/FontUtils.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "FontUtils.h"
-
-#include "JNIHelp.h"
-#include <core_jni_helpers.h>
-
-namespace android {
-namespace {
-
-static struct {
-    jmethodID mGet;
-    jmethodID mSize;
-} gListClassInfo;
-
-static struct {
-    jfieldID mTag;
-    jfieldID mStyleValue;
-} gAxisClassInfo;
-
-}  // namespace
-
-jint ListHelper::size() const {
-    return mEnv->CallIntMethod(mList, gListClassInfo.mSize);
-}
-
-jobject ListHelper::get(jint index) const {
-    return mEnv->CallObjectMethod(mList, gListClassInfo.mGet, index);
-}
-
-jint AxisHelper::getTag() const {
-    return mEnv->GetIntField(mAxis, gAxisClassInfo.mTag);
-}
-
-jfloat AxisHelper::getStyleValue() const {
-    return mEnv->GetFloatField(mAxis, gAxisClassInfo.mStyleValue);
-}
-
-void init_FontUtils(JNIEnv* env) {
-    jclass listClass = FindClassOrDie(env, "java/util/List");
-    gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;");
-    gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I");
-
-    jclass axisClass = FindClassOrDie(env, "android/graphics/FontListParser$Axis");
-    gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "tag", "I");
-    gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "styleValue", "F");
-}
-
-}  // namespace android
diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h
deleted file mode 100644
index 6fbd5e3..0000000
--- a/core/jni/android/graphics/FontUtils.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _ANDROID_GRAPHICS_FONT_UTILS_H_
-#define _ANDROID_GRAPHICS_FONT_UTILS_H_
-
-#include <jni.h>
-
-namespace android {
-
-// Utility wrapper for java.util.List
-class ListHelper {
-public:
-  ListHelper(JNIEnv* env, jobject list) : mEnv(env), mList(list) {}
-
-  jint size() const;
-  jobject get(jint index) const;
-
-private:
-  JNIEnv* mEnv;
-  jobject mList;
-};
-
-// Utility wrapper for android.graphics.FontListParser$Axis
-class AxisHelper {
-public:
-  AxisHelper(JNIEnv* env, jobject axis) : mEnv(env), mAxis(axis) {}
-
-  jint getTag() const;
-  jfloat getStyleValue() const;
-
-private:
-  JNIEnv* mEnv;
-  jobject mAxis;
-};
-
-void init_FontUtils(JNIEnv* env);
-
-}; // namespace android
-
-#endif  // _ANDROID_GRAPHICS_FONT_UTILS_H_
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index 0a0fce3e..c920b8d 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -17,14 +17,12 @@
 #include "jni.h"
 #include "core_jni_helpers.h"
 
-#include "FontUtils.h"
 #include "GraphicsJNI.h"
 #include "ScopedPrimitiveArray.h"
 #include "SkTypeface.h"
 #include <android_runtime/android_util_AssetManager.h>
 #include <androidfw/AssetManager.h>
 #include <hwui/Typeface.h>
-#include <minikin/FontFamily.h>
 
 using namespace android;
 
@@ -42,23 +40,6 @@
     return reinterpret_cast<jlong>(face);
 }
 
-static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
-        jobject listOfAxis) {
-    std::vector<minikin::FontVariation> variations;
-    ListHelper list(env, listOfAxis);
-    for (jint i = 0; i < list.size(); i++) {
-        jobject axisObject = list.get(i);
-        if (axisObject == nullptr) {
-            continue;
-        }
-        AxisHelper axis(env, axisObject);
-        variations.push_back(minikin::FontVariation(axis.getTag(), axis.getStyleValue()));
-    }
-    Typeface* baseTypeface = reinterpret_cast<Typeface*>(familyHandle);
-    Typeface* result = Typeface::createFromTypefaceWithVariation(baseTypeface, variations);
-    return reinterpret_cast<jlong>(result);
-}
-
 static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
     Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
     Typeface* face = Typeface::createWeightAlias(family, weight);
@@ -96,8 +77,6 @@
 
 static const JNINativeMethod gTypefaceMethods[] = {
     { "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
-    { "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
-            (void*)Typeface_createFromTypefaceWithVariation },
     { "nativeCreateWeightAlias",  "(JI)J", (void*)Typeface_createWeightAlias },
     { "nativeUnref",              "(J)V",  (void*)Typeface_unref },
     { "nativeGetStyle",           "(J)I",  (void*)Typeface_getStyle },
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index d75d5c1..3eccc42 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -88,6 +88,7 @@
         return;
     }
 
+    node->setStagingDisplayList(nullptr, nullptr);
     // Update the valid field, since native has already removed
     // the staging DisplayList
     env->SetBooleanField(jnode, gRenderNode_validFieldID, false);
diff --git a/core/proto/android/service/diskstats.proto b/core/proto/android/service/diskstats.proto
new file mode 100644
index 0000000..4d86526
--- /dev/null
+++ b/core/proto/android/service/diskstats.proto
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package android.service.diskstats;
+
+option java_multiple_files = true;
+option java_outer_classname = "DiskStatsServiceProto";
+
+message DiskStatsServiceDumpProto {
+    enum EncryptionType {
+        // Unknown encryption type
+        ENCRYPTION_UNKNOWN = 0;
+        // No encryption
+        ENCRYPTION_NONE = 1;
+        // Full disk encryption
+        ENCRYPTION_FULL_DISK = 2;
+        // File-based encryption
+        ENCRYPTION_FILE_BASED = 3;
+    }
+    // Whether the latency test resulted in an error
+    bool has_test_error = 1;
+    // If the test errored, error message is contained here
+    string error_message = 2;
+    // 512B write latency in milliseconds, if the test was successful
+    int32 write_512b_latency_millis = 3;
+    // Free Space in the major partitions
+    repeated DiskStatsFreeSpaceProto partitions_free_space = 4;
+    // Is the device using file-based encryption, full disk encryption or other
+    EncryptionType encryption = 5;
+    // Cached values of folder sizes, etc.
+    DiskStatsCachedValuesProto cached_folder_sizes = 6;
+}
+
+message DiskStatsCachedValuesProto {
+    // Total app data size, in kilobytes
+    int64 agg_apps_size = 1;
+    // Total app cache size, in kilobytes
+    int64 agg_apps_cache_size = 2;
+    // Size of image files, in kilobytes
+    int64 photos_size = 3;
+    // Size of video files, in kilobytes
+    int64 videos_size = 4;
+    // Size of audio files, in kilobytes
+    int64 audio_size = 5;
+    // Size of downloads, in kilobytes
+    int64 downloads_size = 6;
+    // Size of system directory, in kilobytes
+    int64 system_size = 7;
+    // Size of other files, in kilobytes
+    int64 other_size = 8;
+    // Sizes of individual packages
+    repeated DiskStatsAppSizesProto app_sizes = 9;
+}
+
+message DiskStatsAppSizesProto {
+    // Name of the package
+    string package_name = 1;
+    // App's data size in kilobytes
+    int64 app_size = 2;
+    // App's cache size in kilobytes
+    int64 cache_size = 3;
+}
+
+message DiskStatsFreeSpaceProto {
+    enum Folder {
+        // Data folder
+        FOLDER_DATA = 0;
+        // Cache folder
+        FOLDER_CACHE = 1;
+        // System folder
+        FOLDER_SYSTEM = 2;
+    }
+    // Which folder?
+    Folder folder = 1;
+    // Available space, in kilobytes
+    int64 available_space = 2;
+    // Total space, in kilobytes
+    int64 total_space = 3;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 84b03d2..db846c8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -801,6 +801,16 @@
         android:description="@string/permdesc_callPhone"
         android:protectionLevel="dangerous" />
 
+    <!-- Allows an application to manage its own calls, but rely on the system to route focus to the
+         currently active call.
+        <p>Protection level: dangerous
+    -->
+    <permission android:name="android.permission.MANAGE_OWN_CALLS"
+        android:permissionGroup="android.permission-group.PHONE"
+        android:label="@string/permlab_manageOwnCalls"
+        android:description="@string/permdesc_manageOwnCalls"
+        android:protectionLevel="dangerous" />
+
     <!-- Allows an application to access the IMS call service: making and
          modifying a call
         <p>Protection level: signature|privileged
@@ -1259,7 +1269,7 @@
          recommendations and scores from the NetworkScoreService.
          <p>Not for use by third-party applications. @hide -->
     <permission android:name="android.permission.REQUEST_NETWORK_SCORES"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|setup" />
 
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
@@ -2470,14 +2480,14 @@
         android:protectionLevel="signature" />
 
     <!-- Allows an application to request installing packages. Apps
-         targeting APIs greater than 22 must hold this permission in
+         targeting APIs greater than 25 must hold this permission in
          order to use {@link android.content.Intent#ACTION_INSTALL_PACKAGE}.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
         android:label="@string/permlab_requestInstallPackages"
         android:description="@string/permdesc_requestInstallPackages"
-        android:protectionLevel="normal" />
+        android:protectionLevel="signature|appop" />
 
     <!-- @SystemApi Allows an application to install packages.
     <p>Not for use by third-party applications. -->
diff --git a/core/res/res/layout/preference_widget_seekbar.xml b/core/res/res/layout/preference_widget_seekbar.xml
index 05daa1a..0c6dbf1 100644
--- a/core/res/res/layout/preference_widget_seekbar.xml
+++ b/core/res/res/layout/preference_widget_seekbar.xml
@@ -50,7 +50,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
-            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textAppearance="?android:attr/textAppearanceLarge"
             android:ellipsize="marquee"
             android:fadingEdge="horizontal" />
 
diff --git a/core/res/res/layout/preference_widget_seekbar_material.xml b/core/res/res/layout/preference_widget_seekbar_material.xml
index f70a472..6c72c9e 100644
--- a/core/res/res/layout/preference_widget_seekbar_material.xml
+++ b/core/res/res/layout/preference_widget_seekbar_material.xml
@@ -51,7 +51,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:singleLine="true"
-            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textAppearance="?android:attr/textAppearanceListItem"
             android:ellipsize="marquee"
             android:fadingEdge="horizontal" />
 
@@ -60,7 +60,7 @@
             android:layout_height="wrap_content"
             android:layout_below="@android:id/title"
             android:layout_alignStart="@android:id/title"
-            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
             android:textColor="?android:attr/textColorSecondary"
             android:maxLines="4" />
 
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a5c1a94..a401314 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2890,7 +2890,7 @@
         <attr name="forceHasOverlappingRendering" format="boolean" />
 
         <!-- Defines text displayed in a small popup window on hover or long press. -->
-        <attr name="tooltip" format="string" localization="suggested" />
+        <attr name="tooltipText" format="string" localization="suggested" />
 
         <!-- Whether this view is a root of a keyboard navigation cluster.
              See {@link android.view.View#setKeyboardNavigationCluster(boolean)}. -->
@@ -7029,7 +7029,7 @@
         <attr name="contentDescription" format="string" />
 
         <!-- The tooltip text associated with the item. -->
-        <attr name="tooltip" format="string" />
+        <attr name="tooltipText" format="string" />
 
     </declare-styleable>
 
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b961394..6a4711a8 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -776,6 +776,21 @@
         <enum name="locked" value="14" />
     </attr>
 
+    <!-- Specify the configuration changes that trigger the system to restart the
+         current activity if any of these configuration changes happen in the system.
+         The valid configuration changes include mcc and mnc which are the same with
+         those in configChanges. By default from Android O, we don't restart the activity
+         even the app doesn't specify mcc or mnc in configChanges. If the app wants to
+         restart, specify them in restartOnConfigChanges. -->
+    <attr name="restartOnConfigChanges">
+        <!-- The IMSI MCC has changed, that is a SIM has been detected and
+             updated the Mobile Country Code. -->
+        <flag name="mcc" value="0x0001" />
+        <!-- The IMSI MNC has changed, that is a SIM has been detected and
+             updated the Mobile Network Code. -->
+        <flag name="mnc" value="0x0002" />
+    </attr>
+
     <!-- Specify one or more configuration changes that the activity will
          handle itself.  If not specified, the activity will be restarted
          if any of these configuration changes happen in the system.  Otherwise,
@@ -793,10 +808,16 @@
          include/utils/ResourceTypes.h. -->
     <attr name="configChanges">
         <!-- The IMSI MCC has changed, that is a SIM has been detected and
-             updated the Mobile Country Code. -->
+             updated the Mobile Country Code. By default from Android O, we
+             don't restart the activity even the app doesn't specify mcc in
+             configChanges. If the app wants to restart, specify mcc in
+             restartOnConfigChanges. -->
         <flag name="mcc" value="0x0001" />
         <!-- The IMSI MNC has changed, that is a SIM has been detected and
-             updated the Mobile Network Code. -->
+             updated the Mobile Network Code. By default from Android O, we
+             don't restart the activity even the app doesn't specify mnc in
+             configChanges. If the app wants to restart, specify mnc in
+             restartOnConfigChanges. -->
         <flag name="mnc" value="0x0002" />
         <!-- The locale has changed, that is the user has selected a new
              language that text should be displayed in. -->
@@ -843,6 +864,9 @@
         <flag name="density" value="0x1000" />
         <!-- The layout direction has changed. For example going from LTR to RTL. -->
         <flag name="layoutDirection" value="0x2000" />
+        <!-- The colorimetry capabilities of the screen have changed (color gamut
+             or dynamic range). -->
+        <flag name="colorimetry" value="0x4000" />
         <!-- The font scaling factor has changed, that is the user has
              selected a new global font size. -->
         <flag name="fontScale" value="0x40000000" />
@@ -1917,6 +1941,7 @@
         <attr name="launchMode" />
         <attr name="screenOrientation" />
         <attr name="configChanges" />
+        <attr name="restartOnConfigChanges" />
         <attr name="permission" />
         <attr name="multiprocess" />
         <attr name="process" />
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 8f0350a..e2498df7 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -20,11 +20,14 @@
     <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_device_default_settings_light">@color/primary_material_settings_light</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="primary_dark_device_default_settings_light">@color/primary_dark_material_settings_light</color>
 
     <color name="secondary_device_default_settings">@color/secondary_material_settings</color>
+    <color name="secondary_device_default_settings_light">@color/secondary_material_settings_light</color>
     <color name="tertiary_device_default_settings">@color/tertiary_material_settings</color>
     <color name="quaternary_device_default_settings">@color/quaternary_material_settings</color>
 
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 835b8b60..db89c22 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -27,12 +27,15 @@
     <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_material_settings_light">@color/material_grey_100</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="primary_dark_material_settings_light">@color/material_grey_300</color>
 
     <color name="secondary_material_settings">@color/material_blue_grey_800</color>
+    <color name="secondary_material_settings_light">@color/material_grey_200</color>
     <color name="tertiary_material_settings">@color/material_blue_grey_700</color>
     <color name="quaternary_material_settings">@color/material_blue_grey_200</color>
 
@@ -88,6 +91,7 @@
     <color name="material_grey_800">#ff424242</color>
     <color name="material_grey_600">#ff757575</color>
     <color name="material_grey_300">#ffe0e0e0</color>
+    <color name="material_grey_200">#ffeeeeee</color>
     <color name="material_grey_100">#fff5f5f5</color>
     <color name="material_grey_50">#fffafafa</color>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 099fe08..ad9e4d9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2764,7 +2764,7 @@
         <public name="fontStyle" />
         <public name="font" />
         <public name="fontWeight" />
-        <public name="tooltip" />
+        <public name="tooltipText" />
         <public name="autoSizeText" />
         <public name="autoSizeStepGranularity" />
         <public name="autoSizeStepSizeSet" />
@@ -2785,6 +2785,7 @@
         <public name="appCategory" />
         <public name="autoSizeMaxTextSize" />
         <public name="supportsDismissingWindow" />
+        <public name="restartOnConfigChanges" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0204e93..3d497cc 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -397,7 +397,7 @@
     <string name="network_logging_notification_title">Network traffic is being monitored</string>
     <!-- Content text for a notification. Tapping opens a dialog with more information on network
         logging. [CHAR LIMIT=NONE]-->
-    <string name="network_logging_notification_text">Tap for more details</string>
+    <string name="network_logging_notification_text">Tap to learn more</string>
 
     <!-- Factory reset warning dialog strings--> <skip />
     <!-- Shows up in the dialog's title to warn about an impeding factory reset. [CHAR LIMIT=NONE] -->
@@ -1019,6 +1019,14 @@
       phone number and device IDs, whether a call is active, and the remote number
       connected by a call.</string>
 
+    <!-- Title of an application permission.  When granted the user is giving access to a third
+         party app to route its calls through the system. -->
+    <string name="permlab_manageOwnCalls">route calls through the system</string>
+    <!-- Description of an application permission.  When granted the user is giving access to a
+         third party app to route its calls through the system. -->
+    <string name="permdesc_manageOwnCalls">Allows the app to route its calls through the system in
+        order to improve the calling experience.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_readPhoneNumber">read phone number</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 842b575..faf451b 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1290,7 +1290,7 @@
     <style name="Widget.ActionButton.Overflow">
         <item name="src">@drawable/ic_menu_more</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
-        <item name="tooltip">@string/action_menu_overflow_description</item>
+        <item name="tooltipText">@string/action_menu_overflow_description</item>
     </style>
 
     <style name="Widget.ActionButton.CloseMode">
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index 12b8164..dc32b26 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -660,7 +660,7 @@
         <item name="src">@drawable/ic_menu_moreoverflow_holo_dark</item>
         <item name="background">?attr/actionBarItemBackground</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
-        <item name="tooltip">@string/action_menu_overflow_description</item>
+        <item name="tooltipText">@string/action_menu_overflow_description</item>
     </style>
 
     <style name="Widget.Holo.ActionButton.TextButton" parent="Widget.Holo.ButtonBar.Button" />
@@ -995,7 +995,7 @@
     <style name="Widget.Holo.Light.ActionButton.Overflow">
         <item name="src">@drawable/ic_menu_moreoverflow_holo_light</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
-        <item name="tooltip">@string/action_menu_overflow_description</item>
+        <item name="tooltipText">@string/action_menu_overflow_description</item>
     </style>
 
     <style name="Widget.Holo.Light.ActionBar.TabView" parent="Widget.Holo.ActionBar.TabView" />
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 709200e..0b326e9 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -944,7 +944,7 @@
         <item name="src">@drawable/ic_menu_moreoverflow_material</item>
         <item name="background">?attr/actionBarItemBackground</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
-        <item name="tooltip">@string/action_menu_overflow_description</item>
+        <item name="tooltipText">@string/action_menu_overflow_description</item>
         <item name="minWidth">@dimen/action_button_min_width_overflow_material</item>
         <item name="minHeight">@dimen/action_button_min_height_material</item>
         <item name="paddingStart">@dimen/action_bar_overflow_padding_start_material</item>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 6bd6e1c..5961cb0 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -736,20 +736,12 @@
     <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
     <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="colorSecondary">@color/secondary_device_default_settings</item>
+        <item name="colorPrimary">@color/primary_device_default_settings_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
+        <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
     </style>
 
-    <!-- @hide DeviceDefault theme that should look like the Settings app. The action bar will use a
-         light background and accent color for text and icon. -->
-    <style name="Theme.DeviceDefault.Settings.LightActionBar">
-        <!-- ActionBar -->
-        <item name="actionBarTheme">@style/ThemeOverlay.DeviceDefault.ActionBar.Accent</item>
-        <item name="actionBarStyle">@style/Widget.DeviceDefault.Light.ActionBar</item>
-    </style>
-
     <!-- @hide DeviceDefault theme for a window that should use Settings theme colors
          but has a full dark palette. ONLY USED FOR QUICK SETTINGS THEME -->
     <style name="Theme.DeviceDefault.QuickSettings" parent="Theme.Material">
@@ -817,12 +809,6 @@
 
     <style name="ThemeOverlay.DeviceDefault" />
 
-    <!-- @hide Theme overlay that inherits from material actionbar,  and use accent color for
-             primary text -->
-    <style name="ThemeOverlay.DeviceDefault.ActionBar.Accent" parent="ThemeOverlay.Material.ActionBar">
-        <item name="textColorPrimary">@color/btn_colored_borderless_text_material</item>
-    </style>
-
     <style name="ThemeOverlay.DeviceDefault.Accent">
         <item name="colorAccent">@color/accent_device_default_dark</item>
     </style>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index d0f202b..3587fec 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1323,10 +1323,10 @@
     </style>
 
     <!-- Default theme for Settings and activities launched from Settings. -->
-    <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
-        <item name="colorPrimary">@color/primary_material_settings</item>
-        <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
-        <item name="colorSecondary">@color/secondary_material_settings</item>
+    <style name="Theme.Material.Settings" parent="Theme.Material.Light.LightStatusBar">
+        <item name="colorPrimary">@color/primary_material_settings_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_material_settings_light</item>
+        <item name="colorSecondary">@color/secondary_material_settings_light</item>
 
         <item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
         <item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
diff --git a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
new file mode 100644
index 0000000..f60bf94
--- /dev/null
+++ b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+
+import junit.framework.TestCase;
+
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static android.os.storage.VolumeInfo.STATE_MOUNTED;
+import static android.os.storage.VolumeInfo.STATE_UNMOUNTED;
+
+public class ApplicationPackageManagerTest extends TestCase {
+    private static final String sInternalVolPath = "/data";
+    private static final String sAdoptedVolPath = "/mnt/expand/123";
+    private static final String sPublicVolPath = "/emulated";
+    private static final String sPrivateUnmountedVolPath = "/private";
+
+    private static final String sInternalVolUuid = null; //StorageManager.UUID_PRIVATE_INTERNAL
+    private static final String sAdoptedVolUuid = "adopted";
+    private static final String sPublicVolUuid = "emulated";
+    private static final String sPrivateUnmountedVolUuid = "private";
+
+    private static final VolumeInfo sInternalVol = new VolumeInfo("private",
+            VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/);
+
+    private static final VolumeInfo sAdoptedVol = new VolumeInfo("adopted",
+            VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/);
+
+    private static final VolumeInfo sPublicVol = new VolumeInfo("public",
+            VolumeInfo.TYPE_PUBLIC, null /*DiskInfo*/, null /*partGuid*/);
+
+    private static final VolumeInfo sPrivateUnmountedVol = new VolumeInfo("private2",
+            VolumeInfo.TYPE_PRIVATE, null /*DiskInfo*/, null /*partGuid*/);
+
+    private static final List<VolumeInfo> sVolumes = new ArrayList<>();
+
+    static {
+        sInternalVol.path = sInternalVolPath;
+        sInternalVol.state = STATE_MOUNTED;
+        sInternalVol.fsUuid = sInternalVolUuid;
+
+        sAdoptedVol.path = sAdoptedVolPath;
+        sAdoptedVol.state = STATE_MOUNTED;
+        sAdoptedVol.fsUuid = sAdoptedVolUuid;
+
+        sPublicVol.state = STATE_MOUNTED;
+        sPublicVol.path = sPublicVolPath;
+        sPublicVol.fsUuid = sPublicVolUuid;
+
+        sPrivateUnmountedVol.state = STATE_UNMOUNTED;
+        sPrivateUnmountedVol.path = sPrivateUnmountedVolPath;
+        sPrivateUnmountedVol.fsUuid = sPrivateUnmountedVolUuid;
+
+        sVolumes.add(sInternalVol);
+        sVolumes.add(sAdoptedVol);
+        sVolumes.add(sPublicVol);
+        sVolumes.add(sPrivateUnmountedVol);
+    }
+
+    private static final class MockedApplicationPackageManager extends ApplicationPackageManager {
+        private boolean mForceAllowOnExternal = false;
+        private boolean mAllow3rdPartyOnInternal = true;
+
+        public MockedApplicationPackageManager() {
+            super(null, null);
+        }
+
+        public void setForceAllowOnExternal(boolean forceAllowOnExternal) {
+            mForceAllowOnExternal = forceAllowOnExternal;
+        }
+
+        public void setAllow3rdPartyOnInternal(boolean allow3rdPartyOnInternal) {
+            mAllow3rdPartyOnInternal = allow3rdPartyOnInternal;
+        }
+
+        @Override
+        public boolean isForceAllowOnExternal(Context context) {
+            return mForceAllowOnExternal;
+        }
+
+        @Override
+        public boolean isAllow3rdPartyOnInternal(Context context) {
+            return mAllow3rdPartyOnInternal;
+        }
+    }
+
+    private StorageManager getMockedStorageManager() {
+        StorageManager storageManager = Mockito.mock(StorageManager.class);
+        Mockito.when(storageManager.getVolumes()).thenReturn(sVolumes);
+        Mockito.when(storageManager.findVolumeById(VolumeInfo.ID_PRIVATE_INTERNAL))
+                .thenReturn(sInternalVol);
+        Mockito.when(storageManager.findVolumeByUuid(sAdoptedVolUuid))
+                .thenReturn(sAdoptedVol);
+        Mockito.when(storageManager.findVolumeByUuid(sPublicVolUuid))
+                .thenReturn(sPublicVol);
+        Mockito.when(storageManager.findVolumeByUuid(sPrivateUnmountedVolUuid))
+                .thenReturn(sPrivateUnmountedVol);
+        return storageManager;
+    }
+
+    private void verifyReturnedVolumes(List<VolumeInfo> actualVols, VolumeInfo... exptectedVols) {
+        boolean failed = false;
+        if (actualVols.size() != exptectedVols.length) {
+            failed = true;
+        } else {
+            for (VolumeInfo vol : exptectedVols) {
+                if (!actualVols.contains(vol)) {
+                    failed = true;
+                    break;
+                }
+            }
+        }
+
+        if (failed) {
+            fail("Wrong volumes returned.\n Expected: " + Arrays.toString(exptectedVols)
+                    + "\n Actual: " + Arrays.toString(actualVols.toArray()));
+        }
+    }
+
+    public void testGetCandidateVolumes_systemApp() throws Exception {
+        ApplicationInfo sysAppInfo = new ApplicationInfo();
+        sysAppInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+
+        StorageManager storageManager = getMockedStorageManager();
+        IPackageManager pm = Mockito.mock(IPackageManager.class);
+
+        MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+
+        appPkgMgr.setAllow3rdPartyOnInternal(true);
+        appPkgMgr.setForceAllowOnExternal(true);
+        List<VolumeInfo> candidates =
+                appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm);
+        verifyReturnedVolumes(candidates, sInternalVol);
+
+        appPkgMgr.setAllow3rdPartyOnInternal(true);
+        appPkgMgr.setForceAllowOnExternal(false);
+        candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm);
+        verifyReturnedVolumes(candidates, sInternalVol);
+
+        appPkgMgr.setAllow3rdPartyOnInternal(false);
+        appPkgMgr.setForceAllowOnExternal(false);
+        candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm);
+        verifyReturnedVolumes(candidates, sInternalVol);
+
+        appPkgMgr.setAllow3rdPartyOnInternal(false);
+        appPkgMgr.setForceAllowOnExternal(true);
+        candidates = appPkgMgr.getPackageCandidateVolumes(sysAppInfo, storageManager, pm);
+        verifyReturnedVolumes(candidates, sInternalVol);
+    }
+
+    public void testGetCandidateVolumes_3rdParty_internalOnly() throws Exception {
+        ApplicationInfo appInfo = new ApplicationInfo();
+        StorageManager storageManager = getMockedStorageManager();
+
+        IPackageManager pm = Mockito.mock(IPackageManager.class);
+        Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(false);
+
+        MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+
+        // must allow 3rd party on internal, otherwise the app wouldn't have been installed before.
+        appPkgMgr.setAllow3rdPartyOnInternal(true);
+
+        // INSTALL_LOCATION_INTERNAL_ONLY AND INSTALL_LOCATION_UNSPECIFIED are treated the same.
+        int[] locations = {PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY,
+                PackageInfo.INSTALL_LOCATION_UNSPECIFIED};
+
+        for (int location : locations) {
+            appInfo.installLocation = location;
+            appPkgMgr.setForceAllowOnExternal(true);
+            List<VolumeInfo> candidates = appPkgMgr.getPackageCandidateVolumes(
+                    appInfo, storageManager, pm);
+            verifyReturnedVolumes(candidates, sInternalVol, sAdoptedVol);
+
+            appPkgMgr.setForceAllowOnExternal(false);
+            candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm);
+            verifyReturnedVolumes(candidates, sInternalVol);
+        }
+    }
+
+    public void testGetCandidateVolumes_3rdParty_auto() throws Exception {
+        ApplicationInfo appInfo = new ApplicationInfo();
+        StorageManager storageManager = getMockedStorageManager();
+
+        IPackageManager pm = Mockito.mock(IPackageManager.class);
+
+        MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+        appPkgMgr.setForceAllowOnExternal(true);
+
+        // INSTALL_LOCATION_AUTO AND INSTALL_LOCATION_PREFER_EXTERNAL are treated the same.
+        int[] locations = {PackageInfo.INSTALL_LOCATION_AUTO,
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL};
+
+        for (int location : locations) {
+            appInfo.installLocation = location;
+            appInfo.flags = 0;
+
+            appInfo.volumeUuid = sInternalVolUuid;
+            Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(false);
+            appPkgMgr.setAllow3rdPartyOnInternal(true);
+            List<VolumeInfo> candidates = appPkgMgr.getPackageCandidateVolumes(
+                    appInfo, storageManager, pm);
+            verifyReturnedVolumes(candidates, sInternalVol, sAdoptedVol);
+
+            appInfo.volumeUuid = sInternalVolUuid;
+            appPkgMgr.setAllow3rdPartyOnInternal(true);
+            Mockito.when(pm.isPackageDeviceAdminOnAnyUser(Mockito.anyString())).thenReturn(true);
+            candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm);
+            verifyReturnedVolumes(candidates, sInternalVol);
+
+            appInfo.flags = ApplicationInfo.FLAG_EXTERNAL_STORAGE;
+            appInfo.volumeUuid = sAdoptedVolUuid;
+            appPkgMgr.setAllow3rdPartyOnInternal(false);
+            candidates = appPkgMgr.getPackageCandidateVolumes(appInfo, storageManager, pm);
+            verifyReturnedVolumes(candidates, sAdoptedVol);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
index 2a3c22c..ca4141a 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java
@@ -215,4 +215,46 @@
         // DEV: Released API 20
         verifyComputeTargetSdkVersion(NEWER_VERSION, NEWER_PRE_RELEASE, true, -1);
     }
+
+    /**
+     * Unit test for PackageParser.getActivityConfigChanges().
+     * If the bit is 1 in the original configChanges, it is still 1 in the final configChanges.
+     * If the bit is 0 in the original configChanges and the bit is not set to 1 in
+     * restartOnConfigChanges, the bit is changed to 1 in the final configChanges by default.
+     */
+    @Test
+    public void testGetActivityConfigChanges() {
+        // Not set in either configChanges or restartOnConfigChanges.
+        int configChanges = 0x0000; // 00000000.
+        int restartOnConfigChanges = 0x0000; // 00000000.
+        int finalConfigChanges =
+                PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+        assertEquals(0x0003, finalConfigChanges); // Should be 00000011.
+
+        // Not set in configChanges, but set in restartOnConfigChanges.
+        configChanges = 0x0000; // 00000000.
+        restartOnConfigChanges = 0x0003; // 00000011.
+        finalConfigChanges =
+                PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+        assertEquals(0x0000, finalConfigChanges); // Should be 00000000.
+
+        // Set in configChanges.
+        configChanges = 0x0003; // 00000011.
+        restartOnConfigChanges = 0X0000; // 00000000.
+        finalConfigChanges =
+                PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+        assertEquals(0x0003, finalConfigChanges); // Should be 00000011.
+
+        restartOnConfigChanges = 0x0003; // 00000011.
+        finalConfigChanges =
+                PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+        assertEquals(0x0003, finalConfigChanges); // Should still be 00000011.
+
+        // Other bit set in configChanges.
+        configChanges = 0x0080; // 10000000, orientation.
+        restartOnConfigChanges = 0x0000; // 00000000.
+        finalConfigChanges =
+                PackageParser.getActivityConfigChanges(configChanges, restartOnConfigChanges);
+        assertEquals(0x0083, finalConfigChanges); // Should be 10000011.
+    }
 }
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 29020ba..5bfff26 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -169,25 +169,6 @@
         assertNull(activeScorer);
     }
 
-    public void testIsCallerActiveScorer_providerNotAvailable() throws Exception {
-        ContentResolver cr = mTargetContext.getContentResolver();
-        Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
-        assertFalse(mNetworkScorerAppManager.isCallerActiveScorer(924));
-    }
-
-    public void testIsCallerActiveScorer_providerAvailable() throws Exception {
-        setNetworkRecommendationPackageNames("package1");
-        mockScoreNetworksGranted("package1");
-        mockRecommendationServiceAvailable("package1", 924 /* packageUid */);
-
-        ContentResolver cr = mTargetContext.getContentResolver();
-        Settings.Global.putInt(cr, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 1);
-
-        assertTrue(mNetworkScorerAppManager.isCallerActiveScorer(924));
-        assertFalse(mNetworkScorerAppManager.isCallerActiveScorer(925));
-    }
-
     private void setNetworkRecommendationPackageNames(String... names) {
         if (names == null) {
             names = new String[0];
diff --git a/core/tests/coretests/src/android/net/RecommendationRequestTest.java b/core/tests/coretests/src/android/net/RecommendationRequestTest.java
index 39c1691..bd25500 100644
--- a/core/tests/coretests/src/android/net/RecommendationRequestTest.java
+++ b/core/tests/coretests/src/android/net/RecommendationRequestTest.java
@@ -3,6 +3,7 @@
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.os.Parcel;
+import android.os.SystemClock;
 import android.test.AndroidTestCase;
 
 public class RecommendationRequestTest extends AndroidTestCase {
@@ -10,6 +11,8 @@
     private WifiConfiguration mDefaultConfig;
     private WifiConfiguration mConnectedConfig;
     private WifiConfiguration[] mConnectableConfigs;
+    private int mLastSelectedNetworkId;
+    private long mLastSelectedNetworkTimestamp;
 
     @Override
     public void setUp() throws Exception {
@@ -35,6 +38,8 @@
         mConnectedConfig = new WifiConfiguration();
         mConnectedConfig.SSID = "connected_config";
         mConnectableConfigs = new WifiConfiguration[] {mDefaultConfig, mConnectedConfig};
+        mLastSelectedNetworkId = 5;
+        mLastSelectedNetworkTimestamp = SystemClock.elapsedRealtime();
     }
 
     public void testParceling() throws Exception {
@@ -43,6 +48,7 @@
                 .setScanResults(mScanResults)
                 .setConnectedWifiConfig(mConnectedConfig)
                 .setConnectableConfigs(mConnectableConfigs)
+                .setLastSelectedNetwork(mLastSelectedNetworkId, mLastSelectedNetworkTimestamp)
                 .build();
 
         RecommendationRequest parceled = passThroughParcel(request);
@@ -60,6 +66,8 @@
         for (int i = 0; i < parceledConfigs.length; i++) {
             assertEquals(mConnectableConfigs[i].SSID, parceledConfigs[i].SSID);
         }
+        assertEquals(mLastSelectedNetworkId, parceled.getLastSelectedNetworkId());
+        assertEquals(mLastSelectedNetworkTimestamp, parceled.getLastSelectedNetworkTimestamp());
     }
 
     public void testParceling_nullScanResults() throws Exception {
@@ -82,6 +90,16 @@
         assertNull(parceledConfigs);
     }
 
+    public void testParceling_unsetLastSelectedNetwork() throws Exception {
+        RecommendationRequest request = new RecommendationRequest.Builder()
+                .build();
+
+        RecommendationRequest parceled = passThroughParcel(request);
+
+        assertEquals(0, parceled.getLastSelectedNetworkId());
+        assertEquals(0, parceled.getLastSelectedNetworkTimestamp());
+    }
+
     private RecommendationRequest passThroughParcel(RecommendationRequest request) {
         Parcel p = Parcel.obtain();
         RecommendationRequest output = null;
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index 6718259..b2c6840 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -18,6 +18,14 @@
 
 ########################
 include $(CLEAR_VARS)
+LOCAL_MODULE := framework-sysconfig.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/sysconfig
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
 LOCAL_MODULE := platform.xml
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
@@ -31,4 +39,3 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
-
diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml
new file mode 100644
index 0000000..2f18de0
--- /dev/null
+++ b/data/etc/framework-sysconfig.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- These are configurations that must exist on all Android devices. -->
+<config>
+
+    <!-- Broadcast actions that are currently exempted from O+ background
+         delivery restrictions. -->
+    <allow-implicit-broadcast action="android.intent.action.SIM_STATE_CHANGED" />
+    <allow-implicit-broadcast action="android.intent.action.PACKAGE_CHANGED" />
+
+</config>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index 77e8d77..021a07e 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -565,6 +565,38 @@
 method, which indicates whether the screen is round.</p>
       </td>
     </tr>
+    <tr id="WideColorGamutQualifier">
+      <td>Wide Color Gamut</td>
+      <td>
+        <code>widecg</code><br/>
+        <code>nowidecg</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code widecg}: Displays with a wide color gamut such as Display P3 or AdobeRGB</li>
+          <li>{@code nowidecg}: Displays with a narrow color gamut such as sRGB</li>
+        </ul>
+        <p><em>Added in API level 26.</em></p>
+        <p>Also see the {@link android.content.res.Configuration#isScreenWideColorGamut()} configuration
+        method, which indicates whether the screen has a wide color gamut.</p>
+      </td>
+    </tr>
+    <tr id="HDRQualifier">
+      <td>High Dynamic Range (HDR)</td>
+      <td>
+        <code>highdr</code><br/>
+        <code>lowdr</code>
+      </td>
+      <td>
+        <ul class="nolist">
+          <li>{@code highdr}: Displays with a high-dynamic range</li>
+          <li>{@code lowdr}: Displays with a low/standard dynamic range</li>
+        </ul>
+        <p><em>Added in API level 26.</em></p>
+        <p>Also see the {@link android.content.res.Configuration#isScreenHdr()} configuration
+        method, which indicates whether the screen has a HDR capabilities.</p>
+      </td>
+    </tr>
     <tr id="OrientationQualifier">
       <td>Screen orientation</td>
       <td>
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 2733c43f..e48bf79 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -18,7 +18,6 @@
 
 import android.content.res.AssetManager;
 import android.util.Log;
-import dalvik.annotation.optimization.CriticalNative;
 
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -40,11 +39,11 @@
      */
     public long mNativePtr;
 
-    // Points native font family builder. Must be zero after freezing this family.
-    private long mBuilderPtr;
-
     public FontFamily() {
-        mBuilderPtr = nInitBuilder(null, 0);
+        mNativePtr = nCreateFamily(null, 0);
+        if (mNativePtr == 0) {
+            throw new IllegalStateException("error creating native FontFamily");
+        }
     }
 
     public FontFamily(String lang, String variant) {
@@ -54,15 +53,10 @@
         } else if ("elegant".equals(variant)) {
             varEnum = 2;
         }
-        mBuilderPtr = nInitBuilder(lang, varEnum);
-    }
-
-    public void freeze() {
-        if (mBuilderPtr == 0) {
-            throw new IllegalStateException("This FontFamily is already frozen");
+        mNativePtr = nCreateFamily(lang, varEnum);
+        if (mNativePtr == 0) {
+            throw new IllegalStateException("error creating native FontFamily");
         }
-        mNativePtr = nCreateFamily(mBuilderPtr);
-        mBuilderPtr = 0;
     }
 
     @Override
@@ -75,14 +69,11 @@
     }
 
     public boolean addFont(String path, int ttcIndex) {
-        if (mBuilderPtr == 0) {
-            throw new IllegalStateException("Unable to call addFont after freezing.");
-        }
         try (FileInputStream file = new FileInputStream(path)) {
             FileChannel fileChannel = file.getChannel();
             long fontSize = fileChannel.size();
             ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
-            return nAddFont(mBuilderPtr, fontBuffer, ttcIndex);
+            return nAddFont(mNativePtr, fontBuffer, ttcIndex);
         } catch (IOException e) {
             Log.e(TAG, "Error mapping font file " + path);
             return false;
@@ -91,29 +82,19 @@
 
     public boolean addFontWeightStyle(ByteBuffer font, int ttcIndex, List<FontListParser.Axis> axes,
             int weight, boolean style) {
-        if (mBuilderPtr == 0) {
-            throw new IllegalStateException("Unable to call addFontWeightStyle after freezing.");
-        }
-        return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, axes, weight, style);
+        return nAddFontWeightStyle(mNativePtr, font, ttcIndex, axes, weight, style);
     }
 
     public boolean addFontFromAsset(AssetManager mgr, String path) {
-        if (mBuilderPtr == 0) {
-            throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
-        }
-        return nAddFontFromAsset(mBuilderPtr, mgr, path);
+        return nAddFontFromAsset(mNativePtr, mgr, path);
     }
 
-    private static native long nInitBuilder(String lang, int variant);
-
-    @CriticalNative
-    private static native long nCreateFamily(long mBuilderPtr);
-
-    @CriticalNative
+    private static native long nCreateFamily(String lang, int variant);
     private static native void nUnrefFamily(long nativePtr);
-    private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex);
-    private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
+    private static native boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex);
+    private static native boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font,
             int ttcIndex, List<FontListParser.Axis> listOfAxis,
             int weight, boolean isItalic);
-    private static native boolean nAddFontFromAsset(long builderPtr, AssetManager mgr, String path);
+    private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr,
+            String path);
 }
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 5b53296..9490436 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -21,7 +21,6 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.annotation.Nullable;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.IOException;
@@ -105,12 +104,9 @@
     // Note that a well-formed variation contains a four-character tag and a float as styleValue,
     // with spacers in between. The tag is enclosd either by double quotes or single quotes.
     @VisibleForTesting
-    public static ArrayList<Axis> parseFontVariationSettings(@Nullable String settings) {
-        ArrayList<Axis> axisList = new ArrayList<>();
-        if (settings == null) {
-            return axisList;
-        }
+    public static Axis[] parseFontVariationSettings(String settings) {
         String[] settingList = settings.split(",");
+        ArrayList<Axis> axisList = new ArrayList<>();
         settingLoop:
         for (String setting : settingList) {
             int pos = 0;
@@ -154,7 +150,7 @@
                     tagString.charAt(3));
             axisList.add(new Axis(tag, styleValue));
         }
-        return axisList;
+        return axisList.toArray(new Axis[axisList.size()]);
     }
 
     @VisibleForTesting
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 4ee0c34..7815ae1 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -71,7 +71,6 @@
 
     private LocaleList  mLocales;
     private String      mFontFeatureSettings;
-    private String      mFontVariationSettings;
 
     private static final Object sCacheLock = new Object();
 
@@ -1495,37 +1494,6 @@
     }
 
     /**
-     * Returns the font variation settings.
-     *
-     * @return the paint's currently set font variation settings. Default is null.
-     *
-     * @see #setFontVariationSettings(String)
-     */
-    public String getFontVariationSettings() {
-        return mFontVariationSettings;
-    }
-
-    /**
-     * Set font variation settings.
-     *
-     * @param settings font variation settings, e.g. "'wdth' 300, 'wght' 1.8"
-     *
-     * @see #getFontVariationSettings()
-     *
-     * @param settings the font variation settings. You can pass null or empty string as no
-     *                 variation settings.
-     */
-    public void setFontVariationSettings(String settings) {
-        settings = TextUtils.nullIfEmpty(settings);
-        if (settings == mFontVariationSettings
-                || (settings != null && settings.equals(mFontVariationSettings))) {
-            return;
-        }
-        mFontVariationSettings = settings;
-        setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, settings));
-    }
-
-    /**
      * Get the current value of hyphen edit.
      *
      * @return the current hyphen edit value
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 166ef1b..2886f0d 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -21,7 +21,6 @@
 import android.util.LongSparseArray;
 import android.util.LruCache;
 import android.util.SparseArray;
-import android.graphics.FontListParser;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -172,15 +171,6 @@
         return typeface;
     }
 
-    /** @hide */
-    public static Typeface createFromTypefaceWithVariation(Typeface family,
-            String fontVariationSettings) {
-        final long ni = family == null ? 0 : family.native_instance;
-        ArrayList<FontListParser.Axis> axes =
-                FontListParser.parseFontVariationSettings(fontVariationSettings);
-        return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes));
-    }
-
     /**
      * Returns one of the default typeface objects, based on the specified style
      *
@@ -206,7 +196,6 @@
 
                 FontFamily fontFamily = new FontFamily();
                 if (fontFamily.addFontFromAsset(mgr, path)) {
-                    fontFamily.freeze();
                     FontFamily[] families = { fontFamily };
                     typeface = createFromFamiliesWithDefault(families);
                     sDynamicTypefaceCache.put(key, typeface);
@@ -256,7 +245,6 @@
         if (sFallbackFonts != null) {
             FontFamily fontFamily = new FontFamily();
             if (fontFamily.addFont(path, 0 /* ttcIndex */)) {
-                fontFamily.freeze();
                 FontFamily[] families = { fontFamily };
                 return createFromFamiliesWithDefault(families);
             }
@@ -327,7 +315,6 @@
                 Log.e(TAG, "Error creating font " + font.fontName + "#" + font.ttcIndex);
             }
         }
-        fontFamily.freeze();
         return fontFamily;
     }
 
@@ -453,8 +440,6 @@
     }
 
     private static native long nativeCreateFromTypeface(long native_instance, int style);
-    private static native long nativeCreateFromTypefaceWithVariation(
-            long native_instance, List<FontListParser.Axis> axes);
     private static native long nativeCreateWeightAlias(long native_instance, int weight);
     private static native void nativeUnref(long native_instance);
     private static native int  nativeGetStyle(long native_instance);
diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
index 23de416..d046c11 100644
--- a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
@@ -17,7 +17,6 @@
 package android.graphics;
 
 import android.test.suitebuilder.annotation.SmallTest;
-import java.util.List;
 import junit.framework.TestCase;
 
 
@@ -26,92 +25,92 @@
     @SmallTest
     public void testParseFontVariationSetting() {
         int tag = FontListParser.makeTag('w', 'd', 't', 'h');
-        List<FontListParser.Axis> axes = FontListParser.parseFontVariationSettings("'wdth' 1");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(1.0f, axes.get(0).styleValue);
+        FontListParser.Axis[] axis = FontListParser.parseFontVariationSettings("'wdth' 1");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(1.0f, axis[0].styleValue);
 
-        axes = FontListParser.parseFontVariationSettings("\"wdth\" 100");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(100.0f, axes.get(0).styleValue);
+        axis = FontListParser.parseFontVariationSettings("\"wdth\" 100");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(100.0f, axis[0].styleValue);
 
-        axes = FontListParser.parseFontVariationSettings("   'wdth' 100");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(100.0f, axes.get(0).styleValue);
+        axis = FontListParser.parseFontVariationSettings("   'wdth' 100");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(100.0f, axis[0].styleValue);
 
-        axes = FontListParser.parseFontVariationSettings("\t'wdth' 0.5");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(0.5f, axes.get(0).styleValue);
+        axis = FontListParser.parseFontVariationSettings("\t'wdth' 0.5");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(0.5f, axis[0].styleValue);
 
         tag = FontListParser.makeTag('A', 'X', ' ', ' ');
-        axes = FontListParser.parseFontVariationSettings("'AX  ' 1");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(1.0f, axes.get(0).styleValue);
+        axis = FontListParser.parseFontVariationSettings("'AX  ' 1");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(1.0f, axis[0].styleValue);
 
-        axes = FontListParser.parseFontVariationSettings("'AX  '\t1");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(1.0f, axes.get(0).styleValue);
+        axis = FontListParser.parseFontVariationSettings("'AX  '\t1");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(1.0f, axis[0].styleValue);
 
-        axes = FontListParser.parseFontVariationSettings("'AX  '\n1");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(1.0f, axes.get(0).styleValue);
+        axis = FontListParser.parseFontVariationSettings("'AX  '\n1");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(1.0f, axis[0].styleValue);
 
-        axes = FontListParser.parseFontVariationSettings("'AX  '\r1");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(1.0f, axes.get(0).styleValue);
+        axis = FontListParser.parseFontVariationSettings("'AX  '\r1");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(1.0f, axis[0].styleValue);
 
-        axes = FontListParser.parseFontVariationSettings("'AX  '\r\t\n 1");
-        assertEquals(tag, axes.get(0).tag);
-        assertEquals(1.0f, axes.get(0).styleValue);
+        axis = FontListParser.parseFontVariationSettings("'AX  '\r\t\n 1");
+        assertEquals(tag, axis[0].tag);
+        assertEquals(1.0f, axis[0].styleValue);
 
         // Test for invalid input
-        axes = FontListParser.parseFontVariationSettings("");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("invalid_form");
-        assertEquals(0, axes.size());
+        axis = FontListParser.parseFontVariationSettings("");
+        assertEquals(0, axis.length);
+        axis = FontListParser.parseFontVariationSettings("invalid_form");
+        assertEquals(0, axis.length);
 
         // Test with invalid tag
-        axes = FontListParser.parseFontVariationSettings("'' 1");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'invalid' 1");
-        assertEquals(0, axes.size());
+        axis = FontListParser.parseFontVariationSettings("'' 1");
+        assertEquals(0, axis.length);
+        axis = FontListParser.parseFontVariationSettings("'invalid' 1");
+        assertEquals(0, axis.length);
 
         // Test with invalid styleValue
-        axes = FontListParser.parseFontVariationSettings("'wdth' ");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'wdth' x");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'wdth' \t");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'wdth' \n\r");
-        assertEquals(0, axes.size());
+        axis = FontListParser.parseFontVariationSettings("'wdth' ");
+        assertEquals(0, axis.length);
+        axis = FontListParser.parseFontVariationSettings("'wdth' x");
+        assertEquals(0, axis.length);
+        axis = FontListParser.parseFontVariationSettings("'wdth' \t");
+        assertEquals(0, axis.length);
+        axis = FontListParser.parseFontVariationSettings("'wdth' \n\r");
+        assertEquals(0, axis.length);
     }
 
     @SmallTest
     public void testParseFontVariationStyleSettings() {
-        List<FontListParser.Axis> axes =
+        FontListParser.Axis[] axis =
                 FontListParser.parseFontVariationSettings("'wdth' 10,'AX  '\r1");
         int tag1 = FontListParser.makeTag('w', 'd', 't', 'h');
         int tag2 = FontListParser.makeTag('A', 'X', ' ', ' ');
-        assertEquals(tag1, axes.get(0).tag);
-        assertEquals(10.0f, axes.get(0).styleValue);
-        assertEquals(tag2, axes.get(1).tag);
-        assertEquals(1.0f, axes.get(1).styleValue);
+        assertEquals(tag1, axis[0].tag);
+        assertEquals(10.0f, axis[0].styleValue);
+        assertEquals(tag2, axis[1].tag);
+        assertEquals(1.0f, axis[1].styleValue);
 
         // Test only spacers are allowed before tag
-        axes = FontListParser.parseFontVariationSettings("     'wdth' 10,ab'wdth' 1");
+        axis = FontListParser.parseFontVariationSettings("     'wdth' 10,ab'wdth' 1");
         tag1 = FontListParser.makeTag('w', 'd', 't', 'h');
-        assertEquals(tag1, axes.get(0).tag);
-        assertEquals(10.0f, axes.get(0).styleValue);
-        assertEquals(1, axes.size());
+        assertEquals(tag1, axis[0].tag);
+        assertEquals(10.0f, axis[0].styleValue);
+        assertEquals(1, axis.length);
     }
 
     @SmallTest
     public void testInvalidTagCharacters() {
-        List<FontListParser.Axis> axes =
+        FontListParser.Axis[] axis =
                 FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10");
-        assertEquals(0, axes.size());
-        axes = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
-        assertEquals(0, axes.size());
+        assertEquals(0, axis.length);
+        axis = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
+        assertEquals(0, axis.length);
     }
 
     @SmallTest
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index d6b1cf1..bf7a779a 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -45,6 +45,7 @@
                 PURPOSE_DECRYPT,
                 PURPOSE_SIGN,
                 PURPOSE_VERIFY,
+                PURPOSE_WRAP_KEY,
                 })
     public @interface PurposeEnum {}
 
@@ -69,6 +70,12 @@
     public static final int PURPOSE_VERIFY = 1 << 3;
 
     /**
+     * Purpose of key: wrapping key for secure key import.
+     */
+    public static final int PURPOSE_WRAP_KEY = 1 << 4;
+
+
+    /**
      * @hide
      */
     public static abstract class Purpose {
@@ -84,6 +91,8 @@
                     return KeymasterDefs.KM_PURPOSE_SIGN;
                 case PURPOSE_VERIFY:
                     return KeymasterDefs.KM_PURPOSE_VERIFY;
+                case PURPOSE_WRAP_KEY:
+                    return KeymasterDefs.KM_PURPOSE_WRAP_KEY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
@@ -99,6 +108,8 @@
                     return PURPOSE_SIGN;
                 case KeymasterDefs.KM_PURPOSE_VERIFY:
                     return PURPOSE_VERIFY;
+                case KeymasterDefs.KM_PURPOSE_WRAP_KEY:
+                    return PURPOSE_WRAP_KEY;
                 default:
                     throw new IllegalArgumentException("Unknown purpose: " + purpose);
             }
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index a30c849..a4bcc62 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1907,6 +1907,8 @@
     if (diff != 0) return diff;
     diff = (int32_t)(screenLayout2 - o.screenLayout2);
     if (diff != 0) return diff;
+    diff = (int32_t)(colorimetry - o.colorimetry);
+    if (diff != 0) return diff;
     diff = (int32_t)(uiMode - o.uiMode);
     if (diff != 0) return diff;
     diff = (int32_t)(smallestScreenWidthDp - o.smallestScreenWidthDp);
@@ -1967,6 +1969,9 @@
     if (screenLayout2 != o.screenLayout2) {
         return screenLayout2 < o.screenLayout2 ? -1 : 1;
     }
+    if (colorimetry != o.colorimetry) {
+        return colorimetry < o.colorimetry ? -1 : 1;
+    }
     if (uiMode != o.uiMode) {
         return uiMode < o.uiMode ? -1 : 1;
     }
@@ -1992,6 +1997,8 @@
     if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) diffs |= CONFIG_LAYOUTDIR;
     if ((screenLayout & ~MASK_LAYOUTDIR) != (o.screenLayout & ~MASK_LAYOUTDIR)) diffs |= CONFIG_SCREEN_LAYOUT;
     if ((screenLayout2 & MASK_SCREENROUND) != (o.screenLayout2 & MASK_SCREENROUND)) diffs |= CONFIG_SCREEN_ROUND;
+    if ((colorimetry & MASK_WIDE_COLOR_GAMUT) != (o.colorimetry & MASK_WIDE_COLOR_GAMUT)) diffs |= CONFIG_COLORIMETRY;
+    if ((colorimetry & MASK_HDR) != (o.colorimetry & MASK_HDR)) diffs |= CONFIG_COLORIMETRY;
     if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
     if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE;
     if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE;
@@ -2103,6 +2110,17 @@
         }
     }
 
+    if (colorimetry || o.colorimetry) {
+        if (((colorimetry^o.colorimetry) & MASK_HDR) != 0) {
+            if (!(colorimetry & MASK_HDR)) return false;
+            if (!(o.colorimetry & MASK_HDR)) return true;
+        }
+        if (((colorimetry^o.colorimetry) & MASK_WIDE_COLOR_GAMUT) != 0) {
+            if (!(colorimetry & MASK_WIDE_COLOR_GAMUT)) return false;
+            if (!(o.colorimetry & MASK_WIDE_COLOR_GAMUT)) return true;
+        }
+    }
+
     if (orientation != o.orientation) {
         if (!orientation) return false;
         if (!o.orientation) return true;
@@ -2390,6 +2408,17 @@
             }
         }
 
+        if (colorimetry || o.colorimetry) {
+            if (((colorimetry^o.colorimetry) & MASK_WIDE_COLOR_GAMUT) != 0 &&
+                    (requested->colorimetry & MASK_WIDE_COLOR_GAMUT)) {
+                return colorimetry & MASK_WIDE_COLOR_GAMUT;
+            }
+            if (((colorimetry^o.colorimetry) & MASK_HDR) != 0 &&
+                    (requested->colorimetry & MASK_HDR)) {
+                return colorimetry & MASK_HDR;
+            }
+        }
+
         if ((orientation != o.orientation) && requested->orientation) {
             return (orientation);
         }
@@ -2639,6 +2668,18 @@
         if (screenRound != 0 && screenRound != setScreenRound) {
             return false;
         }
+
+        const int hdr = colorimetry & MASK_HDR;
+        const int setHdr = settings.colorimetry & MASK_HDR;
+        if (hdr != 0 && hdr != setHdr) {
+            return false;
+        }
+
+        const int wideColorGamut = colorimetry & MASK_WIDE_COLOR_GAMUT;
+        const int setWideColorGamut = settings.colorimetry & MASK_WIDE_COLOR_GAMUT;
+        if (wideColorGamut != 0 && wideColorGamut != setWideColorGamut) {
+            return false;
+        }
     }
 
     if (screenSizeDp != 0) {
@@ -2959,6 +3000,34 @@
                 break;
         }
     }
+    if ((colorimetry&MASK_HDR) != 0) {
+        if (res.size() > 0) res.append("-");
+        switch (colorimetry&MASK_HDR) {
+            case ResTable_config::HDR_NO:
+                res.append("lowdr");
+                break;
+            case ResTable_config::HDR_YES:
+                res.append("highdr");
+                break;
+            default:
+                res.appendFormat("hdr=%d", dtohs(colorimetry&MASK_HDR));
+                break;
+        }
+    }
+    if ((colorimetry&MASK_WIDE_COLOR_GAMUT) != 0) {
+        if (res.size() > 0) res.append("-");
+        switch (colorimetry&MASK_WIDE_COLOR_GAMUT) {
+            case ResTable_config::WIDE_COLOR_GAMUT_NO:
+                res.append("nowidecg");
+                break;
+            case ResTable_config::WIDE_COLOR_GAMUT_YES:
+                res.append("widecg");
+                break;
+            default:
+                res.appendFormat("wideColorGamut=%d", dtohs(colorimetry&MASK_WIDE_COLOR_GAMUT));
+                break;
+        }
+    }
     if (orientation != ORIENTATION_ANY) {
         if (res.size() > 0) res.append("-");
         switch (orientation) {
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index c118b57..1e4aee9 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1146,11 +1146,26 @@
         SCREENROUND_YES = ACONFIGURATION_SCREENROUND_YES,
     };
 
+    enum {
+        // colorimetry bits for wide-color gamut/narrow-color gamut.
+        MASK_WIDE_COLOR_GAMUT = 0x03,
+        WIDE_COLOR_GAMUT_ANY = ACONFIGURATION_WIDE_COLOR_GAMUT_ANY,
+        WIDE_COLOR_GAMUT_NO = ACONFIGURATION_WIDE_COLOR_GAMUT_NO,
+        WIDE_COLOR_GAMUT_YES = ACONFIGURATION_WIDE_COLOR_GAMUT_YES,
+
+        // colorimetry bits for HDR/LDR.
+        MASK_HDR = 0x0c,
+        SHIFT_COLORIMETRY_HDR = 2,
+        HDR_ANY = ACONFIGURATION_HDR_ANY << SHIFT_COLORIMETRY_HDR,
+        HDR_NO = ACONFIGURATION_HDR_NO << SHIFT_COLORIMETRY_HDR,
+        HDR_YES = ACONFIGURATION_HDR_YES << SHIFT_COLORIMETRY_HDR,
+    };
+
     // An extension of screenConfig.
     union {
         struct {
             uint8_t screenLayout2;      // Contains round/notround qualifier.
-            uint8_t screenConfigPad1;   // Reserved padding.
+            uint8_t colorimetry;        // Wide-gamut, HDR, etc.
             uint16_t screenConfigPad2;  // Reserved padding.
         };
         uint32_t screenConfig2;
@@ -1193,6 +1208,7 @@
         CONFIG_UI_MODE = ACONFIGURATION_UI_MODE,
         CONFIG_LAYOUTDIR = ACONFIGURATION_LAYOUTDIR,
         CONFIG_SCREEN_ROUND = ACONFIGURATION_SCREEN_ROUND,
+        CONFIG_COLORIMETRY = ACONFIGURATION_COLORIMETRY,
     };
     
     // Compare two configuration, returning CONFIG_* flags set for each value
diff --git a/tools/aapt2/util/StringPiece.h b/libs/androidfw/include/androidfw/StringPiece.h
similarity index 66%
rename from tools/aapt2/util/StringPiece.h
rename to libs/androidfw/include/androidfw/StringPiece.h
index 5144b1f..c9effd1 100644
--- a/tools/aapt2/util/StringPiece.h
+++ b/libs/androidfw/include/androidfw/StringPiece.h
@@ -14,26 +14,24 @@
  * limitations under the License.
  */
 
-#ifndef AAPT_STRING_PIECE_H
-#define AAPT_STRING_PIECE_H
+#ifndef ANDROIDFW_STRING_PIECE_H
+#define ANDROIDFW_STRING_PIECE_H
 
 #include <ostream>
 #include <string>
 
 #include "utils/JenkinsHash.h"
-#include "utils/String8.h"
 #include "utils/Unicode.h"
 
-namespace aapt {
+namespace android {
 
-/**
- * Read only wrapper around basic C strings.
- * Prevents excessive copying.
- *
- * WARNING: When creating from std::basic_string<>, moving the original
- * std::basic_string<> will invalidate the data held in a BasicStringPiece<>.
- * BasicStringPiece<> should only be used transitively.
- */
+// Read only wrapper around basic C strings. Prevents excessive copying.
+// StringPiece does not own the data it is wrapping. The lifetime of the underlying
+// data must outlive this StringPiece.
+//
+// WARNING: When creating from std::basic_string<>, moving the original
+// std::basic_string<> will invalidate the data held in a BasicStringPiece<>.
+// BasicStringPiece<> should only be used transitively.
 template <typename TChar>
 class BasicStringPiece {
  public:
@@ -53,15 +51,14 @@
   BasicStringPiece<TChar>& assign(const TChar* str, size_t len);
 
   BasicStringPiece<TChar> substr(size_t start, size_t len = npos) const;
-  BasicStringPiece<TChar> substr(
-      BasicStringPiece<TChar>::const_iterator begin,
-      BasicStringPiece<TChar>::const_iterator end) const;
+  BasicStringPiece<TChar> substr(BasicStringPiece<TChar>::const_iterator begin,
+                                 BasicStringPiece<TChar>::const_iterator end) const;
 
   const TChar* data() const;
   size_t length() const;
   size_t size() const;
   bool empty() const;
-  std::basic_string<TChar> ToString() const;
+  std::basic_string<TChar> to_string() const;
 
   bool contains(const BasicStringPiece<TChar>& rhs) const;
   int compare(const BasicStringPiece<TChar>& rhs) const;
@@ -89,17 +86,14 @@
 constexpr const size_t BasicStringPiece<TChar>::npos;
 
 template <typename TChar>
-inline BasicStringPiece<TChar>::BasicStringPiece()
-    : data_(nullptr), length_(0) {}
+inline BasicStringPiece<TChar>::BasicStringPiece() : data_(nullptr), length_(0) {}
 
 template <typename TChar>
-inline BasicStringPiece<TChar>::BasicStringPiece(
-    const BasicStringPiece<TChar>& str)
+inline BasicStringPiece<TChar>::BasicStringPiece(const BasicStringPiece<TChar>& str)
     : data_(str.data_), length_(str.length_) {}
 
 template <typename TChar>
-inline BasicStringPiece<TChar>::BasicStringPiece(
-    const std::basic_string<TChar>& str)
+inline BasicStringPiece<TChar>::BasicStringPiece(const std::basic_string<TChar>& str)
     : data_(str.data()), length_(str.length()) {}
 
 template <>
@@ -123,16 +117,14 @@
 }
 
 template <typename TChar>
-inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(
-    const TChar* str, size_t len) {
+inline BasicStringPiece<TChar>& BasicStringPiece<TChar>::assign(const TChar* str, size_t len) {
   data_ = str;
   length_ = len;
   return *this;
 }
 
 template <typename TChar>
-inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(
-    size_t start, size_t len) const {
+inline BasicStringPiece<TChar> BasicStringPiece<TChar>::substr(size_t start, size_t len) const {
   if (len == npos) {
     len = length_ - start;
   }
@@ -171,13 +163,12 @@
 }
 
 template <typename TChar>
-inline std::basic_string<TChar> BasicStringPiece<TChar>::ToString() const {
+inline std::basic_string<TChar> BasicStringPiece<TChar>::to_string() const {
   return std::basic_string<TChar>(data_, length_);
 }
 
 template <>
-inline bool BasicStringPiece<char>::contains(
-    const BasicStringPiece<char>& rhs) const {
+inline bool BasicStringPiece<char>::contains(const BasicStringPiece<char>& rhs) const {
   if (!data_ || !rhs.data_) {
     return false;
   }
@@ -188,8 +179,7 @@
 }
 
 template <>
-inline int BasicStringPiece<char>::compare(
-    const BasicStringPiece<char>& rhs) const {
+inline int BasicStringPiece<char>::compare(const BasicStringPiece<char>& rhs) const {
   const char nullStr = '\0';
   const char* b1 = data_ != nullptr ? data_ : &nullStr;
   const char* e1 = b1 + length_;
@@ -205,15 +195,21 @@
   return static_cast<int>(length_ - rhs.length_);
 }
 
-inline ::std::ostream& operator<<(::std::ostream& out,
-                                  const BasicStringPiece<char16_t>& str) {
-  android::String8 utf8(str.data(), str.size());
-  return out.write(utf8.string(), utf8.size());
+inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char16_t>& str) {
+  const ssize_t result_len = utf16_to_utf8_length(str.data(), str.size());
+  if (result_len < 0) {
+    // Empty string.
+    return out;
+  }
+
+  std::string result;
+  result.resize(static_cast<size_t>(result_len));
+  utf16_to_utf8(str.data(), str.length(), &*result.begin(), static_cast<size_t>(result_len) + 1);
+  return out << result;
 }
 
 template <>
-inline bool BasicStringPiece<char16_t>::contains(
-    const BasicStringPiece<char16_t>& rhs) const {
+inline bool BasicStringPiece<char16_t>::contains(const BasicStringPiece<char16_t>& rhs) const {
   if (!data_ || !rhs.data_) {
     return false;
   }
@@ -224,8 +220,7 @@
 }
 
 template <>
-inline int BasicStringPiece<char16_t>::compare(
-    const BasicStringPiece<char16_t>& rhs) const {
+inline int BasicStringPiece<char16_t>::compare(const BasicStringPiece<char16_t>& rhs) const {
   const char16_t nullStr = u'\0';
   const char16_t* b1 = data_ != nullptr ? data_ : &nullStr;
   const char16_t* b2 = rhs.data_ != nullptr ? rhs.data_ : &nullStr;
@@ -233,66 +228,52 @@
 }
 
 template <typename TChar>
-inline bool BasicStringPiece<TChar>::operator<(
-    const BasicStringPiece<TChar>& rhs) const {
+inline bool BasicStringPiece<TChar>::operator<(const BasicStringPiece<TChar>& rhs) const {
   return compare(rhs) < 0;
 }
 
 template <typename TChar>
-inline bool BasicStringPiece<TChar>::operator>(
-    const BasicStringPiece<TChar>& rhs) const {
+inline bool BasicStringPiece<TChar>::operator>(const BasicStringPiece<TChar>& rhs) const {
   return compare(rhs) > 0;
 }
 
 template <typename TChar>
-inline bool BasicStringPiece<TChar>::operator==(
-    const BasicStringPiece<TChar>& rhs) const {
+inline bool BasicStringPiece<TChar>::operator==(const BasicStringPiece<TChar>& rhs) const {
   return compare(rhs) == 0;
 }
 
 template <typename TChar>
-inline bool BasicStringPiece<TChar>::operator!=(
-    const BasicStringPiece<TChar>& rhs) const {
+inline bool BasicStringPiece<TChar>::operator!=(const BasicStringPiece<TChar>& rhs) const {
   return compare(rhs) != 0;
 }
 
 template <typename TChar>
-inline typename BasicStringPiece<TChar>::const_iterator
-BasicStringPiece<TChar>::begin() const {
+inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::begin() const {
   return data_;
 }
 
 template <typename TChar>
-inline typename BasicStringPiece<TChar>::const_iterator
-BasicStringPiece<TChar>::end() const {
+inline typename BasicStringPiece<TChar>::const_iterator BasicStringPiece<TChar>::end() const {
   return data_ + length_;
 }
 
-inline ::std::ostream& operator<<(::std::ostream& out,
-                                  const BasicStringPiece<char>& str) {
+inline ::std::ostream& operator<<(::std::ostream& out, const BasicStringPiece<char>& str) {
   return out.write(str.data(), str.size());
 }
 
-}  // namespace aapt
-
-inline ::std::ostream& operator<<(::std::ostream& out,
-                                  const std::u16string& str) {
-  android::String8 utf8(str.data(), str.size());
-  return out.write(utf8.string(), utf8.size());
-}
+}  // namespace android
 
 namespace std {
 
 template <typename TChar>
-struct hash<aapt::BasicStringPiece<TChar>> {
-  size_t operator()(const aapt::BasicStringPiece<TChar>& str) const {
+struct hash<android::BasicStringPiece<TChar>> {
+  size_t operator()(const android::BasicStringPiece<TChar>& str) const {
     uint32_t hashCode = android::JenkinsHashMixBytes(
-        0, reinterpret_cast<const uint8_t*>(str.data()),
-        sizeof(TChar) * str.size());
+        0, reinterpret_cast<const uint8_t*>(str.data()), sizeof(TChar) * str.size());
     return static_cast<size_t>(hashCode);
   }
 };
 
 }  // namespace std
 
-#endif  // AAPT_STRING_PIECE_H
+#endif  // ANDROIDFW_STRING_PIECE_H
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 6754cd8..650f813 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -34,6 +34,7 @@
     LoadedArsc_test.cpp \
     ResTable_test.cpp \
     Split_test.cpp \
+    StringPiece_test.cpp \
     TestHelpers.cpp \
     TestMain.cpp \
     Theme_test.cpp \
diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp
index 778c7bf..3e5aca7 100644
--- a/libs/androidfw/tests/Config_test.cpp
+++ b/libs/androidfw/tests/Config_test.cpp
@@ -182,4 +182,24 @@
   EXPECT_TRUE(targetConfigC.isBetterThan(targetConfigB, &deviceConfig));
 }
 
+TEST(ConfigTest, ScreenIsWideGamut) {
+  ResTable_config defaultConfig;
+  memset(&defaultConfig, 0, sizeof(defaultConfig));
+
+  ResTable_config wideGamutConfig = defaultConfig;
+  wideGamutConfig.colorimetry = ResTable_config::WIDE_COLOR_GAMUT_YES;
+
+  EXPECT_EQ(defaultConfig.diff(wideGamutConfig), ResTable_config::CONFIG_COLORIMETRY);
+}
+
+TEST(ConfigTest, ScreenIsHdr) {
+  ResTable_config defaultConfig;
+  memset(&defaultConfig, 0, sizeof(defaultConfig));
+
+  ResTable_config hdrConfig = defaultConfig;
+  hdrConfig.colorimetry = ResTable_config::HDR_YES;
+
+  EXPECT_EQ(defaultConfig.diff(hdrConfig), ResTable_config::CONFIG_COLORIMETRY);
+}
+
 }  // namespace android.
diff --git a/tools/aapt2/util/StringPiece_test.cpp b/libs/androidfw/tests/StringPiece_test.cpp
similarity index 96%
rename from tools/aapt2/util/StringPiece_test.cpp
rename to libs/androidfw/tests/StringPiece_test.cpp
index 048961d..316a5c1 100644
--- a/tools/aapt2/util/StringPiece_test.cpp
+++ b/libs/androidfw/tests/StringPiece_test.cpp
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-#include "util/StringPiece.h"
+#include "androidfw/StringPiece.h"
 
 #include <algorithm>
 #include <string>
 #include <vector>
 
-#include "test/Test.h"
+#include "TestHelpers.h"
 
-namespace aapt {
+namespace android {
 
 TEST(StringPieceTest, CompareNonNullTerminatedPiece) {
   StringPiece a("hello world", 5);
@@ -92,4 +92,4 @@
   EXPECT_FALSE(text16.contains(long_needle16));
 }
 
-}  // namespace aapt
+}  // namespace android
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 6a00379..956f66e 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -17,8 +17,7 @@
 #include "MinikinSkia.h"
 
 #include <log/log.h>
-#include <SkFontDescriptor.h>
-#include <SkFontMgr.h>
+
 #include <SkPaint.h>
 #include <SkTypeface.h>
 
@@ -87,28 +86,6 @@
     return mTtcIndex;
 }
 
-minikin::MinikinFont* MinikinFontSkia::createFontWithVariation(
-        const std::vector<minikin::FontVariation>& variations) const {
-    SkFontMgr::FontParameters params;
-
-    int ttcIndex;
-    SkStreamAsset* stream = mTypeface->openStream(&ttcIndex);
-    LOG_ALWAYS_FATAL_IF(stream == nullptr, "openStream failed");
-
-    params.setCollectionIndex(ttcIndex);
-    std::vector<SkFontMgr::FontParameters::Axis> skAxes;
-    skAxes.resize(variations.size());
-    for (size_t i = 0; i < variations.size(); i++) {
-        skAxes[i].fTag = variations[i].axisTag;
-        skAxes[i].fStyleValue = SkFloatToScalar(variations[i].value);
-    }
-    params.setAxes(skAxes.data(), skAxes.size());
-    sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
-    sk_sp<SkTypeface> face(fm->createFromStream(stream, params));
-
-    return new MinikinFontSkia(std::move(face), mFontData, mFontSize, ttcIndex);
-}
-
 uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
     uint32_t flags = paint->getFlags();
     SkPaint::Hinting hinting = paint->getHinting();
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 249b0cb..3ee916c 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -44,8 +44,6 @@
     const void* GetFontData() const;
     size_t GetFontSize() const;
     int GetFontIndex() const;
-    minikin::MinikinFont* createFontWithVariation(
-            const std::vector<minikin::FontVariation>&) const;
 
     static uint32_t packPaintFlags(const SkPaint* paint);
     static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index b69b0cb..ca43156 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -62,7 +62,7 @@
 Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {
     Typeface* resolvedFace = Typeface::resolveDefault(src);
     Typeface* result = new Typeface;
-    if (result != nullptr) {
+    if (result != 0) {
         result->fFontCollection = resolvedFace->fFontCollection;
         result->fFontCollection->Ref();
         result->fSkiaStyle = style;
@@ -72,30 +72,10 @@
     return result;
 }
 
-Typeface* Typeface::createFromTypefaceWithVariation(Typeface* src,
-        const std::vector<minikin::FontVariation>& variations) {
-    Typeface* resolvedFace = Typeface::resolveDefault(src);
-    Typeface* result = new Typeface();
-    if (result != nullptr) {
-        result->fFontCollection =
-                resolvedFace->fFontCollection->createCollectionWithVariation(variations);
-        if (result->fFontCollection == nullptr) {
-            // None of passed axes are supported by this collection.
-            // So we will reuse the same collection with incrementing reference count.
-            result->fFontCollection = resolvedFace->fFontCollection;
-            result->fFontCollection->Ref();
-        }
-        result->fSkiaStyle = resolvedFace->fSkiaStyle;
-        result->fBaseWeight = resolvedFace->fBaseWeight;
-        resolveStyle(result);
-    }
-    return result;
-}
-
 Typeface* Typeface::createWeightAlias(Typeface* src, int weight) {
     Typeface* resolvedFace = Typeface::resolveDefault(src);
     Typeface* result = new Typeface;
-    if (result != nullptr) {
+    if (result != 0) {
         result->fFontCollection = resolvedFace->fFontCollection;
         result->fFontCollection->Ref();
         result->fSkiaStyle = resolvedFace->fSkiaStyle;
@@ -150,9 +130,9 @@
     sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release());
     LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont);
 
+    minikin::FontFamily* family = new minikin::FontFamily();
     minikin::MinikinFont* font = new MinikinFontSkia(std::move(typeface), data, st.st_size, 0);
-    minikin::FontFamily* family = new minikin::FontFamily(
-                 std::vector<minikin::Font>({ minikin::Font(font, minikin::FontStyle()) }));
+    family->addFont(font);
     font->Unref();
 
     std::vector<minikin::FontFamily*> typefaces = { family };
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index 4392ebc..1be630c 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -43,9 +43,6 @@
 
     static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
 
-    static Typeface* createFromTypefaceWithVariation(Typeface* src,
-            const std::vector<minikin::FontVariation>& variations);
-
     static Typeface* createWeightAlias(Typeface* src, int baseweight);
 
     static Typeface* createFromFamilies(const std::vector<minikin::FontFamily*>& families);
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index 419c8a9..6ca8d8b 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -19,7 +19,6 @@
 #include "RenderNode.h"
 #include "SkClipStack.h"
 #include <private/hwui/DrawGlInfo.h>
-#include <SkPath.h>
 #include <GrContext.h>
 
 namespace android {
@@ -76,9 +75,7 @@
 
     //apply a simple clip with a scissor or a complex clip with a stencil
     SkRegion clipRegion;
-    SkPath path;
-    canvas->getClipStack()->asPath(&path);
-    clipRegion.setPath(path, SkRegion(ibounds));
+    canvas->temporary_internal_getRgnClip(&clipRegion);
     if (CC_UNLIKELY(clipRegion.isComplex())) {
         //It is only a temporary solution to use a scissor to draw the stencil.
         //There is a bug 31489986 to implement efficiently non-rectangular clips.
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 64576ec..e62dfaa 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -801,6 +801,28 @@
     }
 
     /**
+     * Sets the next output file descriptor to be used when the maximum filesize is reached
+     * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File descriptor
+     * must be seekable and in read-write mode. After setting the next output file, application
+     * should not use the file referenced by this file descriptor until {@link #stop}. Application
+     * must call this after receiving on the {@link android.media.MediaRecorder.OnInfoListener} a
+     * "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving
+     * a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used
+     * until switching to that output. Application will receive
+     * {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED} when the next output file is used.
+     * Application will not be able to set a new output file if the previous one has not been used.
+     * Application is responsible for cleaning up unused files after {@link #stop} is called.
+     *
+     * @param fd an open file descriptor to be written into.
+     * @throws IllegalStateException if it is called before prepare().
+     * @throws IOException if setNextOutputFile fails otherwise.
+     */
+    public void setNextOutputFile(FileDescriptor fd) throws IllegalStateException, IOException
+    {
+        _setNextOutputFile(fd);
+    }
+
+    /**
      * Sets the path of the output file to be produced. Call this after
      * setOutputFormat() but before prepare().
      *
@@ -814,9 +836,38 @@
         mPath = path;
     }
 
+    /**
+     * Sets the next output file path to be used when the maximum filesize is reached
+     * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File should
+     * be seekable. After setting the next output file, application should not use the file
+     * referenced by this file descriptor until {@link #stop}. Application must call this
+     * after receiving on the {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
+     * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
+     * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
+     * that output. Application will receive {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
+     * when the next output file is used. Application will not be able to set a new output file if
+     * the previous one has not been used. Application is responsible for cleaning up unused files
+     * after {@link #stop} is called.
+     *
+     * @param  path The pathname to use.
+     * @throws IllegalStateException if it is called before prepare().
+     * @throws IOException if setNextOutputFile fails otherwise.
+     */
+    public void setNextOutputFile(String path) throws IllegalStateException, IOException
+    {
+        if (path != null) {
+            RandomAccessFile file = new RandomAccessFile(path, "rws");
+            try {
+                _setNextOutputFile(file.getFD());
+            } finally {
+                file.close();
+            }
+        }
+    }
+
     // native implementation
-    private native void _setOutputFile(FileDescriptor fd, long offset, long length)
-        throws IllegalStateException, IOException;
+    private native void _setOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
+    private native void _setNextOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
     private native void _prepare() throws IllegalStateException, IOException;
 
     /**
@@ -833,12 +884,12 @@
         if (mPath != null) {
             RandomAccessFile file = new RandomAccessFile(mPath, "rws");
             try {
-                _setOutputFile(file.getFD(), 0, 0);
+                _setOutputFile(file.getFD());
             } finally {
                 file.close();
             }
         } else if (mFd != null) {
-            _setOutputFile(mFd, 0, 0);
+            _setOutputFile(mFd);
         } else {
             throw new IOException("No valid output file");
         }
@@ -980,9 +1031,26 @@
      */
     public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
     /** A maximum filesize had been setup and has now been reached.
+     * Note: This event will not be sent if application already set
+     * next output file through {@link #setNextOutputFile}.
      * @see android.media.MediaRecorder.OnInfoListener
      */
     public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801;
+    /** A maximum filesize had been setup and current recorded file size
+     * has reached 90% of the limit. This is sent once per file upon
+     * reaching/passing the 90% limit. To continue the recording, applicaiton
+     * should use {@link #setNextOutputFile} to set the next output file.
+     * Otherwise, recording will stop when reaching maximum file size.
+     * @see android.media.MediaRecorder.OnInfoListener
+     */
+    public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING = 802;
+    /** A maximum filesize had been reached and MediaRecorder has switched
+     * output to a new file set by application {@link #setNextOutputFile}.
+     * For best practice, application should use this event to keep track
+     * of whether the file previously set has been used or not.
+     * @see android.media.MediaRecorder.OnInfoListener
+     */
+    public static final int MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED = 803;
 
     /** informational events for individual tracks, for testing purpose.
      * The track informational event usually contains two parts in the ext1
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 6c79ab7..7c509d2 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -290,7 +290,7 @@
 }
 
 static void
-android_media_MediaRecorder_setOutputFileFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
+android_media_MediaRecorder_setOutputFileFD(JNIEnv *env, jobject thiz, jobject fileDescriptor)
 {
     ALOGV("setOutputFile");
     if (fileDescriptor == NULL) {
@@ -303,7 +303,25 @@
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return;
     }
-    status_t opStatus = mr->setOutputFile(fd, offset, length);
+    status_t opStatus = mr->setOutputFile(fd);
+    process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
+}
+
+static void
+android_media_MediaRecorder_setNextOutputFileFD(JNIEnv *env, jobject thiz, jobject fileDescriptor)
+{
+    ALOGV("setNextOutputFile");
+    if (fileDescriptor == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+    if (mr == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+    status_t opStatus = mr->setNextOutputFile(fd);
     process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
 }
 
@@ -617,7 +635,8 @@
     {"setVideoEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setVideoEncoder},
     {"setAudioEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setAudioEncoder},
     {"setParameter",         "(Ljava/lang/String;)V",           (void *)android_media_MediaRecorder_setParameter},
-    {"_setOutputFile",       "(Ljava/io/FileDescriptor;JJ)V",   (void *)android_media_MediaRecorder_setOutputFileFD},
+    {"_setOutputFile",       "(Ljava/io/FileDescriptor;)V",     (void *)android_media_MediaRecorder_setOutputFileFD},
+    {"_setNextOutputFile",   "(Ljava/io/FileDescriptor;)V",     (void *)android_media_MediaRecorder_setNextOutputFileFD},
     {"setVideoSize",         "(II)V",                           (void *)android_media_MediaRecorder_setVideoSize},
     {"setVideoFrameRate",    "(I)V",                            (void *)android_media_MediaRecorder_setVideoFrameRate},
     {"setMaxDuration",       "(I)V",                            (void *)android_media_MediaRecorder_setMaxDuration},
diff --git a/packages/SettingsLib/Android.mk b/packages/SettingsLib/Android.mk
index ad07283..67ef40a 100644
--- a/packages/SettingsLib/Android.mk
+++ b/packages/SettingsLib/Android.mk
@@ -12,6 +12,8 @@
     android-support-v7-appcompat \
     android-support-v14-preference
 
+LOCAL_STATIC_JAVA_LIBRARY := legacy-android-test
+
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
 LOCAL_JAR_EXCLUDE_FILES := none
@@ -21,4 +23,4 @@
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # For the test package.
-include $(call all-makefiles-under, $(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_root.xml b/packages/SettingsLib/res/layout/access_point_friction_widget.xml
similarity index 62%
rename from packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_root.xml
rename to packages/SettingsLib/res/layout/access_point_friction_widget.xml
index 85573e0..7409686 100644
--- a/packages/SystemUI/res/anim/ic_signal_workmode_enable_animation_root.xml
+++ b/packages/SettingsLib/res/layout/access_point_friction_widget.xml
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2017 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,11 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="0.3"
-        android:valueTo="1.0"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/friction_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:contentDescription="@null" />
diff --git a/packages/SettingsLib/res/layout/settings_with_drawer.xml b/packages/SettingsLib/res/layout/settings_with_drawer.xml
index 24a5422..b659cee 100644
--- a/packages/SettingsLib/res/layout/settings_with_drawer.xml
+++ b/packages/SettingsLib/res/layout/settings_with_drawer.xml
@@ -26,12 +26,12 @@
         android:orientation="vertical"
         android:fitsSystemWindows="true">
         <FrameLayout
+            style="?android:attr/actionBarStyle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:theme="?android:attr/actionBarTheme">
             <Toolbar
                 android:id="@+id/action_bar"
-                style="?android:attr/actionBarStyle"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:navigationContentDescription="@*android:string/action_bar_up_description"/>
diff --git a/packages/SettingsLib/res/values/attrs.xml b/packages/SettingsLib/res/values/attrs.xml
index f064e4e..1f35d3e 100644
--- a/packages/SettingsLib/res/values/attrs.xml
+++ b/packages/SettingsLib/res/values/attrs.xml
@@ -36,7 +36,12 @@
     <declare-styleable name="WifiEncryptionState">
         <attr name="state_encrypted" format="boolean" />
     </declare-styleable>
+    <declare-styleable name="WifiSavedState">
+        <attr name="state_saved" format="boolean" />
+    </declare-styleable>
+
     <attr name="wifi_signal" format="reference" />
+    <attr name="wifi_friction" format="reference" />
 
     <declare-styleable name="UsageView">
         <attr name="android:colorAccent" />
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 6179244..fbc6aa3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -13,8 +13,11 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.net.ConnectivityManager;
+import android.net.ScoredNetwork;
 import android.os.BatteryManager;
 import android.os.UserManager;
 import android.print.PrintManager;
@@ -29,6 +32,14 @@
     private static String sServicesSystemSharedLibPackageName;
     private static String sSharedSystemSharedLibPackageName;
 
+    static final int[] WIFI_PIE_FOR_BADGING = {
+          com.android.internal.R.drawable.ic_signal_wifi_badged_0_bars,
+          com.android.internal.R.drawable.ic_signal_wifi_badged_1_bar,
+          com.android.internal.R.drawable.ic_signal_wifi_badged_2_bars,
+          com.android.internal.R.drawable.ic_signal_wifi_badged_3_bars,
+          com.android.internal.R.drawable.ic_signal_wifi_badged_4_bars
+    };
+
     /**
      * Return string resource that best describes combination of tethering
      * options available on this device.
@@ -160,10 +171,7 @@
 
     @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;
+        return getColorAttr(context, android.R.attr.colorAccent);
     }
 
     @ColorInt
@@ -182,6 +190,29 @@
         return list.getDefaultColor();
     }
 
+    @ColorInt
+    public static int getDisabled(Context context, int inputColor) {
+        return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor);
+    }
+
+    @ColorInt
+    public static int applyAlphaAttr(Context context, int attr, int inputColor) {
+        TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
+        float alpha = ta.getFloat(0, 0);
+        ta.recycle();
+        alpha *= Color.alpha(inputColor);
+        return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor),
+                Color.blue(inputColor));
+    }
+
+    @ColorInt
+    public static int getColorAttr(Context context, int attr) {
+        TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
+        @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.
@@ -233,4 +264,41 @@
                 com.android.internal.R.string.config_deviceProvisioningPackage);
         return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName);
     }
+
+    /**
+     * Returns a badged Wifi icon drawable.
+     *
+     * <p>The first layer contains the Wifi pie and the second layer contains the badge. Callers
+     * should set the drawable to the appropriate size and tint color.
+     *
+     * @param context The caller's context (must have access to internal resources)
+     * @param level The number of bars to show (0-4)
+     * @param badge The badge enum {@see android.net.ScoredNetwork}
+     *
+     * @throws IllegalArgumentException if an invalid badge enum is given
+     *
+     * @deprecated TODO(sghuman): Finalize the form of this method and then move it to a new
+     *         location.
+     */
+    public static LayerDrawable getBadgedWifiIcon(Context context, int level, int badge) {
+        return new LayerDrawable(
+                new Drawable[] {
+                        context.getDrawable(WIFI_PIE_FOR_BADGING[level]),
+                        context.getDrawable(getWifiBadgeResource(badge))
+                });
+    }
+
+    private static int getWifiBadgeResource(int badge) {
+        switch (badge) {
+            case ScoredNetwork.BADGING_SD:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_sd;
+            case ScoredNetwork.BADGING_HD:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_hd;
+            case ScoredNetwork.BADGING_4K:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_4k;
+            default:
+                throw new IllegalArgumentException(
+                    "No badge resource found for badge value: " + badge);
+        }
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index b327be0..6e10aab 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
@@ -105,6 +106,12 @@
     private static final String EXTRA_CATEGORY_KEY = "com.android.settings.category";
 
     /**
+     * The key used to get the package name of the icon resource for the preference.
+     */
+    private static final String EXTRA_PREFERENCE_ICON_PACKAGE =
+        "com.android.settings.icon_package";
+
+    /**
      * Name of the meta-data item that should be set in the AndroidManifest.xml
      * to specify the key that should be used for the preference.
      */
@@ -342,6 +349,7 @@
             ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) {
         if (applicationInfo.isSystemApp()) {
             int icon = 0;
+            Pair<String, Integer> iconFromUri = null;
             CharSequence title = null;
             String summary = null;
             String keyHint = null;
@@ -358,10 +366,10 @@
 
                 if (res != null && metaData != null) {
                     if (metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
-                        icon = getIconFromUri(context,
+                        iconFromUri = getIconFromUri(context, activityInfo.packageName,
                                 metaData.getString(META_DATA_PREFERENCE_ICON_URI), providerMap);
                     }
-                    if ((icon == 0) && metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
+                    if (iconFromUri == null && metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
                         icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
                     }
                     if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
@@ -401,12 +409,18 @@
             if (TextUtils.isEmpty(title)) {
                 title = activityInfo.loadLabel(pm).toString();
             }
-            if (icon == 0) {
-                icon = activityInfo.icon;
+
+            // Set the icon
+            if (iconFromUri != null) {
+                tile.icon = Icon.createWithResource(iconFromUri.first, iconFromUri.second);
+            } else {
+                if (icon == 0) {
+                    icon = activityInfo.icon;
+                }
+                tile.icon = Icon.createWithResource(activityInfo.packageName, icon);
             }
 
-            // Set icon, title and summary for the preference
-            tile.icon = Icon.createWithResource(activityInfo.packageName, icon);
+            // Set title and summary for the preference
             tile.title = title;
             tile.summary = summary;
             // Replace the intent with this specific activity
@@ -422,16 +436,33 @@
     }
 
     /**
-     * Gets the icon resource id from content provider.
+     * Gets the icon package name and resource id from content provider.
      * @param Context context
+     * @param packageName package name of the target activity
      * @param uriString URI for the content provider
      * @param providerMap Maps URI authorities to providers
-     * @return Resource id if returned by the content provider, otherwise 0
+     * @return package name and resource id of the icon specified
      */
-    public static int getIconFromUri(Context context, String uriString,
-            Map<String, IContentProvider> providerMap) {
+    public static Pair<String, Integer> getIconFromUri(Context context, String packageName,
+            String uriString, Map<String, IContentProvider> providerMap) {
         Bundle bundle = getBundleFromUri(context, uriString, providerMap);
-        return (bundle != null) ? bundle.getInt(META_DATA_PREFERENCE_ICON, 0) : 0;
+        if (bundle == null) {
+            return null;
+        }
+        String iconPackageName = bundle.getString(EXTRA_PREFERENCE_ICON_PACKAGE);
+        if (TextUtils.isEmpty(iconPackageName)) {
+            return null;
+        }
+        int resId = bundle.getInt(META_DATA_PREFERENCE_ICON, 0);
+        if (resId == 0) {
+            return null;
+        }
+        // Icon can either come from the target package or from the Settings app.
+        if (iconPackageName.equals(packageName)
+                || iconPackageName.equals(context.getPackageName())) {
+            return Pair.create(iconPackageName, bundle.getInt(META_DATA_PREFERENCE_ICON, 0));
+        }
+        return null;
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index e7450fa..06ea445 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -27,12 +27,15 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkInfo.State;
+import android.net.NetworkKey;
+import android.net.ScoredNetwork;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.net.wifi.WifiNetworkScoreCache;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -48,6 +51,7 @@
 import com.android.settingslib.R;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -132,6 +136,9 @@
 
     private Object mTag;
 
+    private int mRankingScore = Integer.MIN_VALUE;
+    private int mBadge = ScoredNetwork.BADGING_NONE;
+
     // used to co-relate internal vs returned accesspoint.
     int mId;
 
@@ -205,6 +212,8 @@
         this.mScanResultCache.clear();
         this.mScanResultCache.putAll(that.mScanResultCache);
         this.mId = that.mId;
+        this.mBadge = that.mBadge;
+        this.mRankingScore = that.mRankingScore;
     }
 
     @Override
@@ -213,6 +222,11 @@
         if (isActive() && !other.isActive()) return -1;
         if (!isActive() && other.isActive()) return 1;
 
+        // Higher scores go before lower scores
+        if (mRankingScore != other.mRankingScore) {
+            return (mRankingScore > other.mRankingScore) ? -1 : 1;
+        }
+
         // Reachable one goes before unreachable one.
         if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
         if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
@@ -268,9 +282,38 @@
         if (security != SECURITY_NONE) {
             builder.append(',').append(securityToString(security, pskType));
         }
+        builder.append(",rankingScore=").append(mRankingScore);
+        builder.append(",badge=").append(mBadge);
+
         return builder.append(')').toString();
     }
 
+    /**
+     * Updates the AccessPoint rankingScore and badge, returning true if the data has changed.
+     *
+     * @param scoreCache The score cache to use to retrieve scores.
+     */
+    boolean updateScores(WifiNetworkScoreCache scoreCache) {
+        int oldBadge = mBadge;
+        int oldRankingScore = mRankingScore;
+        mBadge = ScoredNetwork.BADGING_NONE;
+        mRankingScore = Integer.MIN_VALUE;
+
+        for (ScanResult result : mScanResultCache.values()) {
+            ScoredNetwork score = scoreCache.getScoredNetwork(result);
+            if (score == null) {
+                continue;
+            }
+
+            if (score.hasRankingScore()) {
+                mRankingScore = Math.max(mRankingScore, score.calculateRankingScore(result.level));
+            }
+            mBadge = Math.max(mBadge, score.calculateBadge(result.level));
+        }
+
+        return (oldBadge != mBadge || oldRankingScore != mRankingScore);
+    }
+
     private void evictOldScanResults() {
         long nowMs = SystemClock.elapsedRealtime();
         for (Iterator<ScanResult> iter = mScanResultCache.values().iterator(); iter.hasNext(); ) {
@@ -555,6 +598,8 @@
             visibility.append(" rssi=").append(mInfo.getRssi());
             visibility.append(" ");
             visibility.append(" score=").append(mInfo.score);
+            visibility.append(" rankingScore=").append(getRankingScore());
+            visibility.append(" badge=").append(getBadge());
             visibility.append(String.format(" tx=%.1f,", mInfo.txSuccessRate));
             visibility.append(String.format("%.1f,", mInfo.txRetriesRate));
             visibility.append(String.format("%.1f ", mInfo.txBadRate));
@@ -820,6 +865,14 @@
         mRssi = rssi;
     }
 
+    int getRankingScore() {
+        return mRankingScore;
+    }
+
+    int getBadge() {
+        return mBadge;
+    }
+
     public static String getSummary(Context context, String ssid, DetailedState state,
             boolean isEphemeral, String passpointProvider) {
         if (state == DetailedState.CONNECTED && ssid == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index aae9cf6..8ebea61 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -18,8 +18,12 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.graphics.drawable.StateListDrawable;
+import android.net.ScoredNetwork;
 import android.net.wifi.WifiConfiguration;
 import android.os.Looper;
 import android.os.UserHandle;
@@ -28,19 +32,27 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.SparseArray;
+import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.settingslib.R;
+import com.android.settingslib.Utils;
 
 public class AccessPointPreference extends Preference {
 
     private static final int[] STATE_SECURED = {
             R.attr.state_encrypted
     };
+    private static final int[] STATE_SAVED = {
+            R.attr.state_encrypted,
+            R.attr.state_saved
+    };
     private static final int[] STATE_NONE = {};
 
-    private static int[] wifi_signal_attributes = { R.attr.wifi_signal };
+    private static final int[] wifi_signal_attributes = { R.attr.wifi_signal };
+    private static final int[] wifi_friction_attributes = { R.attr.wifi_friction };
 
     private final StateListDrawable mWifiSld;
+    private final StateListDrawable mFrictionSld;
     private final int mBadgePadding;
     private final UserBadgeCache mBadgeCache;
     private TextView mTitleView;
@@ -51,6 +63,9 @@
     private int mLevel;
     private CharSequence mContentDescription;
     private int mDefaultIconResId;
+    private int mIconWidth;
+    private int mIconHeight;
+    private int mWifiBadge = ScoredNetwork.BADGING_NONE;
 
     static final int[] WIFI_CONNECTION_STRENGTH = {
             R.string.accessibility_wifi_one_bar,
@@ -63,6 +78,7 @@
     public AccessPointPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
         mWifiSld = null;
+        mFrictionSld = null;
         mBadgePadding = 0;
         mBadgeCache = null;
     }
@@ -70,6 +86,7 @@
     public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache,
             boolean forSavedNetworks) {
         super(context);
+        setWidgetLayoutResource(R.layout.access_point_friction_widget);
         mBadgeCache = cache;
         mAccessPoint = accessPoint;
         mForSavedNetworks = forSavedNetworks;
@@ -78,6 +95,17 @@
 
         mWifiSld = (StateListDrawable) context.getTheme()
                 .obtainStyledAttributes(wifi_signal_attributes).getDrawable(0);
+        // Save icon width and height to use for creating a badged icon
+        setIconWidthAndHeight();
+
+        TypedArray frictionSld;
+        try {
+            frictionSld = context.getTheme().obtainStyledAttributes(wifi_friction_attributes);
+        } catch (Resources.NotFoundException e) {
+            // Fallback for platforms that do not need friction icon resources.
+            frictionSld = null;
+        }
+        mFrictionSld = frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null;
 
         // Distance from the end of the title at which this AP's user badge should sit.
         mBadgePadding = context.getResources()
@@ -88,6 +116,7 @@
     public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache,
             int iconResId, boolean forSavedNetworks) {
         super(context);
+        setWidgetLayoutResource(R.layout.access_point_friction_widget);
         mBadgeCache = cache;
         mAccessPoint = accessPoint;
         mForSavedNetworks = forSavedNetworks;
@@ -97,12 +126,30 @@
 
         mWifiSld = (StateListDrawable) context.getTheme()
                 .obtainStyledAttributes(wifi_signal_attributes).getDrawable(0);
+        // Save icon width and height to use for creating a badged icon
+        setIconWidthAndHeight();
+
+        TypedArray frictionSld;
+        try {
+            frictionSld = context.getTheme().obtainStyledAttributes(wifi_friction_attributes);
+        } catch (Resources.NotFoundException e) {
+            // Fallback for platforms that do not need friction icon resources.
+            frictionSld = null;
+        }
+        mFrictionSld = frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null;
 
         // Distance from the end of the title at which this AP's user badge should sit.
         mBadgePadding = context.getResources()
                 .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding);
     }
 
+    private void setIconWidthAndHeight() {
+        // TODO(sghuman): Refactor this defined widths and heights into a dimension resource and
+        // reference directly.
+        mIconWidth = mWifiSld.getIntrinsicWidth();
+        mIconHeight = mWifiSld.getIntrinsicHeight();
+    }
+
     public AccessPoint getAccessPoint() {
         return mAccessPoint;
     }
@@ -126,12 +173,27 @@
             mTitleView.setCompoundDrawablePadding(mBadgePadding);
         }
         view.itemView.setContentDescription(mContentDescription);
+
+        if (!mForSavedNetworks) {
+            ImageView frictionImageView = (ImageView) view.findViewById(R.id.friction_icon);
+            bindFrictionImage(frictionImageView);
+        }
     }
 
     protected void updateIcon(int level, Context context) {
         if (level == -1) {
             safeSetDefaultIcon();
         } else {
+           if (mWifiBadge != ScoredNetwork.BADGING_NONE) {
+                // TODO(sghuman): Refactor this to reuse drawable to save memory and add to a
+                // special subclass of AccessPointPreference
+                LayerDrawable drawable = Utils.getBadgedWifiIcon(context, level, mWifiBadge);
+                drawable.setLayerSize(0, mIconWidth, mIconHeight);
+                drawable.setLayerSize(1, mIconWidth, mIconHeight);
+                drawable.setTint(Utils.getColorAccent(getContext()));
+                setIcon(drawable);
+                return;
+            }
             if (getIcon() == null) {
                 // To avoid a drawing race condition, we first set the state (SECURE/NONE) and then
                 // set the icon (drawable) to that state's drawable.
@@ -152,6 +214,27 @@
         }
     }
 
+    /**
+     * Binds the friction icon drawable using a StateListDrawable.
+     *
+     * <p>Friction icons will be rebound when notifyChange() is called, and therefore
+     * do not need to be managed in refresh()</p>.
+     */
+    private void bindFrictionImage(ImageView frictionImageView) {
+        if (frictionImageView == null || mFrictionSld == null) {
+            return;
+        }
+        if (mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
+            if (mAccessPoint.isSaved()) {
+                mFrictionSld.setState(STATE_SAVED);
+            } else {
+                mFrictionSld.setState(STATE_SECURED);
+            }
+        }
+        Drawable drawable = mFrictionSld.getCurrent();
+        frictionImageView.setImageDrawable(drawable);
+    }
+
     private void safeSetDefaultIcon() {
         if (mDefaultIconResId != 0) {
             setIcon(mDefaultIconResId);
@@ -182,11 +265,14 @@
 
         final Context context = getContext();
         int level = mAccessPoint.getLevel();
-        if (level != mLevel) {
+        int wifiBadge = mAccessPoint.getBadge();
+        if (level != mLevel || wifiBadge != mWifiBadge) {
             mLevel = level;
+            mWifiBadge = wifiBadge;
             updateIcon(mLevel, context);
             notifyChanged();
         }
+
         updateBadge(context);
 
         setSummary(mForSavedNetworks ? mAccessPoint.getSavedNetworkSummary()
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 77a45b3..799f388 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -24,15 +24,22 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkKey;
 import android.net.NetworkRequest;
+import android.net.NetworkScoreManager;
+import android.net.ScoredNetwork;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
+import android.net.wifi.WifiNetworkScoreCache;
+import android.net.wifi.WifiNetworkScoreCache.CacheListener;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.support.annotation.WorkerThread;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
@@ -49,14 +56,18 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Tracks saved or available wifi networks and their state.
  */
 public class WifiTracker {
+    // TODO(sghuman): Document remaining methods with @UiThread and @WorkerThread where possible.
+    // TODO(sghuman): Refactor to avoid calling certain methods on the UiThread.
+
     private static final String TAG = "WifiTracker";
-    private static final boolean DBG = false;
+    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
 
     /** verbose logging flag. this flag is set thru developer debugging options
      * and used so as to assist with in-the-field WiFi connectivity debugging  */
@@ -122,6 +133,10 @@
     private NetworkInfo mLastNetworkInfo;
     private WifiInfo mLastInfo;
 
+    private final NetworkScoreManager mNetworkScoreManager;
+    private final WifiNetworkScoreCache mScoreCache;
+    private final Set<NetworkKey> mRequestedScores = new ArraySet<>();
+
     @VisibleForTesting
     Scanner mScanner;
 
@@ -144,14 +159,16 @@
             boolean includeSaved, boolean includeScans, boolean includePasspoints) {
         this(context, wifiListener, workerLooper, includeSaved, includeScans, includePasspoints,
                 context.getSystemService(WifiManager.class),
-                context.getSystemService(ConnectivityManager.class), Looper.myLooper());
+                context.getSystemService(ConnectivityManager.class),
+                context.getSystemService(NetworkScoreManager.class), Looper.myLooper()
+        );
     }
 
     @VisibleForTesting
     WifiTracker(Context context, WifiListener wifiListener, Looper workerLooper,
             boolean includeSaved, boolean includeScans, boolean includePasspoints,
             WifiManager wifiManager, ConnectivityManager connectivityManager,
-            Looper currentLooper) {
+            NetworkScoreManager networkScoreManager, Looper currentLooper) {
         if (!includeSaved && !includeScans) {
             throw new IllegalArgumentException("Must include either saved or scans");
         }
@@ -186,6 +203,18 @@
                 .clearCapabilities()
                 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                 .build();
+
+        mNetworkScoreManager = networkScoreManager;
+
+        mScoreCache = new WifiNetworkScoreCache(context, new CacheListener(mWorkHandler) {
+            @Override
+            public void networkCacheUpdated(List<ScoredNetwork> networks) {
+                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                    Log.v(TAG, "Score cache was updated with networks: " + networks);
+                }
+                Message.obtain(mWorkHandler, WorkHandler.MSG_UPDATE_NETWORK_SCORES).sendToTarget();
+            }
+        });
     }
 
     /**
@@ -216,6 +245,8 @@
 
     /**
      * Resume scanning for wifi networks after it has been paused.
+     *
+     * <p>The score cache should be registered before this method is invoked.
      */
     public void resumeScanning() {
         if (mScanner == null) {
@@ -230,11 +261,20 @@
     }
 
     /**
-     * Start tracking wifi networks.
-     * Registers listeners and starts scanning for wifi networks. If this is not called
+     * Start tracking wifi networks and scores.
+     *
+     * <p>Registers listeners and starts scanning for wifi networks. If this is not called
      * then forceUpdate() must be called to populate getAccessPoints().
      */
     public void startTracking() {
+        mWorkHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                registerScoreCache();
+            }
+        });
+
+
         resumeScanning();
         if (!mRegistered) {
             mContext.registerReceiver(mReceiver, mFilter);
@@ -245,9 +285,28 @@
         }
     }
 
+    @WorkerThread
+    private void registerScoreCache() {
+        mNetworkScoreManager.registerNetworkScoreCache(
+                NetworkKey.TYPE_WIFI,
+                mScoreCache,
+                NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
+    }
+
+    private void requestScoresForNetworkKeys(Collection<NetworkKey> keys) {
+        if (keys.isEmpty()) return;
+
+        if (DBG) {
+            Log.d(TAG, "Requesting scores for Network Keys: " + keys);
+        }
+        mNetworkScoreManager.requestScores(keys.toArray(new NetworkKey[keys.size()]));
+        mRequestedScores.addAll(keys);
+    }
+
     /**
-     * Stop tracking wifi networks.
-     * Unregisters all listeners and stops scanning for wifi networks. This should always
+     * Stop tracking wifi networks and scores.
+     *
+     * <p>Unregisters all listeners and stops scanning for wifi networks. This should always
      * be called when done with a WifiTracker (if startTracking was called) to ensure
      * proper cleanup.
      */
@@ -255,11 +314,26 @@
         if (mRegistered) {
             mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_ACCESS_POINTS);
             mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_NETWORK_INFO);
+            mWorkHandler.removeMessages(WorkHandler.MSG_UPDATE_NETWORK_SCORES);
             mContext.unregisterReceiver(mReceiver);
             mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
             mRegistered = false;
         }
         pauseScanning();
+
+        mWorkHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                unregisterAndClearScoreCache();
+            }
+        });
+    }
+
+    @WorkerThread
+    private void unregisterAndClearScoreCache() {
+        mRequestedScores.clear();
+        mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, mScoreCache);
+        mScoreCache.clearScores();
     }
 
     /**
@@ -415,6 +489,7 @@
             }
         }
 
+        final List<NetworkKey> scoresToRequest = new ArrayList<>();
         if (results != null) {
             for (ScanResult result : results) {
                 // Ignore hidden and ad-hoc networks.
@@ -423,6 +498,11 @@
                     continue;
                 }
 
+                NetworkKey key = NetworkKey.createFromScanResult(result);
+                if (!mRequestedScores.contains(key)) {
+                    scoresToRequest.add(key);
+                }
+
                 boolean found = false;
                 for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
                     if (accessPoint.update(result)) {
@@ -457,27 +537,35 @@
             }
         }
 
+
+        requestScoresForNetworkKeys(scoresToRequest);
+        for (AccessPoint ap : accessPoints) {
+            ap.updateScores(mScoreCache);
+        }
+
         // Pre-sort accessPoints to speed preference insertion
         Collections.sort(accessPoints);
 
         // Log accesspoints that were deleted
-        if (DBG) Log.d(TAG, "------ Dumping SSIDs that were not seen on this scan ------");
-        for (AccessPoint prevAccessPoint : mInternalAccessPoints) {
-            if (prevAccessPoint.getSsid() == null)
-                continue;
-            String prevSsid = prevAccessPoint.getSsidStr();
-            boolean found = false;
-            for (AccessPoint newAccessPoint : accessPoints) {
-                if (newAccessPoint.getSsid() != null && newAccessPoint.getSsid()
-                        .equals(prevSsid)) {
-                    found = true;
-                    break;
+        if (DBG) {
+            Log.d(TAG, "------ Dumping SSIDs that were not seen on this scan ------");
+            for (AccessPoint prevAccessPoint : mInternalAccessPoints) {
+                if (prevAccessPoint.getSsid() == null)
+                    continue;
+                String prevSsid = prevAccessPoint.getSsidStr();
+                boolean found = false;
+                for (AccessPoint newAccessPoint : accessPoints) {
+                    if (newAccessPoint.getSsid() != null && newAccessPoint.getSsid()
+                            .equals(prevSsid)) {
+                        found = true;
+                        break;
+                    }
                 }
+                if (!found)
+                    Log.d(TAG, "Did not find " + prevSsid + " in this scan");
             }
-            if (!found)
-                if (DBG) Log.d(TAG, "Did not find " + prevSsid + " in this scan");
+            Log.d(TAG, "---- Done dumping SSIDs that were not seen on this scan ----");
         }
-        if (DBG) Log.d(TAG, "---- Done dumping SSIDs that were not seen on this scan ----");
 
         mInternalAccessPoints.clear();
         mInternalAccessPoints.addAll(accessPoints);
@@ -549,7 +637,38 @@
 
         boolean reorder = false;
         for (int i = mInternalAccessPoints.size() - 1; i >= 0; --i) {
-            if (mInternalAccessPoints.get(i).update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
+            AccessPoint ap = mInternalAccessPoints.get(i);
+            if (ap.update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
+                reorder = true;
+            }
+            if (ap.updateScores(mScoreCache)) {
+                reorder = true;
+            }
+        }
+        if (reorder) {
+            Collections.sort(mInternalAccessPoints);
+            mMainHandler.scheduleAPCopyingAndCloseWriteLock();
+        }
+    }
+
+    /**
+     * Update all the internal access points rankingScores and badge.
+     *
+     * <p>Will trigger a resort and notify listeners of changes if applicable.
+     */
+    private void updateNetworkScores() {
+        // Lock required to prevent accidental copying of AccessPoint states while the modification
+        // is in progress. see #copyAndNotifyListeners
+        long before = System.currentTimeMillis();
+        mInternalAccessPointsWriteLock.block();
+        if (DBG) {
+            Log.d(TAG, "Acquired AP lock on WorkerHandler for inserting NetworkScores. Wait time = " +
+                    (System.currentTimeMillis() - before) + "ms.");
+        }
+
+        boolean reorder = false;
+        for (int i = 0; i < mInternalAccessPoints.size(); i++) {
+            if (mInternalAccessPoints.get(i).updateScores(mScoreCache)) {
                 reorder = true;
             }
         }
@@ -661,6 +780,7 @@
         private static final int MSG_UPDATE_NETWORK_INFO = 1;
         private static final int MSG_RESUME = 2;
         private static final int MSG_UPDATE_WIFI_STATE = 3;
+        private static final int MSG_UPDATE_NETWORK_SCORES = 4;
 
         public WorkHandler(Looper looper) {
             super(looper);
@@ -695,6 +815,9 @@
                     mMainHandler.obtainMessage(MainHandler.MSG_WIFI_STATE_CHANGED, msg.arg1, 0)
                             .sendToTarget();
                     break;
+                case MSG_UPDATE_NETWORK_SCORES:
+                    updateNetworkScores();
+                    break;
             }
         }
     }
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index 4208522..98bce0c 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -27,7 +27,8 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-test \
     espresso-core \
-    mockito-target-minus-junit4
+    mockito-target-minus-junit4 \
+    legacy-android-test
 
 include frameworks/base/packages/SettingsLib/common.mk
 
diff --git a/packages/SettingsLib/tests/integ/AndroidManifest.xml b/packages/SettingsLib/tests/integ/AndroidManifest.xml
index 00b2164..0d5ff2c 100644
--- a/packages/SettingsLib/tests/integ/AndroidManifest.xml
+++ b/packages/SettingsLib/tests/integ/AndroidManifest.xml
@@ -22,6 +22,7 @@
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY"/>
     <uses-permission android:name="android.permission.SET_TIME_ZONE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 
 
     <application>
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index c650190..eaf0367 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -15,29 +15,278 @@
  */
 package com.android.settingslib.wifi;
 
-
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkKey;
+import android.net.NetworkScoreManager;
+import android.net.ScoredNetwork;
+import android.net.RssiCurve;
+import android.net.WifiKey;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiNetworkScoreCache;
+import android.net.wifi.WifiSsid;
+import android.os.Bundle;
 import android.os.SystemClock;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.provider.Settings;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import org.mockito.ArgumentCaptor;
+import org.mockito.Matchers;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.List;
-
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class WifiTrackerTest {
 
+    private static final String TAG = "WifiTrackerTest";
+    private static final int LATCH_TIMEOUT = 2000;
+
+    private static final String SSID_1 = "ssid1";
+    private static final String BSSID_1 = "00:00:00:00:00:00";
+    private static final NetworkKey NETWORK_KEY_1 =
+            new NetworkKey(new WifiKey('"' + SSID_1 + '"', BSSID_1));
+    private static final int RSSI_1 = -30;
+    private static final byte SCORE_1 = 10;
+    private static final int BADGE_1 = ScoredNetwork.BADGING_SD;
+
+    private static final String SSID_2 = "ssid2";
+    private static final String BSSID_2 = "AA:AA:AA:AA:AA:AA";
+    private static final NetworkKey NETWORK_KEY_2 =
+            new NetworkKey(new WifiKey('"' + SSID_2 + '"', BSSID_2));
+    private static final int RSSI_2 = -30;
+    private static final byte SCORE_2 = 15;
+    private static final int BADGE_2 = ScoredNetwork.BADGING_HD;
+
+    @Captor ArgumentCaptor<WifiNetworkScoreCache> mScoreCacheCaptor;
+    @Mock private ConnectivityManager mockConnectivityManager;
+    @Mock private NetworkScoreManager mockNetworkScoreManager;
+    @Mock private RssiCurve mockCurve1;
+    @Mock private RssiCurve mockCurve2;
+    @Mock private RssiCurve mockBadgeCurve1;
+    @Mock private RssiCurve mockBadgeCurve2;
+    @Mock private WifiManager mockWifiManager;
+    @Mock private WifiTracker.WifiListener mockWifiListener;
+
+    private final List<NetworkKey> mRequestedKeys = new ArrayList<>();
+
+    private Context mContext;
+    private CountDownLatch mAccessPointsChangedLatch;
+    private CountDownLatch mRequestScoresLatch;
+    private Handler mScannerHandler;
+    private HandlerThread mMainThread;
+    private HandlerThread mWorkerThread;
+    private Looper mLooper;
+    private Looper mMainLooper;
+    private int mOriginalSettingValue;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        MockitoAnnotations.initMocks(this);
+
+        mWorkerThread = new HandlerThread("TestHandlerWorkerThread");
+        mWorkerThread.start();
+        mLooper = mWorkerThread.getLooper();
+        mMainThread = new HandlerThread("TestHandlerThread");
+        mMainThread.start();
+        mMainLooper = mMainThread.getLooper();
+
+        // Make sure the scanner doesn't try to run on the testing thread.
+        HandlerThread scannerThread = new HandlerThread("ScannerWorkerThread");
+        scannerThread.start();
+        mScannerHandler = new Handler(scannerThread.getLooper());
+
+        when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mockWifiManager.getScanResults())
+                .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2()));
+
+
+        when(mockCurve1.lookupScore(RSSI_1)).thenReturn(SCORE_1);
+        when(mockCurve2.lookupScore(RSSI_2)).thenReturn(SCORE_2);
+
+        when(mockBadgeCurve1.lookupScore(RSSI_1)).thenReturn((byte) BADGE_1);
+        when(mockBadgeCurve2.lookupScore(RSSI_2)).thenReturn((byte) BADGE_2);
+
+        doNothing()
+                .when(mockNetworkScoreManager)
+                .registerNetworkScoreCache(
+                        anyInt(),
+                        mScoreCacheCaptor.capture(),
+                        Matchers.anyInt());
+
+        // Capture requested keys and count down latch if present
+        doAnswer(
+                new Answer<Boolean>() {
+                    @Override
+                    public Boolean answer(InvocationOnMock input) {
+                        if (mRequestScoresLatch != null) {
+                            mRequestScoresLatch.countDown();
+                        }
+                        NetworkKey[] keys = (NetworkKey[]) input.getArguments()[0];
+                        for (NetworkKey key : keys) {
+                            mRequestedKeys.add(key);
+                        }
+                        return true;
+                    }
+                }).when(mockNetworkScoreManager).requestScores(Matchers.<NetworkKey[]>any());
+
+        doAnswer(
+                new Answer<Void>() {
+                  @Override
+                  public Void answer (InvocationOnMock invocation) throws Throwable {
+                    if (mAccessPointsChangedLatch != null) {
+                      mAccessPointsChangedLatch.countDown();
+                    }
+
+                    return null;
+                  }
+                }).when(mockWifiListener).onAccessPointsChanged();
+
+        mOriginalSettingValue = Settings.Global.getInt(
+            InstrumentationRegistry.getTargetContext().getContentResolver(),
+            Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+            0 /* disabled */);
+
+    }
+
+    @After
+    public void cleanUp() {
+        Settings.Global.putInt(
+            InstrumentationRegistry.getTargetContext().getContentResolver(),
+            Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+            mOriginalSettingValue);
+    }
+
+    private static ScanResult buildScanResult1() {
+        return new ScanResult(
+                WifiSsid.createFromAsciiEncoded(SSID_1),
+                BSSID_1,
+                0, // hessid
+                0, //anqpDomainId
+                null, // osuProviders
+                "", // capabilities
+                RSSI_1,
+                0, // frequency
+                SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
+    }
+
+    private static ScanResult buildScanResult2() {
+        return new ScanResult(
+                WifiSsid.createFromAsciiEncoded(SSID_2),
+                BSSID_2,
+                0, // hessid
+                0, //anqpDomainId
+                null, // osuProviders
+                "", // capabilities
+                RSSI_2,
+                0, // frequency
+                SystemClock.elapsedRealtime() * 1000 /* microsecond timestamp */);
+    }
+
+    private WifiTracker createTrackerAndInjectInitialScanResults() throws InterruptedException {
+        WifiTracker tracker = createMockedWifiTracker();
+        startTracking(tracker);
+
+        mAccessPointsChangedLatch = new CountDownLatch(1);
+        sendScanResultsAndProcess(tracker);
+        mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        return tracker;
+    }
+
+    private WifiTracker createMockedWifiTracker() {
+        WifiTracker tracker =
+                new WifiTracker(
+                    mContext,
+                    mockWifiListener,
+                    mLooper,
+                    true,
+                    true,
+                    true,
+                    mockWifiManager,
+                    mockConnectivityManager,
+                        mockNetworkScoreManager, mMainLooper
+                );
+
+        return tracker;
+    }
+
+    private void startTracking(WifiTracker tracker)  throws InterruptedException {
+        CountDownLatch latch = new CountDownLatch(1);
+        mScannerHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                tracker.startTracking();
+                latch.countDown();
+            }
+        });
+        latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+    }
+
+    private void sendScanResultsAndProcess(WifiTracker tracker) throws InterruptedException {
+        mAccessPointsChangedLatch = new CountDownLatch(1);
+        Intent i = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+        tracker.mReceiver.onReceive(mContext, i);
+
+        mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+    }
+
+    private void updateScores() {
+        Bundle attr1 = new Bundle();
+        attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve1);
+        ScoredNetwork sc1 =
+                new ScoredNetwork(
+                        NETWORK_KEY_1,
+                        mockCurve1,
+                        false /* meteredHint */,
+                        attr1);
+
+        Bundle attr2 = new Bundle();
+        attr2.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve2);
+        ScoredNetwork sc2 =
+                new ScoredNetwork(
+                        NETWORK_KEY_2,
+                        mockCurve2,
+                        false /* meteredHint */,
+                        attr2);
+
+        WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue();
+        scoreCache.updateScores(Arrays.asList(sc1, sc2));
+    }
+
     @Test
     public void testAccessPointListenerSetWhenLookingUpUsingScanResults() {
         ScanResult scanResult = new ScanResult();
@@ -47,7 +296,7 @@
         scanResult.capabilities = "";
 
         WifiTracker tracker = new WifiTracker(
-                InstrumentationRegistry.getTargetContext(), null, true, true);
+                InstrumentationRegistry.getTargetContext(), null, mLooper, true, true);
 
         AccessPoint result = tracker.getCachedOrCreate(scanResult, new ArrayList<AccessPoint>());
         assertTrue(result.mAccessPointListener != null);
@@ -63,9 +312,125 @@
         configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
 
         WifiTracker tracker = new WifiTracker(
-                InstrumentationRegistry.getTargetContext(), null, true, true);
+                InstrumentationRegistry.getTargetContext(), null, mLooper, true, true);
 
         AccessPoint result = tracker.getCachedOrCreate(configuration, new ArrayList<AccessPoint>());
         assertTrue(result.mAccessPointListener != null);
     }
+
+    @Test
+    public void startAndStopTrackingShouldRegisterAndUnregisterScoreCache()
+            throws InterruptedException {
+        WifiTracker tracker = createMockedWifiTracker();
+
+        // Test register
+        startTracking(tracker);
+        verify(mockNetworkScoreManager)
+                .registerNetworkScoreCache(
+                          Matchers.anyInt(),
+                          mScoreCacheCaptor.capture(),
+                          Matchers.anyInt());
+
+        WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue();
+
+        // Test unregister
+        tracker.stopTracking();
+
+        verify(mockNetworkScoreManager)
+                .unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache);
+    }
+
+    @Test
+    public void startTrackingShouldRequestScoresForCurrentAccessPoints() throws InterruptedException {
+        // Start the tracker and inject the initial scan results and then stop tracking
+        WifiTracker tracker =  createTrackerAndInjectInitialScanResults();
+
+        tracker.stopTracking();
+        mRequestedKeys.clear();
+
+        mRequestScoresLatch = new CountDownLatch(2);
+        startTracking(tracker);
+        mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        assertTrue(mRequestedKeys.contains(NETWORK_KEY_1));
+        assertTrue(mRequestedKeys.contains(NETWORK_KEY_2));
+    }
+
+    @Test
+    public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged() throws InterruptedException {
+        WifiTracker tracker = createMockedWifiTracker();
+        startTracking(tracker);
+        sendScanResultsAndProcess(tracker);
+
+        updateScoresAndWaitForAccessPointsChangedCallback();
+    }
+
+    private void updateScoresAndWaitForAccessPointsChangedCallback() throws InterruptedException {
+        mAccessPointsChangedLatch = new CountDownLatch(2);
+        updateScores();
+        mAccessPointsChangedLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+    }
+
+    @Test
+    public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
+        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        List<AccessPoint> aps = tracker.getAccessPoints();
+        assertTrue(aps.size() == 2);
+        assertEquals(aps.get(0).getSsidStr(), SSID_1);
+        assertEquals(aps.get(1).getSsidStr(), SSID_2);
+
+        updateScoresAndWaitForAccessPointsChangedCallback();
+
+        aps = tracker.getAccessPoints();
+        assertTrue(aps.size() == 2);
+        assertEquals(aps.get(0).getSsidStr(), SSID_2);
+        assertEquals(aps.get(1).getSsidStr(), SSID_1);
+
+    }
+
+    @Test
+    public void scoreCacheUpdateScoresShouldInsertBadgeIntoAccessPoint() throws InterruptedException {
+        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        updateScoresAndWaitForAccessPointsChangedCallback();
+
+        List<AccessPoint> aps = tracker.getAccessPoints();
+
+        for (AccessPoint ap : aps) {
+            if (ap.getSsidStr().equals(SSID_1)) {
+                assertEquals(BADGE_1, ap.getBadge());
+            } else if (ap.getSsidStr().equals(SSID_2)) {
+                assertEquals(BADGE_2, ap.getBadge());
+            }
+        }
+    }
+
+    @Test
+    public void scoresShouldBeRequestedForNewScanResultOnly()  throws InterruptedException {
+        mRequestScoresLatch = new CountDownLatch(2);
+        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+        mRequestedKeys.clear();
+
+        String ssid = "ssid3";
+        String bssid = "00:00:00:00:00:00";
+        ScanResult newResult = new ScanResult(
+                WifiSsid.createFromAsciiEncoded(ssid),
+                bssid,
+                0, // hessid
+                0, //anqpDomainId
+                null, // osuProviders
+                "", // capabilities
+                RSSI_1,
+                0, // frequency
+                SystemClock.elapsedRealtime() * 1000);
+        when(mockWifiManager.getScanResults())
+                .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2(), newResult));
+
+        mRequestScoresLatch = new CountDownLatch(1);
+        sendScanResultsAndProcess(tracker);
+        mRequestScoresLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
+
+        assertEquals(1, mRequestedKeys.size());
+        assertTrue(mRequestedKeys.contains(new NetworkKey(new WifiKey('"' + ssid + '"', bssid))));
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index d8082c4..c95cac5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -255,6 +255,7 @@
 
         Bundle bundle = new Bundle();
         bundle.putInt("com.android.settings.icon", 161803);
+        bundle.putString("com.android.settings.icon_package", "abc");
         bundle.putString("com.android.settings.summary", "dynamic-summary");
         when(mIContentProvider.call(anyString(),
                 eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_ICON))), eq(URI_GET_ICON), any()))
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 058e38a..527631e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -271,6 +271,7 @@
 
     @Override
     public boolean onCreate() {
+        Settings.setInSystemServer();
         synchronized (mLock) {
             mUserManager = UserManager.get(getContext());
             mPackageManager = AppGlobals.getPackageManager();
@@ -829,7 +830,8 @@
             SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
                     SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
 
-            List<String> names = settingsState.getSettingNamesLocked();
+            List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_GLOBAL,
+                    UserHandle.USER_SYSTEM);
 
             final int nameCount = names.size();
 
@@ -852,6 +854,9 @@
             Slog.v(LOG_TAG, "getGlobalSetting(" + name + ")");
         }
 
+        // Ensure the caller can access the setting.
+        enforceSettingReadable(name, SETTINGS_TYPE_GLOBAL, UserHandle.getCallingUserId());
+
         // Get the value.
         synchronized (mLock) {
             return mSettingsRegistry.getSettingLocked(SETTINGS_TYPE_GLOBAL,
@@ -954,8 +959,7 @@
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
 
         synchronized (mLock) {
-            List<String> names = mSettingsRegistry.getSettingsNamesLocked(
-                    SETTINGS_TYPE_SECURE, callingUserId);
+            List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SECURE, callingUserId);
 
             final int nameCount = names.size();
 
@@ -997,6 +1001,9 @@
         // Resolve the userId on whose behalf the call is made.
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
 
+        // Ensure the caller can access the setting.
+        enforceSettingReadable(name, SETTINGS_TYPE_SECURE, callingUserId);
+
         // Determine the owning user as some profile settings are cloned from the parent.
         final int owningUserId = resolveOwningUserIdForSecureSettingLocked(callingUserId, name);
 
@@ -1039,7 +1046,7 @@
                 name);
 
         // Lazy initialize ssaid if not yet present in ssaid table.
-        if (ssaid.isNull() || ssaid.getValue() == null) {
+        if (ssaid == null || ssaid.isNull() || ssaid.getValue() == null) {
             return mSettingsRegistry.generateSsaidLocked(getCallingPackage(), owningUserId);
         }
 
@@ -1159,8 +1166,7 @@
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(userId);
 
         synchronized (mLock) {
-            List<String> names = mSettingsRegistry.getSettingsNamesLocked(
-                    SETTINGS_TYPE_SYSTEM, callingUserId);
+            List<String> names = getSettingsNamesLocked(SETTINGS_TYPE_SYSTEM, callingUserId);
 
             final int nameCount = names.size();
 
@@ -1191,6 +1197,9 @@
         // Resolve the userId on whose behalf the call is made.
         final int callingUserId = resolveCallingUserIdEnforcingPermissionsLocked(requestingUserId);
 
+        // Ensure the caller can access the setting.
+        enforceSettingReadable(name, SETTINGS_TYPE_SYSTEM, callingUserId);
+
         // Determine the owning user as some profile settings are cloned from the parent.
         final int owningUserId = resolveOwningUserIdForSystemSettingLocked(callingUserId, name);
 
@@ -1409,9 +1418,15 @@
                 && (parentId = getGroupParentLocked(userId)) != userId) {
             // The setting has a dependency and the profile has a parent
             String dependency = sSystemCloneFromParentOnDependency.get(setting);
-            Setting settingObj = getSecureSetting(dependency, userId);
-            if (settingObj != null && settingObj.getValue().equals("1")) {
-                return parentId;
+            // Lookup the dependency setting as ourselves, some callers may not have access to it.
+            final long token = Binder.clearCallingIdentity();
+            try {
+                Setting settingObj = getSecureSetting(dependency, userId);
+                if (settingObj != null && settingObj.getValue().equals("1")) {
+                    return parentId;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
             }
         }
         return resolveOwningUserIdLocked(userId, sSystemCloneToManagedSettings, setting);
@@ -1479,6 +1494,55 @@
         }
     }
 
+    private Set<String> getEphemeralAccessibleSettings(int settingsType) {
+        switch (settingsType) {
+            case SETTINGS_TYPE_GLOBAL:
+                return Settings.Global.EPHEMERAL_SETTINGS;
+            case SETTINGS_TYPE_SECURE:
+                return Settings.Secure.EPHEMERAL_SETTINGS;
+            case SETTINGS_TYPE_SYSTEM:
+                return Settings.System.EPHEMERAL_SETTINGS;
+            default:
+                throw new IllegalArgumentException("Invalid settings type: " + settingsType);
+        }
+    }
+
+    private List<String> getSettingsNamesLocked(int settingsType, int userId) {
+        ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId);
+        if (ai.isEphemeralApp()) {
+            return new ArrayList<String>(getEphemeralAccessibleSettings(settingsType));
+        } else {
+            return mSettingsRegistry.getSettingsNamesLocked(settingsType, userId);
+        }
+    }
+
+    private void enforceSettingReadable(String settingName, int settingsType, int userId) {
+        if (UserHandle.getAppId(Binder.getCallingUid()) < Process.FIRST_APPLICATION_UID) {
+            return;
+        }
+        ApplicationInfo ai = getCallingApplicationInfoOrThrow(userId);
+        if (!ai.isEphemeralApp()) {
+            return;
+        }
+        if (!getEphemeralAccessibleSettings(settingsType).contains(settingName)) {
+            throw new SecurityException("Setting " + settingName + " is not accessible from"
+                    + " ephemeral package " + getCallingPackage());
+        }
+    }
+
+    private ApplicationInfo getCallingApplicationInfoOrThrow(int userId) {
+        ApplicationInfo ai = null;
+        try {
+            ai = mPackageManager.getApplicationInfo(getCallingPackage(), 0 , userId);
+        } catch (RemoteException ignored) {
+        }
+        if (ai == null) {
+            throw new IllegalStateException("Failed to lookup info for package "
+                    + getCallingPackage());
+        }
+        return ai;
+    }
+
     private PackageInfo getCallingPackageInfoOrThrow(int userId) {
         try {
             PackageInfo packageInfo = mPackageManager.getPackageInfo(
@@ -1548,7 +1612,7 @@
         value = value.substring(1);
 
         Setting settingValue = getSecureSetting(
-                Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
+                    Settings.Secure.LOCATION_PROVIDERS_ALLOWED, owningUserId);
         if (settingValue == null) {
             return false;
         }
@@ -1923,11 +1987,13 @@
 
             // Read the user's key from the ssaid table.
             Setting userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY);
-            if (userKeySetting.isNull() || userKeySetting.getValue() == null) {
+            if (userKeySetting == null || userKeySetting.isNull()
+                    || userKeySetting.getValue() == null) {
                 // Lazy initialize and store the user key.
                 generateUserKeyLocked(userId);
                 userKeySetting = getSettingLocked(SETTINGS_TYPE_SSAID, userId, SSAID_USER_KEY);
-                if (userKeySetting.isNull() || userKeySetting.getValue() == null) {
+                if (userKeySetting == null || userKeySetting.isNull()
+                        || userKeySetting.getValue() == null) {
                     throw new IllegalStateException("User key not accessible");
                 }
             }
@@ -2165,7 +2231,7 @@
 
             SettingsState settingsState = peekSettingsStateLocked(key);
             if (settingsState == null) {
-                return settingsState.getNullSetting();
+                return null;
             }
 
             // getSettingLocked will return non-null result
@@ -2999,8 +3065,13 @@
                     // user data or first boot on a new device should use new ssaid generation.
                     if (isUpgrade) {
                         // Retrieve the legacy ssaid from the secure settings table.
-                        final String legacySsaid = getSettingLocked(SETTINGS_TYPE_SECURE, userId,
-                                Settings.Secure.ANDROID_ID).getValue();
+                        final Setting legacySsaidSetting = getSettingLocked(SETTINGS_TYPE_SECURE,
+                                userId, Settings.Secure.ANDROID_ID);
+                        if (legacySsaidSetting == null || legacySsaidSetting.isNull()
+                                || legacySsaidSetting.getValue() == null) {
+                            throw new IllegalStateException("Legacy ssaid not accessible");
+                        }
+                        final String legacySsaid = legacySsaidSetting.getValue();
 
                         // Fill each uid with the legacy ssaid to be backwards compatible.
                         final List<PackageInfo> packages;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index ff76c56..fede34d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -60,6 +60,7 @@
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
     <uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
+    <uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
     <uses-permission android:name="android.permission.CONTROL_VPN" />
     <uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
     <!-- Physical hardware -->
@@ -289,7 +290,7 @@
                   android:resumeWhilePausing="true"
                   android:screenOrientation="behind"
                   android:resizeableActivity="true"
-                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden"
                   android:theme="@style/RecentsTheme.Wallpaper">
             <intent-filter>
                 <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
diff --git a/packages/SystemUI/res/anim/ic_dnd_disable_alpha_animation.xml b/packages/SystemUI/res/anim/ic_dnd_disable_alpha_animation.xml
deleted file mode 100644
index 21caab4..0000000
--- a/packages/SystemUI/res/anim/ic_dnd_disable_alpha_animation.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.3"
-        android:valueType="floatType"
-        android:interpolator="@android:interpolator/linear" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml b/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml
deleted file mode 100644
index 21caab4..0000000
--- a/packages/SystemUI/res/anim/ic_dnd_total_silence_disable_alpha_animation.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.3"
-        android:valueType="floatType"
-        android:interpolator="@android:interpolator/linear" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_hotspot_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_hotspot_disable_animation_root.xml
deleted file mode 100644
index 770c401..0000000
--- a/packages/SystemUI/res/anim/ic_hotspot_disable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.3"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_hotspot_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_hotspot_enable_animation_root.xml
deleted file mode 100644
index 387ca29..0000000
--- a/packages/SystemUI/res/anim/ic_hotspot_enable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="0.3"
-        android:valueTo="1.0"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml
deleted file mode 100644
index 770c401..0000000
--- a/packages/SystemUI/res/anim/ic_invert_colors_disable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.3"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml
deleted file mode 100644
index 387ca29..0000000
--- a/packages/SystemUI/res/anim/ic_invert_colors_enable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="0.3"
-        android:valueTo="1.0"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml
deleted file mode 100644
index 770c401..0000000
--- a/packages/SystemUI/res/anim/ic_signal_airplane_disable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.3"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml
deleted file mode 100644
index 387ca29..0000000
--- a/packages/SystemUI/res/anim/ic_signal_airplane_enable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="0.3"
-        android:valueTo="1.0"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml
deleted file mode 100644
index 770c401..0000000
--- a/packages/SystemUI/res/anim/ic_signal_flashlight_disable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.3"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml
deleted file mode 100644
index 387ca29..0000000
--- a/packages/SystemUI/res/anim/ic_signal_flashlight_enable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="0.3"
-        android:valueTo="1.0"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml
deleted file mode 100644
index 770c401..0000000
--- a/packages/SystemUI/res/anim/ic_signal_location_disable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.3"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml
deleted file mode 100644
index 387ca29..0000000
--- a/packages/SystemUI/res/anim/ic_signal_location_enable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2014 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="0.3"
-        android:valueTo="1.0"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/anim/ic_signal_workmode_disable_animation_root.xml b/packages/SystemUI/res/anim/ic_signal_workmode_disable_animation_root.xml
deleted file mode 100644
index 72834c9..0000000
--- a/packages/SystemUI/res/anim/ic_signal_workmode_disable_animation_root.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-    <objectAnimator
-        android:duration="350"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.3"
-        android:interpolator="@android:interpolator/fast_out_slow_in" />
-</set>
diff --git a/packages/SystemUI/res/drawable/ic_access_alarms_small.xml b/packages/SystemUI/res/drawable/ic_access_alarms_small.xml
index 994274a..b94cc8e 100644
--- a/packages/SystemUI/res/drawable/ic_access_alarms_small.xml
+++ b/packages/SystemUI/res/drawable/ic_access_alarms_small.xml
@@ -18,9 +18,9 @@
     android:height="16dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
-    android:tint="?android:attr/colorControlNormal">
+    android:tint="?android:attr/textColorTertiary">
 
     <path
-        android:fillColor="#64ffffff"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M22.0,5.7l-4.6,-3.9l-1.3,1.5l4.6,3.9L22.0,5.7zM7.9,3.4L6.6,1.9L2.0,5.7l1.3,1.5L7.9,3.4zM12.5,8.0L11.0,8.0l0.0,6.0l4.7,2.9l0.8,-1.2l-4.0,-2.4L12.5,8.0zM12.0,4.0c-5.0,0.0 -9.0,4.0 -9.0,9.0c0.0,5.0 4.0,9.0 9.0,9.0s9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0zM12.0,20.0c-3.9,0.0 -7.0,-3.1 -7.0,-7.0c0.0,-3.9 3.1,-7.0 7.0,-7.0c3.9,0.0 7.0,3.1 7.0,7.0C19.0,16.9 15.9,20.0 12.0,20.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml b/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml
index 13ed767..d755481 100644
--- a/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_dnd_disable_animation.xml
@@ -23,7 +23,4 @@
     <target
         android:name="bar01_0"
         android:animation="@anim/ic_dnd_disable_bar01_0_animation" />
-    <target
-        android:name="ic_dnd_disable"
-        android:animation="@anim/ic_dnd_disable_alpha_animation" />
 </animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml b/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml
index c0b2d69..f796d62 100644
--- a/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_dnd_total_silence_disable_animation.xml
@@ -23,7 +23,4 @@
     <target
         android:name="outer_ring_merged"
         android:animation="@anim/ic_dnd_total_silence_disable_outer_ring_merged_animation" />
-    <target
-        android:name="ic_dnd_total_silence_disable"
-        android:animation="@anim/ic_dnd_total_silence_disable_alpha_animation" />
 </animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_disable_animation.xml b/packages/SystemUI/res/drawable/ic_hotspot_disable_animation.xml
index 694c23f..e446a32 100644
--- a/packages/SystemUI/res/drawable/ic_hotspot_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_hotspot_disable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_hotspot_disable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_hotspot_disable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_hotspot_disable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_enable.xml b/packages/SystemUI/res/drawable/ic_hotspot_enable.xml
index 31e7fe1..7a99630 100644
--- a/packages/SystemUI/res/drawable/ic_hotspot_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_hotspot_enable.xml
@@ -16,12 +16,10 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="root"
-    android:alpha="0.3"
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48" >
     <group
         android:name="ic_hotspot"
         android:translateX="23.97354"
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_enable_animation.xml b/packages/SystemUI/res/drawable/ic_hotspot_enable_animation.xml
index c5187dd..945e42f 100644
--- a/packages/SystemUI/res/drawable/ic_hotspot_enable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_hotspot_enable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_hotspot_enable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_hotspot_enable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_hotspot_enable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml b/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml
index 83f46e5..7641998 100644
--- a/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml
+++ b/packages/SystemUI/res/drawable/ic_hotspot_unavailable.xml
@@ -19,9 +19,7 @@
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:alpha="0.25"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48" >
     <group
         android:name="ic_hotspot"
         android:translateX="23.97354"
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml b/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml
index 476c00d..aeda0a5 100644
--- a/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_disable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_invert_colors_disable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_invert_colors_disable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_invert_colors_disable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml b/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml
index 879066c..85928ac 100644
--- a/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors_enable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_invert_colors_enable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_invert_colors_enable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_invert_colors_enable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml b/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml
new file mode 100644
index 0000000..7b29740
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_battery_saver.xml
@@ -0,0 +1,28 @@
+<!--
+    Copyright (C) 2016 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:autoMirrored="true"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:pathData="M5,3
+        l3.5,0 l0,-1.5 l7,0 l0,1.5 l3.5,0 l0,19.5 l-14,0z
+        M10.5,8.5 l0,3 l-3,0 l0,3 l3,0 l0,3 l3,0 l0,-3 l3,0 l0,-3 l-3,0 l0,-3 z"
+        android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
index 36eb418..3148a2c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_off.xml
@@ -21,6 +21,6 @@
         android:tint="?android:attr/colorControlNormal">
 
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M26.0,11.8l3.8,3.8l-3.2,3.2l2.8,2.8l6.0,-6.0L24.0,4.2l-2.0,0.0l0.0,10.1l4.0,4.0L26.0,11.8zM10.8,8.2L8.0,11.0l13.2,13.2L10.0,35.3l2.8,2.8L22.0,29.0l0.0,15.2l2.0,0.0l8.6,-8.6l4.6,4.6l2.8,-2.8L10.8,8.2zM26.0,36.5L26.0,29.0l3.8,3.8L26.0,36.5z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
index 0fdbe1f..06a0886 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_off.xml
@@ -17,10 +17,9 @@
         android:width="64dp"
         android:height="64dp"
         android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="48.0">
 
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
index d2e9eb2..794eb9e 100644
--- a/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_cast_on.xml
@@ -17,8 +17,7 @@
         android:width="64dp"
         android:height="64dp"
         android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="48.0">
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_circle.xml b/packages/SystemUI/res/drawable/ic_qs_circle.xml
index 57223cf..990cec6 100644
--- a/packages/SystemUI/res/drawable/ic_qs_circle.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_circle.xml
@@ -14,14 +14,13 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="64dp"
-        android:height="64dp"
+        android:width="40dp"
+        android:height="40dp"
         android:viewportWidth="2.2"
         android:viewportHeight="2.2">
 
     <path
-        android:strokeColor="#4DFFFFFF"
-        android:strokeWidth=".05"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M.1,1.1
         c0,.55  .45,1   1,1
         c.55,0  1,-.45  1,-1
diff --git a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
index d11b6f4..439ee3b 100644
--- a/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_data_disabled.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:autoMirrored="true"
-        android:width="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="40.0"
-        android:viewportHeight="40.0">
+        android:width="17dp"
+        android:height="17.0dp"
+        android:viewportWidth="20.0"
+        android:viewportHeight="20.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
index 164a557..9168dbc 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_off.xml
@@ -17,9 +17,7 @@
     android:height="64dp"
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
-    android:alpha=".3"
-    android:width="64dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:width="64dp" >
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
index 7e2eca8..f4c20a9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on.xml
@@ -17,8 +17,7 @@
         android:width="64dp"
         android:height="64dp"
         android:viewportWidth="48.0"
-        android:viewportHeight="48.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="48.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
index 5f4fa11..fb26c09 100644
--- a/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_dnd_on_total_silence.xml
@@ -17,8 +17,7 @@
         android:width="64dp"
         android:height="64dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_minus.xml b/packages/SystemUI/res/drawable/ic_qs_minus.xml
index 147a94b..6a3410a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_minus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_minus.xml
@@ -17,8 +17,7 @@
     android:height="24.0dp"
     android:viewportHeight="48.0"
     android:viewportWidth="48.0"
-    android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:width="24.0dp" >
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
index b99dc03..aaca663 100644
--- a/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
@@ -17,12 +17,10 @@
     android:width="64dp"
     android:height="64dp"
     android:viewportWidth="24"
-    android:viewportHeight="24"
-    android:alpha="0.3"
-    android:tint="?android:attr/colorControlNormal">
+    android:viewportHeight="24">
 
     <path
-        android:fillColor="#FFFFFF"
+        android:fillColor="#FFF"
         android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
 
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
index d875592..aaca663 100644
--- a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
@@ -17,11 +17,10 @@
     android:width="64dp"
     android:height="64dp"
     android:viewportWidth="24"
-    android:viewportHeight="24"
-    android:tint="?android:attr/colorControlNormal">
+    android:viewportHeight="24">
 
     <path
-        android:fillColor="#FFFFFF"
+        android:fillColor="#FFF"
         android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
 
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
index 2d831b2..69869fe 100644
--- a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
@@ -17,10 +17,9 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
 
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M19.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0l-7.0,0.0L7.7,5.3L19.0,16.7L19.0,5.0zM3.7,3.9L2.4,5.2L5.0,7.8L5.0,19.0c0.0,1.1 0.9,2.0 2.0,2.0l10.0,0.0c0.4,0.0 0.7,-0.1 1.0,-0.3l1.9,1.9l1.3,-1.3L3.7,3.9z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_plus.xml b/packages/SystemUI/res/drawable/ic_qs_plus.xml
index 1f254d1..393f51c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_plus.xml
@@ -17,8 +17,7 @@
     android:height="24.0dp"
     android:viewportHeight="48.0"
     android:viewportWidth="48.0"
-    android:width="24.0dp"
-    android:tint="?android:attr/colorControlNormal" >
+    android:width="24.0dp" >
 
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
index 0673848..b78d3bf 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
@@ -18,8 +18,7 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
         android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
index fbf9e71..e055de7 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
@@ -18,8 +18,7 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
         android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
index 3a55623..195849a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="16.0dp"
+        android:width="32.0dp"
         android:height="32dp"
         android:viewportWidth="12.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
index e9f5a0b..8a48817 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
@@ -18,8 +18,7 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
         android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
index 769d648..39cc94c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
@@ -18,8 +18,7 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
         android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
index ddd8065..68c4307 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="17.333334dp"
+        android:width="32dp"
         android:height="32dp"
         android:viewportWidth="13.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="13.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
index 1bec1b8..012e95e 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
@@ -18,8 +18,7 @@
         android:width="32.0dp"
         android:height="32.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
         android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
index 8e1f8eb..61ecc9c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="16.0dp"
+        android:width="32.0dp"
         android:height="32dp"
         android:viewportWidth="12.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
index e0c6b68..54c52bf 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
+        android:width="32.0dp"
+        android:height="32.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
index 1c068e5..96e2fd4 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_carrier_network_change.xml
@@ -17,8 +17,7 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:name="dot1"
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
index 0a85392..dd5843d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
@@ -18,12 +18,11 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M21.799999,22.299999l-1.199999,-1.299999 0.000000,0.000000 -9.600000,-10.000000 0.000000,0.000000 -6.400000,-6.700000 -1.300000,1.300000 6.400000,6.700000 -8.700000,8.700000 16.900000,0.000000 2.600000,2.700001z"/>
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M21.000000,1.000000l-8.600000,8.600000 8.600000,9.100000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
index 4c90421..dd0f271 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="6.6666665dp"
+        android:width="32dp"
         android:height="32dp"
         android:viewportWidth="5.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="5.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
index db4df76..326373d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_0.xml
@@ -18,8 +18,7 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
         android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
index 6e5439d..8baa4eb 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
@@ -18,8 +18,7 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
         android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
index 194edc3..bf19a71 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_2.xml
@@ -18,8 +18,7 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
         android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
index b57af5c..01839e85 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_3.xml
@@ -18,8 +18,7 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
         android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
index 7d754a8..48151ad 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_4.xml
@@ -18,8 +18,7 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
index 64aadf9..3b47c0d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="9.333333dp"
+        android:width="32dp"
         android:height="32dp"
         android:viewportWidth="7.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="7.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
index 31918a9..d694e61 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="8.0dp"
+        android:width="32.0dp"
         android:height="32dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="6.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
index 4122b76..236fdac 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_in.xml
@@ -17,8 +17,7 @@
         android:width="6.0dp"
         android:height="32dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M6.000000,15.700000l-3.000000,5.599999 -3.000000,-5.599999z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
index 8766075..a381d03e 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="17.333334dp"
+        android:width="32dp"
         android:height="32dp"
         android:viewportWidth="13.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="13.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
index 5ff7d85..3bed28a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24.0dp"
-        android:height="24.0dp"
+        android:width="32.0dp"
+        android:height="32.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
index 4e65004..c8c857c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_no_signal.xml
@@ -18,9 +18,8 @@
         android:width="32dp"
         android:height="32dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M2.000000,22.000000l20.000000,0.000000L22.000000,2.000000L2.000000,22.000000zM20.000000,20.000000L6.800000,20.000000L20.000000,6.800000L20.000000,20.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
index a3823ae..c510972 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_out.xml
@@ -17,8 +17,7 @@
         android:width="6.0dp"
         android:height="32dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M0.000000,13.700000l3.000000,-5.700000 3.000000,5.700000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
index 2c10dc3f..40bfbe6 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
@@ -14,11 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="8.0dp"
+        android:width="32.0dp"
         android:height="32dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="6.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.800000,7.900000l-1.000000,0.000000L1.800000,11.000000L0.200000,11.000000L0.200000,2.500000l2.700000,0.000000c0.900000,0.000000 1.500000,0.200000 2.000000,0.700000s0.700000,1.100000 0.700000,1.900000c0.000000,0.600000 -0.100000,1.100000 -0.300000,1.500000S4.800000,7.200000 4.400000,7.400000l1.500000,3.500000L5.900000,11.000000L4.100000,11.000000L2.800000,7.900000zM1.800000,6.500000l1.100000,0.000000c0.400000,0.000000 0.600000,-0.100000 0.800000,-0.400000S4.000000,5.600000 4.000000,5.200000c0.000000,-0.400000 -0.100000,-0.800000 -0.300000,-1.000000S3.300000,3.800000 2.900000,3.800000L1.800000,3.800000L1.800000,6.500000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_vpn.xml b/packages/SystemUI/res/drawable/ic_qs_vpn.xml
index e7ef02a..cf24e12 100644
--- a/packages/SystemUI/res/drawable/ic_qs_vpn.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_vpn.xml
@@ -19,6 +19,6 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M12.700000,10.000000c-0.800000,-2.300000 -3.000000,-4.000000 -5.700000,-4.000000c-3.300000,0.000000 -6.000000,2.700000 -6.000000,6.000000s2.700000,6.000000 6.000000,6.000000c2.600000,0.000000 4.800000,-1.700000 5.700000,-4.000000L17.000000,14.000000l0.000000,4.000000l4.000000,0.000000l0.000000,-4.000000l2.000000,0.000000l0.000000,-4.000000L12.700000,10.000000zM7.000000,14.000000c-1.100000,0.000000 -2.000000,-0.900000 -2.000000,-2.000000c0.000000,-1.100000 0.900000,-2.000000 2.000000,-2.000000s2.000000,0.900000 2.000000,2.000000C9.000000,13.100000 8.100000,14.000000 7.000000,14.000000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
index fe963b1..e6f9292 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
@@ -17,8 +17,7 @@
         android:width="24.0dp"
         android:height="24.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
         android:fillAlpha="0.3"
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
index 82d2be2..d423ccb 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
@@ -17,8 +17,7 @@
         android:width="24.0dp"
         android:height="24.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
         android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
index f30ba76..1982130 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
@@ -17,8 +17,7 @@
         android:width="24.0dp"
         android:height="24.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
         android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
index 8a17083..b350111 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
@@ -17,8 +17,7 @@
         android:width="24.0dp"
         android:height="24.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
         android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
index fcd57d0..136a004 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
@@ -17,8 +17,7 @@
         android:width="24.0dp"
         android:height="24.0dp"
         android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
         android:fillColor="#FFFFFF"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
index bbff2e1..bed37b1 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disabled.xml
@@ -17,12 +17,11 @@
         android:width="32.0dp"
         android:height="29.5dp"
         android:viewportWidth="26.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M17.500000,16.500000L5.800000,3.400000c0.000000,0.000000 0.000000,0.000000 0.000000,0.000000l-2.700000,-3.000000L1.600000,1.800000l2.200000,2.500000c-2.000000,1.000000 -3.200000,2.000000 -3.400000,2.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l3.200000,-3.900000l2.400000,2.700000l1.500000,-1.400000L17.500000,16.500000L17.500000,16.500000z"/>
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000c-1.900000,0.000000 -3.600000,0.300000 -5.200000,0.700000L18.700001,15.000000L25.600000,6.500000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
index 071892a..2dcdb71 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_disconnected.xml
@@ -17,8 +17,7 @@
         android:width="26.0dp"
         android:height="24.0dp"
         android:viewportWidth="26.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M21.0,8.5
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
index c0e1037..1bc7438 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_0.xml
@@ -17,8 +17,7 @@
         android:width="32.0dp"
         android:height="29.5dp"
         android:viewportWidth="26.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
         android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
index f609295..5856115 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_1.xml
@@ -17,8 +17,7 @@
         android:width="32.0dp"
         android:height="29.5dp"
         android:viewportWidth="26.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
         android:pathData="M13.100000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.500000,6.500000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
index f44b303..4a5e1f8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_2.xml
@@ -17,8 +17,7 @@
         android:width="32.0dp"
         android:height="29.5dp"
         android:viewportWidth="26.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
         android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
index 850f5b9..965442d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_3.xml
@@ -17,8 +17,7 @@
         android:width="32.0dp"
         android:height="29.5dp"
         android:viewportWidth="26.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
         android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
index 8ccc1fd9..b29d3f9 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_full_4.xml
@@ -17,8 +17,7 @@
         android:width="32.0dp"
         android:height="29.5dp"
         android:viewportWidth="26.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
index 45cfc1c..e59e7f4 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_no_network.xml
@@ -17,9 +17,8 @@
         android:width="32.0dp"
         android:height="29.5dp"
         android:viewportWidth="26.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#4DFFFFFF"
+        android:fillColor="#FFFFFFFF"
         android:pathData="M13.000000,2.000000C7.700000,2.000000 3.700000,3.900000 0.400000,6.400000L13.000000,22.000000L25.600000,6.500000C22.299999,4.000000 18.299999,2.000000 13.000000,2.000000zM13.000000,18.600000L3.300000,7.000000l0.000000,0.000000l0.000000,0.000000C6.000000,5.300000 8.700000,4.000000 13.000000,4.000000s7.000000,1.400000 9.700000,3.000000l0.000000,0.000000l0.000000,0.000000L13.000000,18.600000z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_settings_20dp.xml b/packages/SystemUI/res/drawable/ic_settings_20dp.xml
index 45ee94f..3170f86 100644
--- a/packages/SystemUI/res/drawable/ic_settings_20dp.xml
+++ b/packages/SystemUI/res/drawable/ic_settings_20dp.xml
@@ -17,8 +17,7 @@
     android:width="20dp"
     android:height="20dp"
     android:viewportWidth="24.0"
-    android:viewportHeight="24.0"
-    android:tint="?android:attr/colorControlNormal">
+    android:viewportHeight="24.0">
     <path
         android:pathData="M19.4,13.0c0.0,-0.3 0.1,-0.6 0.1,-1.0s0.0,-0.7 -0.1,-1.0l2.1,-1.7c0.2,-0.2 0.2,-0.4 0.1,-0.6l-2.0,-3.5C19.5,5.1 19.3,5.0 19.0,5.1l-2.5,1.0c-0.5,-0.4 -1.1,-0.7 -1.7,-1.0l-0.4,-2.6C14.5,2.2 14.2,2.0 14.0,2.0l-4.0,0.0C9.8,2.0 9.5,2.2 9.5,2.4L9.1,5.1C8.5,5.3 8.0,5.7 7.4,6.1L5.0,5.1C4.7,5.0 4.5,5.1 4.3,5.3l-2.0,3.5C2.2,8.9 2.3,9.2 2.5,9.4L4.6,11.0c0.0,0.3 -0.1,0.6 -0.1,1.0s0.0,0.7 0.1,1.0l-2.1,1.7c-0.2,0.2 -0.2,0.4 -0.1,0.6l2.0,3.5C4.5,18.9 4.7,19.0 5.0,18.9l2.5,-1.0c0.5,0.4 1.1,0.7 1.7,1.0l0.4,2.6c0.0,0.2 0.2,0.4 0.5,0.4l4.0,0.0c0.2,0.0 0.5,-0.2 0.5,-0.4l0.4,-2.6c0.6,-0.3 1.2,-0.6 1.7,-1.0l2.5,1.0c0.2,0.1 0.5,0.0 0.6,-0.2l2.0,-3.5c0.1,-0.2 0.1,-0.5 -0.1,-0.6L19.4,13.0zM12.0,15.5c-1.9,0.0 -3.5,-1.6 -3.5,-3.5s1.6,-3.5 3.5,-3.5s3.5,1.6 3.5,3.5S13.9,15.5 12.0,15.5z"
         android:fillColor="#ffffffff" />
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
index 2ff0de4..09a67e1 100644
--- a/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_disable.xml
@@ -20,8 +20,7 @@
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48" >
     <group
         android:name="ic_signal_airplane"
         android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml
index 4fe585c..56ae4aa 100644
--- a/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_disable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_signal_airplane_disable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_signal_airplane_disable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_signal_airplane_disable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
index 9987279..b7ac0134 100644
--- a/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_enable.xml
@@ -16,12 +16,10 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="root"
-    android:alpha="0.3"
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48" >
     <group
         android:name="ic_signal_airplane"
         android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml
index d64b199..87dfba9 100644
--- a/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_airplane_enable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_signal_airplane_enable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_signal_airplane_enable_animation_root" />
-    <target
         android:name="ic_signal_airplane"
         android:animation="@anim/ic_signal_airplane_enable_animation_ic_signal_airplane" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
index 542797a..35844b7 100644
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable.xml
@@ -20,8 +20,7 @@
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48" >
     <group
         android:name="ic_signal_flashlight"
         android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml
index 61e5287..e228b7c 100644
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_disable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_signal_flashlight_disable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_signal_flashlight_disable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_signal_flashlight_disable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
index a5ba05b..c2215f1 100644
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable.xml
@@ -16,12 +16,10 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="root"
-    android:alpha="0.3"
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48" >
     <group
         android:name="ic_signal_flashlight"
         android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml
index 4bd9188..220c65e 100644
--- a/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_flashlight_enable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_signal_flashlight_enable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_signal_flashlight_enable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_signal_flashlight_enable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
index e36f270..439851d 100644
--- a/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_location_disable.xml
@@ -20,8 +20,7 @@
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48" >
     <group
         android:name="ic_signal_location"
         android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml
index a598b2d..0e9d1cb 100644
--- a/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_location_disable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_signal_location_disable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_signal_location_disable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_signal_location_disable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
index 46a72bc..d4b8673 100644
--- a/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_location_enable.xml
@@ -16,12 +16,10 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="root"
-    android:alpha="0.3"
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48" >
     <group
         android:name="ic_signal_location"
         android:translateX="21.9995"
diff --git a/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml
index 127af29..9f1d917 100644
--- a/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_location_enable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_signal_location_enable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_signal_location_enable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_signal_location_enable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml
index a15a127..9c23126 100644
--- a/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_workmode_disable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_signal_workmode_disable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_signal_workmode_disable_animation_root" />
-    <target
         android:name="mask"
         android:animation="@anim/ic_signal_workmode_disable_animation_mask" />
     <target
diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml
index ad14505..f962594 100644
--- a/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_workmode_enable.xml
@@ -16,7 +16,6 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="root"
-    android:alpha="0.3"
     android:height="42dp"
     android:width="42dp"
     android:viewportHeight="42"
diff --git a/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml b/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml
index 41d2b42..04ddfad 100644
--- a/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml
+++ b/packages/SystemUI/res/drawable/ic_signal_workmode_enable_animation.xml
@@ -17,9 +17,6 @@
 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/ic_signal_workmode_enable" >
     <target
-        android:name="root"
-        android:animation="@anim/ic_signal_workmode_enable_animation_root" />
-    <target
         android:name="ic_signal_briefcase"
         android:animation="@anim/ic_signal_workmode_enable_animation_ic_signal_briefcase" />
     <target
diff --git a/packages/SystemUI/res/drawable/minor_a_b.xml b/packages/SystemUI/res/drawable/minor_a_b.xml
index 0622aac..4bb330c 100644
--- a/packages/SystemUI/res/drawable/minor_a_b.xml
+++ b/packages/SystemUI/res/drawable/minor_a_b.xml
@@ -17,12 +17,10 @@
 <vector
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="minor_a_b"
-    android:alpha="0.3"
     android:width="16dp"
     android:viewportWidth="16"
     android:height="8dp"
-    android:viewportHeight="8"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportHeight="8" >
     <group
         android:name="dot_02"
         android:translateX="3.25"
diff --git a/packages/SystemUI/res/drawable/minor_b_a.xml b/packages/SystemUI/res/drawable/minor_b_a.xml
index ecb4341..f61deec 100644
--- a/packages/SystemUI/res/drawable/minor_b_a.xml
+++ b/packages/SystemUI/res/drawable/minor_b_a.xml
@@ -17,12 +17,10 @@
 <vector
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="minor_b_a"
-    android:alpha="0.3"
     android:width="16dp"
     android:viewportWidth="16"
     android:height="8dp"
-    android:viewportHeight="8"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportHeight="8" >
     <group
         android:name="dot_02"
         android:translateX="8"
diff --git a/packages/SystemUI/res/drawable/minor_b_c.xml b/packages/SystemUI/res/drawable/minor_b_c.xml
index 7f59e34..867af6d 100644
--- a/packages/SystemUI/res/drawable/minor_b_c.xml
+++ b/packages/SystemUI/res/drawable/minor_b_c.xml
@@ -17,12 +17,10 @@
 <vector
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="minor_b_c"
-    android:alpha="0.3"
     android:width="16dp"
     android:viewportWidth="16"
     android:height="8dp"
-    android:viewportHeight="8"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportHeight="8" >
     <group
         android:name="dot_02"
         android:translateX="8"
diff --git a/packages/SystemUI/res/drawable/minor_c_b.xml b/packages/SystemUI/res/drawable/minor_c_b.xml
index 97309bc..b2e33cf 100644
--- a/packages/SystemUI/res/drawable/minor_c_b.xml
+++ b/packages/SystemUI/res/drawable/minor_c_b.xml
@@ -17,12 +17,10 @@
 <vector
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="minor_c_b"
-    android:alpha="0.3"
     android:width="16dp"
     android:viewportWidth="16"
     android:height="8dp"
-    android:viewportHeight="8"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportHeight="8" >
     <group
         android:name="dot_02"
         android:translateX="12.75"
diff --git a/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml b/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
new file mode 100644
index 0000000..0b2bd22
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_dual_tile_caret.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M14.0,20.0l10.0,10.0 10.0,-10.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
index 2ac223b..b7da30b 100644
--- a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
+++ b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
@@ -17,7 +17,8 @@
     android:width="24.0dp"
     android:height="24.0dp"
     android:viewportWidth="72.0"
-    android:viewportHeight="72.0">
+    android:viewportHeight="72.0"
+    android:tint="?android:attr/textColorPrimary">
     <group
         android:translateX="52.0"
         android:translateY="42.0" >
diff --git a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml b/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml
index a85beb8..ea03a50 100644
--- a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml
+++ b/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml
@@ -15,5 +15,5 @@
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
   <solid android:color="#61FFFFFF" />
-  <corners android:radius="8dp"/>
+  <corners android:radius="@dimen/recents_grid_task_view_rounded_corners_radius"/>
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_managed_profile_disable_animation.xml b/packages/SystemUI/res/drawable/stat_sys_managed_profile_disable_animation.xml
index c6a2fdd..1e41a31 100644
--- a/packages/SystemUI/res/drawable/stat_sys_managed_profile_disable_animation.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_managed_profile_disable_animation.xml
@@ -16,7 +16,6 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="27.0dp"
         android:height="22.0dp"
-        android:alpha="0.3"
         android:viewportWidth="27.0"
         android:viewportHeight="22.0">
     <clip-path
diff --git a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
index e85b76d..46c761a 100644
--- a/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
+++ b/packages/SystemUI/res/layout-sw410dp/status_bar_alarm_group.xml
@@ -27,7 +27,7 @@
     <LinearLayout
         android:id="@+id/date_time_group"
         android:layout_width="wrap_content"
-        android:layout_height="19dp"
+        android:layout_height="wrap_content"
         android:orientation="horizontal"
         android:focusable="true" >
 
diff --git a/packages/SystemUI/res/layout/qs_customize_tile_frame.xml b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml
index aaa84fd..ff55f99 100644
--- a/packages/SystemUI/res/layout/qs_customize_tile_frame.xml
+++ b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml
@@ -18,7 +18,8 @@
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="wrap_content"
-    android:layout_width="wrap_content"
+    android:layout_width="match_parent"
     android:paddingStart="8dp"
     android:paddingEnd="8dp"
-    android:paddingBottom="16dp" />
+    android:paddingTop="8dp"
+    android:gravity="center" />
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 50ee64a..25d5226 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -20,10 +20,10 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/qs_detail_background"
-    android:paddingBottom="8dp"
     android:clickable="true"
-    android:visibility="invisible"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:paddingBottom="8dp"
+    android:visibility="invisible">
 
     <com.android.systemui.ResizingSpace
         android:layout_width="match_parent"
@@ -33,17 +33,16 @@
         android:id="@+id/qs_detail_header"
         layout="@layout/qs_detail_header"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
+        android:layout_height="wrap_content"
+        />
 
     <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:scaleType="fitXY"
-        android:translationY="8dp"
+        android:alpha="0"
+        android:background="@color/qs_detail_progress_track"
+        android:src="@drawable/indeterminate_anim"
         />
 
     <com.android.systemui.qs.NonInterceptingScrollView
@@ -51,12 +50,13 @@
         android:layout_height="0dp"
         android:layout_weight="1"
         android:fillViewport="true">
+
         <FrameLayout
             android:id="@android:id/content"
             android:layout_width="match_parent"
             android:layout_height="match_parent"/>
     </com.android.systemui.qs.NonInterceptingScrollView>
 
-    <include layout="@layout/qs_detail_buttons" />
+    <include layout="@layout/qs_detail_buttons"/>
 
 </com.android.systemui.qs.QSDetail>
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index 7876ada..6edf135 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -29,7 +29,8 @@
         android:layout_width="@dimen/qs_detail_item_icon_size"
         android:layout_height="@dimen/qs_detail_item_icon_size"
         android:layout_marginStart="@dimen/qs_detail_item_icon_marginStart"
-        android:layout_marginEnd="@dimen/qs_detail_item_icon_marginEnd" />
+        android:layout_marginEnd="@dimen/qs_detail_item_icon_marginEnd"
+        android:tint="?android:attr/textColorPrimary"/>
 
     <LinearLayout
         android:layout_width="0dp"
@@ -62,6 +63,7 @@
         android:focusable="true"
         android:scaleType="center"
         android:contentDescription="@*android:string/media_route_controller_disconnect"
+        android:tint="?android:attr/textColorPrimary"
         android:src="@drawable/ic_qs_cancel" />
 
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail_items.xml b/packages/SystemUI/res/layout/qs_detail_items.xml
index 9a7e1b6..b9cdf28 100644
--- a/packages/SystemUI/res/layout/qs_detail_items.xml
+++ b/packages/SystemUI/res/layout/qs_detail_items.xml
@@ -43,7 +43,8 @@
         <ImageView
             android:id="@android:id/icon"
             android:layout_width="56dp"
-            android:layout_height="56dp"/>
+            android:layout_height="56dp"
+            android:tint="?android:attr/textColorSecondary" />
 
         <TextView
             android:id="@android:id/title"
diff --git a/packages/SystemUI/res/layout/qs_page_indicator.xml b/packages/SystemUI/res/layout/qs_page_indicator.xml
new file mode 100644
index 0000000..02bd31a
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_page_indicator.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.systemui.qs.PageIndicator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/page_indicator"
+    android:layout_width="match_parent"
+    android:layout_height="48dp"
+    android:layout_gravity="center"
+    android:layout_marginTop="40dp"
+    android:layout_marginBottom="24dp"
+    android:focusable="true"
+    android:gravity="center"
+    android:importantForAccessibility="yes"
+    android:visibility="gone"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
index 8b6060f..8ff1d1e 100644
--- a/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
+++ b/packages/SystemUI/res/layout/qs_paged_tile_layout.xml
@@ -28,15 +28,6 @@
         android:layout_height="48dp"
         android:layout_gravity="bottom">
 
-        <com.android.systemui.qs.PageIndicator
-            android:id="@+id/page_indicator"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:gravity="center"
-            android:importantForAccessibility="yes"
-            android:focusable="true" />
-
     </FrameLayout>
 
 </com.android.systemui.qs.PagedTileLayout>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 9e0a6fe..895185b 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -26,10 +26,9 @@
     <com.android.systemui.qs.QSPanel
             android:id="@+id/quick_settings_panel"
             android:background="#0000"
-            android:layout_marginTop="80dp"
+            android:layout_marginTop="52dp"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingBottom="8dp" />
+            android:layout_height="wrap_content" />
 
     <include layout="@layout/quick_status_bar_expanded_header" />
 
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 5b0f0df..a093b87 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -18,11 +18,12 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:orientation="horizontal">
+        android:orientation="horizontal"
+        android:paddingTop="16dp">
      <TextView android:id="@+id/tile_label"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textColor="?android:attr/textColorSecondary"
+            android:textColor="?android:attr/textColorPrimary"
             android:gravity="center_horizontal"
             android:minLines="2"
             android:padding="0dp"
@@ -36,4 +37,4 @@
             android:layout_marginLeft="@dimen/restricted_padlock_pading"
             android:scaleType="centerInside"
             android:visibility="gone" />
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 080f553..6988c76 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -17,6 +17,7 @@
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="48dp"
     android:layout_width="match_parent"
+    android:layout_marginBottom="24dp"
     android:paddingLeft="16dp"
     android:paddingRight="16dp"
     style="@style/BrightnessDialogContainer">
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 53acb9f..4122707 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -23,30 +23,35 @@
     android:layout_width="match_parent"
     android:layout_height="@dimen/status_bar_header_height"
     android:layout_gravity="@integer/notification_panel_layout_gravity"
-    android:clipChildren="false"
-    android:clipToPadding="false"
     android:baselineAligned="false"
     android:clickable="false"
+    android:clipChildren="false"
+    android:clipToPadding="false"
+    android:paddingTop="0dp"
+    android:paddingEnd="0dp"
+    android:paddingStart="0dp"
     >
 
     <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="48dp"
-        android:gravity="center"
+        android:layout_alignParentEnd="true"
         android:clipChildren="false"
         android:clipToPadding="false"
-        android:orientation="horizontal"
-        android:layout_alignParentEnd="true"
-        android:layout_marginTop="4dp"
-        android:layout_marginEnd="12dp">
+        android:gravity="center"
+        android:paddingEnd="4dp"
+        android:orientation="horizontal">
 
-        <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
+        <com.android.systemui.statusbar.phone.MultiUserSwitch
+            android:id="@+id/multi_user_switch"
             android:layout_width="48dp"
             android:layout_height="48dp"
             android:layout_alignParentEnd="true"
-            android:focusable="true"
-            android:background="@drawable/ripple_drawable" >
-            <ImageView android:id="@+id/multi_user_avatar"
+            android:background="@drawable/ripple_drawable"
+            android:focusable="true">
+
+            <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"
@@ -57,13 +62,42 @@
             android:id="@android:id/edit"
             android:layout_width="48dp"
             android:layout_height="48dp"
-            android:clipToPadding="false"
-            android:clickable="true"
-            android:focusable="true"
-            android:src="@drawable/ic_mode_edit"
             android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:clickable="true"
+            android:clipToPadding="false"
             android:contentDescription="@string/accessibility_quick_settings_edit"
-            android:padding="14dp" />
+            android:focusable="true"
+            android:padding="14dp"
+            android:src="@drawable/ic_mode_edit"
+            android:tint="?android:attr/colorForeground"/>
+
+        <LinearLayout
+            android:id="@+id/system_icons_super_container"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/status_bar_header_height"
+            android:layout_alignWithParentIfMissing="true"
+            android:layout_toStartOf="@id/multi_user_switch"
+            android:background="@drawable/ripple_drawable">
+
+            <FrameLayout
+                android:id="@+id/system_icons_container"
+                android:layout_width="wrap_content"
+                android:layout_height="24dp"
+                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:importantForAccessibility="noHideDescendants"
+                android:textColor="?android:attr/textColorPrimary"
+                android:textSize="@dimen/battery_level_text_size"/>
+        </LinearLayout>
 
         <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
             android:id="@+id/settings_button_container"
@@ -78,16 +112,18 @@
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:background="@drawable/ripple_drawable"
+                android:contentDescription="@string/accessibility_quick_settings_settings"
                 android:src="@drawable/ic_settings_20dp"
-                android:contentDescription="@string/accessibility_quick_settings_settings" />
+                android:tint="?android:attr/colorForeground"/>
+
             <com.android.systemui.statusbar.AlphaOptimizedImageView
                 android:id="@+id/tuner_icon"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:paddingStart="36dp"
-                android:alpha="0.3"
-                android:visibility="invisible"
-                android:src="@drawable/tuner" />
+                android:src="@drawable/tuner"
+                android:tint="?android:attr/textColorTertiary"
+                android:visibility="invisible"/>
 
         </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
 
@@ -106,23 +142,26 @@
 
     <TextView
         android:id="@+id/header_emergency_calls_only"
-        android:layout_height="wrap_content"
         android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:layout_alignParentStart="true"
         android:layout_alignParentTop="true"
-        android:paddingStart="16dp"
+        android:focusable="true"
+        android:gravity="center_vertical"
         android:paddingEnd="16dp"
         android:paddingTop="6dp"
-        android:visibility="gone"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
-        android:text="@*android:string/emergency_calls_only"
         android:singleLine="true"
-        android:gravity="center_vertical"
-        android:focusable="true" />
+        android:text="@*android:string/emergency_calls_only"
+        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
+        android:visibility="gone"/>
 
     <include
         android:id="@+id/date_time_alarm_group"
         layout="@layout/status_bar_alarm_group"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="12dp"
         android:layout_alignParentStart="true"
         android:layout_alignParentTop="true" />
 
@@ -130,38 +169,41 @@
         android:id="@+id/quick_qs_panel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="52dp"
-        android:layout_marginStart="12dp"
-        android:layout_marginEnd="12dp"
         android:layout_alignParentEnd="true"
+        android:layout_marginTop="54dp"
+        android:layout_marginBottom="24dp"
+        android:layout_alignParentTop="true"
+        android:accessibilityTraversalAfter="@+id/date_time_group"
+        android:accessibilityTraversalBefore="@id/expand_indicator"
         android:clipChildren="false"
         android:clipToPadding="false"
-        android:importantForAccessibility="yes"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="16dp"
         android:focusable="true"
-        android:accessibilityTraversalAfter="@+id/date_time_group"
-        android:accessibilityTraversalBefore="@id/expand_indicator" />
+        android:importantForAccessibility="yes"
+        android:paddingTop="0dp"/>
 
     <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"
+        android:alpha="0"
+        android:background="@color/qs_detail_progress_track"
+        android:src="@drawable/indeterminate_anim"
         />
 
     <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:padding="2dp"
+        android:textColor="#00A040"
         android:textSize="11dp"
         android:textStyle="bold"
-        android:textColor="#00A040"
-        android:padding="2dp"
+        android:visibility="invisible"
         />
 
 </com.android.systemui.statusbar.phone.QuickStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/recents_grid_task_view.xml b/packages/SystemUI/res/layout/recents_grid_task_view.xml
index 53bec70..1c9b9ac 100644
--- a/packages/SystemUI/res/layout/recents_grid_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_grid_task_view.xml
@@ -18,7 +18,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:focusable="true">
-    <com.android.systemui.recents.views.TaskViewThumbnail
+    <com.android.systemui.recents.views.grid.GridTaskViewThumbnail
         android:id="@+id/task_view_thumbnail"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
diff --git a/packages/SystemUI/res/layout/split_clock_view.xml b/packages/SystemUI/res/layout/split_clock_view.xml
index ae5136f..8198f03 100644
--- a/packages/SystemUI/res/layout/split_clock_view.xml
+++ b/packages/SystemUI/res/layout/split_clock_view.xml
@@ -28,6 +28,7 @@
         android:singleLine="true"
         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
         android:textSize="@dimen/qs_time_collapsed_size"
+        android:textColor="?android:attr/textColorPrimary"
         />
     <TextClock
         android:id="@+id/am_pm_view"
@@ -36,6 +37,7 @@
         android:singleLine="true"
         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
         android:textSize="@dimen/qs_time_collapsed_size"
+        android:textColor="?android:attr/textColorPrimary"
         android:importantForAccessibility="no"
         />
 
@@ -44,8 +46,9 @@
         android:id="@+id/empty_time_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:visibility="invisible"
+        android:visibility="gone"
         android:singleLine="true"
         android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+        android:textColor="?android:attr/textColorPrimary"
         />
 </com.android.systemui.statusbar.policy.SplitClockView>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 6784254..63af3e0 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -42,7 +42,7 @@
     <LinearLayout android:id="@+id/status_bar_contents"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:paddingStart="@dimen/status_bar_padding_start"
+        android:paddingStart="6dp"
         android:paddingEnd="8dp"
         android:orientation="horizontal"
         >
diff --git a/packages/SystemUI/res/layout/status_bar_alarm_group.xml b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
index a02e9af..745320e 100644
--- a/packages/SystemUI/res/layout/status_bar_alarm_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_alarm_group.xml
@@ -41,6 +41,7 @@
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:src="@drawable/ic_access_alarms_small"
+            android:tint="?android:attr/textColorPrimary"
             android:paddingStart="6dp"
             android:gravity="center"
             android:visibility="gone" />
diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml
index ca4f727..2b4a0f5 100644
--- a/packages/SystemUI/res/layout/zen_mode_condition.xml
+++ b/packages/SystemUI/res/layout/zen_mode_condition.xml
@@ -63,6 +63,7 @@
         android:scaleType="center"
         android:layout_toStartOf="@android:id/button2"
         android:contentDescription="@string/accessibility_quick_settings_less_time"
+        android:tint="?android:attr/textColorPrimary"
         android:src="@drawable/ic_qs_minus" />
 
     <ImageView
@@ -75,6 +76,7 @@
         android:scaleType="center"
         android:layout_centerVertical="true"
         android:contentDescription="@string/accessibility_quick_settings_more_time"
+        android:tint="?android:attr/textColorPrimary"
         android:src="@drawable/ic_qs_plus" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index a229866..7fb513c 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -40,8 +40,9 @@
         <attr name="decayTime" format="integer" />
         <attr name="orientation" />
     </declare-styleable>
+    <attr name="frameColor" format="color" />
     <declare-styleable name="BatteryMeterView">
-        <attr name="frameColor" format="color" />
+        <attr name="frameColor" />
     </declare-styleable>
     <declare-styleable name="Clock">
         <attr name="amPmStyle" format="enum">
@@ -60,7 +61,7 @@
         <attr name="framePadding" format="dimension" />
         <!-- {@deprecated Use a statelist in frameColor instead.} -->
         <attr name="activeFrameColor" format="color" />
-        <attr name="frameColor" format="color" />
+        <attr name="frameColor" />
         <attr name="badgeDiameter" format="dimension" />
         <attr name="badgeMargin" format="dimension" />
     </declare-styleable>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 6ffdbcb..79529a7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -164,7 +164,7 @@
     <dimen name="close_handle_underlap">32dp</dimen>
 
     <!-- Height of the status bar header bar -->
-    <dimen name="status_bar_header_height">104dp</dimen>
+    <dimen name="status_bar_header_height">126dp</dimen>
 
     <!-- Height of the status bar header bar when expanded -->
     <dimen name="status_bar_header_height_expanded">116dp</dimen>
@@ -204,8 +204,8 @@
     <!-- The size of the gesture span needed to activate the "pull" notification expansion -->
     <dimen name="pull_span_min">25dp</dimen>
 
-    <dimen name="qs_tile_height">88dp</dimen>
-    <dimen name="qs_tile_margin">16dp</dimen>
+    <dimen name="qs_tile_height">80dp</dimen>
+    <dimen name="qs_tile_margin">36dp</dimen>
     <dimen name="qs_tile_margin_top">16dp</dimen>
     <dimen name="qs_quick_tile_size">48dp</dimen>
     <dimen name="qs_quick_tile_padding">12dp</dimen>
@@ -421,7 +421,7 @@
     <dimen name="qs_time_collapsed_size">14sp</dimen>
 
     <!-- The font size of the time when expanded in QS -->
-    <dimen name="qs_time_expanded_size">20sp</dimen>
+    <dimen name="qs_time_expanded_size">14sp</dimen>
 
     <!-- The font size of the "emergency calls only" label in QS -->
     <dimen name="qs_emergency_calls_only_text_size">12sp</dimen>
diff --git a/packages/SystemUI/res/values/dimens_grid.xml b/packages/SystemUI/res/values/dimens_grid.xml
index 0b9836ff..5858443 100644
--- a/packages/SystemUI/res/values/dimens_grid.xml
+++ b/packages/SystemUI/res/values/dimens_grid.xml
@@ -22,5 +22,6 @@
   <dimen name="recents_grid_task_view_header_height">44dp</dimen>
   <dimen name="recents_grid_task_view_header_button_padding">8dp</dimen>
   <dimen name="recents_grid_task_view_focused_frame_thickness">8dp</dimen>
+  <dimen name="recents_grid_task_view_rounded_corners_radius">8dp</dimen>
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a17430a..de2b654 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1022,10 +1022,10 @@
     <string name="monitoring_title">Network monitoring</string>
 
     <!-- STOPSHIP Monitoring strings still need to be finalized and approved -->
-    <!-- Monitoring dialog subtitle for the section describing VPN [CHAR LIMIT=TODO]-->
+    <!-- Monitoring dialog subtitle for the section describing VPN [CHAR LIMIT=35]-->
     <string name="monitoring_subtitle_vpn">VPN</string>
 
-    <!-- Monitoring dialog subtitle for the section describing network logging [CHAR LIMIT=TODO]-->
+    <!-- Monitoring dialog subtitle for the section describing network logging [CHAR LIMIT=35]-->
     <string name="monitoring_subtitle_network_logging">Network Logging</string>
 
     <!-- Monitoring dialog disable vpn button [CHAR LIMIT=30] -->
@@ -1041,7 +1041,7 @@
     <string name="monitoring_description_do_header_with_name"><xliff:g id="organization_name" example="Foo, Inc.">%1$s</xliff:g> uses <xliff:g id="device_owner_app" example="Google Mobile Management">%2$s</xliff:g> to manage your device.</string>
 
     <!-- Monitoring dialog: Part of text body explaining what a Device Owner app can do [CHAR LIMIT=130] -->
-    <string name="monitoring_description_do_body">Your administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.</string>
+    <string name="monitoring_description_do_body">Your admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.</string>
 
     <!-- Monitoring dialog: Space that separates the body text and the "learn more" link that follows it. [CHAR LIMIT=5] -->
     <string name="monitoring_description_do_learn_more_separator">" "</string>
@@ -1055,18 +1055,18 @@
     <!-- Monitoring dialog: Space that separates the VPN body text and the "Open VPN Settings" link that follows it. [CHAR LIMIT=5] -->
     <string name="monitoring_description_vpn_settings_separator">" "</string>
 
-    <!-- Monitoring dialog: Link to open the VPN settings page [CHAR LIMIT=TODO] -->
+    <!-- Monitoring dialog: Link to open the VPN settings page [CHAR LIMIT=60] -->
     <string name="monitoring_description_vpn_settings">Open VPN Settings</string>
 
-    <!-- Monitoring dialog: Network logging text [CHAR LIMIT=TODO] -->
-    <string name="monitoring_description_network_logging">Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information contact your admin.</string>
+    <!-- Monitoring dialog: Network logging text [CHAR LIMIT=400] -->
+    <string name="monitoring_description_network_logging">Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin.</string>
 
 
     <!-- Monitoring dialog VPN text [CHAR LIMIT=400] -->
     <string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps, and websites.</string>
 
     <!-- Monitoring dialog VPN with profile owner text [CHAR LIMIT=400] -->
-    <string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your administrator.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string>
+    <string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string>
 
     <!-- Name for a generic legacy VPN connection [CHAR LIMIT=20] -->
     <string name="legacy_vpn_name">VPN</string>
@@ -1081,7 +1081,7 @@
     <string name="branded_monitoring_description_app_personal">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps, and websites.</string>
 
     <!-- Monitoring dialog text for single app (inside work profile) [CHAR LIMIT=400] -->
-    <string name="monitoring_description_app_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string>
+    <string name="monitoring_description_app_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nFor more information, contact your admin.</string>
 
     <!-- Monitoring dialog text for multiple apps (in personal and work profiles) [CHAR LIMIT=400] -->
     <string name="monitoring_description_app_personal_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application_work">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nYou\'re also connected to <xliff:g id="application_personal">%3$s</xliff:g>, which can monitor your personal network activity.</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index a9c858c..f53e30f 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -106,24 +106,28 @@
         <item name="android:textColor">@color/status_bar_clock_color</item>
     </style>
 
-    <style name="TextAppearance.StatusBar.Expanded" parent="@*android:style/TextAppearance.StatusBar" />
+    <style name="TextAppearance.StatusBar.Expanded" parent="@*android:style/TextAppearance.StatusBar">
+        <item name="android:textColor">?android:attr/textColorTertiary</item>
+    </style>
 
     <style name="TextAppearance.StatusBar.Expanded.Clock">
         <item name="android:textSize">@dimen/qs_time_expanded_size</item>
-        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:fontFamily">sans-serif-condensed</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:textStyle">normal</item>
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.Date">
         <item name="android:textSize">@dimen/qs_date_collapsed_size</item>
         <item name="android:textStyle">normal</item>
         <item name="android:textColor">?android:attr/textColorSecondary</item>
+        <item name="android:fontFamily">sans-serif-condensed</item>
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.AboveDateTime">
         <item name="android:textSize">@dimen/qs_emergency_calls_only_text_size</item>
         <item name="android:textStyle">normal</item>
-        <item name="android:textColor">?android:attr/textColorSecondary</item>
+        <item name="android:textColor">?android:attr/textColorTertiary</item>
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
@@ -135,7 +139,7 @@
     <style name="TextAppearance.StatusBar.Expanded.UserSwitcher">
         <item name="android:textSize">16sp</item>
         <item name="android:textStyle">normal</item>
-        <item name="android:textColor">@color/qs_user_detail_name</item>
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
     </style>
     <style name="TextAppearance.StatusBar.Expanded.UserSwitcher.UserName" />
 
@@ -172,7 +176,7 @@
 
     <style name="TextAppearance.QS.DetailButton">
         <item name="android:textSize">@dimen/qs_detail_button_text_size</item>
-        <item name="android:textColor">@color/qs_detail_button</item>
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
         <item name="android:textAllCaps">true</item>
         <item name="android:fontFamily">sans-serif-medium</item>
         <item name="android:gravity">center</item>
@@ -184,7 +188,7 @@
 
     <style name="TextAppearance.QS.DetailEmpty">
         <item name="android:textSize">@dimen/qs_detail_empty_text_size</item>
-        <item name="android:textColor">@color/qs_subhead</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.QS.Subhead">
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
index 07ef5e0..5a6afca 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java
@@ -292,12 +292,16 @@
         }
         int backgroundColor = getBackgroundColor(darkIntensity);
         int fillColor = getFillColor(darkIntensity);
+        setColors(fillColor, backgroundColor);
+        mOldDarkIntensity = darkIntensity;
+    }
+
+    public void setColors(int fillColor, int backgroundColor) {
         mIconTint = fillColor;
         mFramePaint.setColor(backgroundColor);
         mBoltPaint.setColor(fillColor);
         mChargeColor = fillColor;
         invalidateSelf();
-        mOldDarkIntensity = darkIntensity;
     }
 
     private int getBackgroundColor(float darkIntensity) {
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index ef1c25d..030250a 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -72,8 +72,6 @@
     @Override
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
-        mBatteryController.addCallback(this);
-        mDrawable.startListening();
         TunerService.get(getContext()).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
     }
 
@@ -100,9 +98,15 @@
     public void setBatteryController(BatteryController mBatteryController) {
         this.mBatteryController = mBatteryController;
         mDrawable.setBatteryController(mBatteryController);
+        mBatteryController.addCallback(this);
+        mDrawable.startListening();
     }
 
     public void setDarkIntensity(float f) {
         mDrawable.setDarkIntensity(f);
     }
+
+    public void setRawColors(int fgColor, int bgColor) {
+        mDrawable.setColors(fgColor, bgColor);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index 63d1cc2..c7514a9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -91,10 +91,6 @@
         // Draw captions overlaid on the content view, so the whole window is one solid color.
         setOverlayWithDecorCaptionEnabled(true);
 
-        // Match task description to the task stack we are replacing so it's still recognizably the
-        // original task stack with the same icon and title text.
-        setTaskDescription(new TaskDescription(null, null, color));
-
         // Blank out the activity. When it is on-screen it will look like a Recents thumbnail with
         // redaction switched on.
         final View blankView = new View(this);
@@ -127,6 +123,11 @@
         return;
     }
 
+    @Override
+    public void setTaskDescription(TaskDescription taskDescription) {
+        // Use the previous activity's task description.
+    }
+
     private final BroadcastReceiver mLockEventReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index a2d7d6b..3103267 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -16,14 +16,20 @@
 
 package com.android.systemui.pip.phone;
 
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.app.ActivityManager;
+import android.app.ActivityManager.StackInfo;
+import android.app.ActivityOptions;
 import android.app.IActivityManager;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.IPinnedStackController;
 import android.view.IPinnedStackListener;
@@ -49,6 +55,7 @@
     private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
 
     private PipMenuActivityController mMenuController;
+    private PipMediaController mMediaController;
     private PipTouchHandler mTouchHandler;
 
     /**
@@ -57,7 +64,11 @@
     TaskStackListener mTaskStackListener = new TaskStackListener() {
         @Override
         public void onActivityPinned() {
+            if (!checkCurrentUserId(false /* debug */)) {
+                return;
+            }
             mTouchHandler.onActivityPinned();
+            mMediaController.onActivityPinned();
         }
 
         @Override
@@ -66,8 +77,24 @@
         }
 
         @Override
-        public void onPinnedActivityRestartAttempt() {
-            // TODO(winsonc): Hide the menu and expand the PiP
+        public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) {
+            if (!checkCurrentUserId(false /* debug */)) {
+                return;
+            }
+
+            // Expand the activity back to fullscreen only if it was attempted to be restarted from
+            // another package than the top activity in the stack
+            boolean expandPipToFullscreen = true;
+            if (sourceComponent != null) {
+                ComponentName topActivity = PipUtils.getTopPinnedActivity(mActivityManager);
+                expandPipToFullscreen = topActivity != null && topActivity.getPackageName().equals(
+                        sourceComponent.getPackageName());
+            }
+            if (expandPipToFullscreen) {
+                mTouchHandler.expandPinnedStackToFullscreen();
+            } else {
+                Log.w(TAG, "Can not expand PiP to fullscreen via intent from the same package.");
+            }
         }
     };
 
@@ -91,7 +118,7 @@
         @Override
         public void onActionsChanged(ParceledListSlice actions) {
             mHandler.post(() -> {
-                mMenuController.setActions(actions);
+                mMenuController.setAppActions(actions);
             });
         }
 
@@ -127,7 +154,9 @@
         }
         SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
 
-        mMenuController = new PipMenuActivityController(context, mActivityManager, mWindowManager);
+        mMediaController = new PipMediaController(context, mActivityManager);
+        mMenuController = new PipMenuActivityController(context, mActivityManager, mWindowManager,
+                mMediaController);
         mTouchHandler = new PipTouchHandler(context, mMenuController, mActivityManager,
                 mWindowManager);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
new file mode 100644
index 0000000..2284013
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.pip.phone;
+
+import android.app.IActivityManager;
+import android.app.RemoteAction;
+import android.content.ComponentName;
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.media.session.MediaController;
+import android.media.session.MediaController.TransportControls;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
+
+import com.android.systemui.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Interfaces with the {@link MediaSessionManager} to compose the right set of actions to show (only
+ * if there are no actions from the PiP activity itself). The active media controller is only set
+ * when there is a media session from the top PiP activity.
+ */
+public class PipMediaController {
+
+    /**
+     * A listener interface to receive notification on changes to the media actions.
+     */
+    public interface ActionListener {
+        /**
+         * Called when the media actions changes.
+         */
+        void onMediaActionsChanged(List<RemoteAction> actions);
+    }
+
+    private final Context mContext;
+    private final IActivityManager mActivityManager;
+
+    private final MediaSessionManager mMediaSessionManager;
+    private MediaController mMediaController;
+
+    private RemoteAction mPauseAction;
+    private RemoteAction mPlayAction;
+
+    private MediaController.Callback mPlaybackChangedListener = new MediaController.Callback() {
+        @Override
+        public void onPlaybackStateChanged(PlaybackState state) {
+            if (!mListeners.isEmpty()) {
+                notifyActionsChanged(getMediaActions());
+            }
+        }
+    };
+
+    private ArrayList<ActionListener> mListeners = new ArrayList<>();
+
+    public PipMediaController(Context context, IActivityManager activityManager) {
+        mContext = context;
+        mActivityManager = activityManager;
+
+        createMediaActions();
+        mMediaSessionManager =
+                (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
+        mMediaSessionManager.addOnActiveSessionsChangedListener(controllers -> {
+            resolveActiveMediaController(controllers);
+        }, null);
+    }
+
+    /**
+     * Handles when an activity is pinned.
+     */
+    public void onActivityPinned() {
+        // Once we enter PiP, try to find the active media controller for the top most activity
+        resolveActiveMediaController(mMediaSessionManager.getActiveSessions(null));
+    }
+
+    /**
+     * Adds a new media action listener.
+     */
+    public void addListener(ActionListener listener) {
+        if (!mListeners.contains(listener)) {
+            mListeners.add(listener);
+            listener.onMediaActionsChanged(getMediaActions());
+        }
+    }
+
+    /**
+     * Removes a media action listener.
+     */
+    public void removeListener(ActionListener listener) {
+        listener.onMediaActionsChanged(Collections.EMPTY_LIST);
+        mListeners.remove(listener);
+    }
+
+    /**
+     * Gets the set of media actions currently available.
+     */
+    private List<RemoteAction> getMediaActions() {
+        if (mMediaController == null || mMediaController.getPlaybackState() == null) {
+            return Collections.EMPTY_LIST;
+        }
+
+        ArrayList<RemoteAction> mediaActions = new ArrayList<>();
+        int state = mMediaController.getPlaybackState().getState();
+        boolean isPlaying = MediaSession.isActiveState(state);
+        long actions = mMediaController.getPlaybackState().getActions();
+        if (!isPlaying && ((actions & PlaybackState.ACTION_PLAY) != 0)) {
+            mediaActions.add(mPauseAction);
+        } else if (isPlaying && ((actions & PlaybackState.ACTION_PAUSE) != 0)) {
+            mediaActions.add(mPlayAction);
+        }
+        return mediaActions;
+    }
+
+    /**
+     * Creates the standard media buttons that we may show.
+     */
+    private void createMediaActions() {
+        String pauseDescription = mContext.getString(R.string.pip_pause);
+        mPauseAction = new RemoteAction(Icon.createWithResource(mContext,
+                R.drawable.ic_pause_white_24dp), pauseDescription, pauseDescription,
+                action -> mMediaController.getTransportControls().pause());
+
+        String playDescription = mContext.getString(R.string.pip_play);
+        mPlayAction = new RemoteAction(Icon.createWithResource(mContext,
+                R.drawable.ic_play_arrow_white_24dp), playDescription, playDescription,
+                action -> mMediaController.getTransportControls().play());
+    }
+
+    /**
+     * Tries to find and set the active media controller for the top PiP activity.
+     */
+    private void resolveActiveMediaController(List<MediaController> controllers) {
+        if (controllers != null) {
+            final ComponentName topActivity = PipUtils.getTopPinnedActivity(mActivityManager);
+            if (topActivity != null) {
+                for (int i = 0; i < controllers.size(); i++) {
+                    final MediaController controller = controllers.get(i);
+                    if (controller.getPackageName().equals(topActivity.getPackageName())) {
+                        setActiveMediaController(controller);
+                        return;
+                    }
+                }
+            }
+        }
+        setActiveMediaController(null);
+    }
+
+    /**
+     * Sets the active media controller for the top PiP activity.
+     */
+    private void setActiveMediaController(MediaController controller) {
+        if (controller != mMediaController) {
+            if (mMediaController != null) {
+                mMediaController.unregisterCallback(mPlaybackChangedListener);
+            }
+            mMediaController = controller;
+            if (controller != null) {
+                controller.registerCallback(mPlaybackChangedListener);
+            }
+            if (!mListeners.isEmpty()) {
+                notifyActionsChanged(getMediaActions());
+            }
+
+            // TODO(winsonc): Consider if we want to close the PIP after a timeout (like on TV)
+        }
+    }
+
+    /**
+     * Notifies all listeners that the actions have changed.
+     */
+    private void notifyActionsChanged(List<RemoteAction> actions) {
+        if (!mListeners.isEmpty()) {
+            mListeners.forEach(l -> l.onMediaActionsChanged(actions));
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 0f7647d..6ef30c0 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.android.systemui.pip.phone;
 
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -5,6 +21,7 @@
 import android.app.ActivityManager.StackInfo;
 import android.app.ActivityOptions;
 import android.app.IActivityManager;
+import android.app.RemoteAction;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
@@ -16,11 +33,20 @@
 import android.util.Log;
 import android.view.IWindowManager;
 
-import java.util.ArrayList;
+import com.android.systemui.pip.phone.PipMediaController.ActionListener;
 
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages the PiP menu activity.
+ *
+ * The current media session provides actions whenever there are no valid actions provided by the
+ * current PiP activity. Otherwise, those actions always take precedence.
+ */
 public class PipMenuActivityController {
 
-    private static final String TAG = "PipMenuActivityController";
+    private static final String TAG = "PipMenuActController";
 
     public static final String EXTRA_CONTROLLER_MESSENGER = "messenger";
     public static final String EXTRA_ACTIONS = "actions";
@@ -59,9 +85,12 @@
     private Context mContext;
     private IActivityManager mActivityManager;
     private IWindowManager mWindowManager;
+    private PipMediaController mMediaController;
 
     private ArrayList<Listener> mListeners = new ArrayList<>();
-    private ParceledListSlice mActions;
+    private ParceledListSlice mAppActions;
+    private ParceledListSlice mMediaActions;
+    private boolean mVisible;
 
     private Messenger mToActivityMessenger;
     private Messenger mMessenger = new Messenger(new Handler() {
@@ -70,13 +99,13 @@
             switch (msg.what) {
                 case MESSAGE_MENU_VISIBILITY_CHANGED: {
                     boolean visible = msg.arg1 > 0;
-                    mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible));
+                    onMenuVisibilityChanged(visible);
                     break;
                 }
                 case MESSAGE_EXPAND_PIP: {
                     mListeners.forEach(l -> l.onPipExpand());
                     // Preemptively mark the menu as invisible once we expand the PiP
-                    mListeners.forEach(l -> l.onPipMenuVisibilityChanged(false));
+                    onMenuVisibilityChanged(false);
                     break;
                 }
                 case MESSAGE_MINIMIZE_PIP: {
@@ -86,14 +115,14 @@
                 case MESSAGE_DISMISS_PIP: {
                     mListeners.forEach(l -> l.onPipDismiss());
                     // Preemptively mark the menu as invisible once we dismiss the PiP
-                    mListeners.forEach(l -> l.onPipMenuVisibilityChanged(false));
+                    onMenuVisibilityChanged(false);
                     break;
                 }
                 case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                     mToActivityMessenger = msg.replyTo;
                     // Mark the menu as invisible once the activity finishes as well
                     if (mToActivityMessenger == null) {
-                        mListeners.forEach(l -> l.onPipMenuVisibilityChanged(false));
+                        onMenuVisibilityChanged(false);
                     }
                     break;
                 }
@@ -101,11 +130,20 @@
         }
     });
 
+    private ActionListener mMediaActionListener = new ActionListener() {
+        @Override
+        public void onMediaActionsChanged(List<RemoteAction> mediaActions) {
+            mMediaActions = new ParceledListSlice<>(mediaActions);
+            updateMenuActions();
+        }
+    };
+
     public PipMenuActivityController(Context context, IActivityManager activityManager,
-            IWindowManager windowManager) {
+            IWindowManager windowManager, PipMediaController mediaController) {
         mContext = context;
         mActivityManager = activityManager;
         mWindowManager = windowManager;
+        mMediaController = mediaController;
     }
 
     /**
@@ -137,7 +175,7 @@
                         pinnedStackInfo.taskIds.length > 0) {
                     Intent intent = new Intent(mContext, PipMenuActivity.class);
                     intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
-                    intent.putExtra(EXTRA_ACTIONS, mActions);
+                    intent.putExtra(EXTRA_ACTIONS, resolveMenuActions());
                     ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
                     options.setLaunchTaskId(
                             pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);
@@ -168,15 +206,31 @@
     }
 
     /**
-     * Sets the {@param actions} associated with the PiP.
+     * Sets the menu actions to the actions provided by the current PiP activity.
      */
-    public void setActions(ParceledListSlice actions) {
-        mActions = actions;
+    public void setAppActions(ParceledListSlice appActions) {
+        mAppActions = appActions;
+        updateMenuActions();
+    }
 
+    /**
+     * @return the best set of actions to show in the PiP menu.
+     */
+    private ParceledListSlice resolveMenuActions() {
+        if (isValidActions(mAppActions)) {
+            return mAppActions;
+        }
+        return mMediaActions;
+    }
+
+    /**
+     * Updates the PiP menu activity with the best set of actions provided.
+     */
+    private void updateMenuActions() {
         if (mToActivityMessenger != null) {
             Message m = Message.obtain();
             m.what = PipMenuActivity.MESSAGE_UPDATE_ACTIONS;
-            m.obj = actions;
+            m.obj = resolveMenuActions();
             try {
                 mToActivityMessenger.send(m);
             } catch (RemoteException e) {
@@ -184,4 +238,30 @@
             }
         }
     }
+
+    /**
+     * Returns whether the set of actions are valid.
+     */
+    private boolean isValidActions(ParceledListSlice actions) {
+        return actions != null && actions.getList().size() > 0;
+    }
+
+    /**
+     * Handles changes in menu visibility.
+     */
+    private void onMenuVisibilityChanged(boolean visible) {
+        mListeners.forEach(l -> l.onPipMenuVisibilityChanged(visible));
+        if (visible != mVisible) {
+            if (visible) {
+                // Once visible, start listening for media action changes. This call will trigger
+                // the menu actions to be updated again.
+                mMediaController.addListener(mMediaActionListener);
+            } else {
+                // Once hidden, stop listening for media action changes. This call will trigger
+                // the menu actions to be updated again.
+                mMediaController.removeListener(mMediaActionListener);
+            }
+        }
+        mVisible = visible;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 18ae3cf..12fda14 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -87,6 +87,7 @@
     // Allow the PIP to be "docked" slightly offscreen
     private boolean mEnableMinimizing = true;
 
+    private final Rect mStableInsets = new Rect();
     private final Rect mPinnedStackBounds = new Rect();
     private final Rect mBoundedPinnedStackBounds = new Rect();
     private ValueAnimator mPinnedStackBoundsAnimator = null;
@@ -421,7 +422,8 @@
         mContext.getDisplay().getRealSize(displaySize);
         Rect toBounds = mSnapAlgorithm.findClosestSnapBounds(mBoundedPinnedStackBounds,
                 mPinnedStackBounds);
-        mSnapAlgorithm.applyMinimizedOffset(toBounds, mBoundedPinnedStackBounds, displaySize);
+        mSnapAlgorithm.applyMinimizedOffset(toBounds, mBoundedPinnedStackBounds, displaySize,
+                mStableInsets);
         mPinnedStackBoundsAnimator = mMotionHelper.createAnimationToBounds(mPinnedStackBounds,
                 toBounds, MINIMIZE_STACK_MAX_DURATION, LINEAR_OUT_SLOW_IN,
                 mUpdatePinnedStackBoundsListener);
@@ -485,7 +487,7 @@
     /**
      * Resizes the pinned stack back to fullscreen.
      */
-    private void expandPinnedStackToFullscreen() {
+    void expandPinnedStackToFullscreen() {
         BackgroundThread.getHandler().post(() -> {
             try {
                 mActivityManager.resizeStack(PINNED_STACK_ID, null /* bounds */,
@@ -528,6 +530,7 @@
                 if (updatePinnedStackBounds) {
                     mPinnedStackBounds.set(info.bounds);
                 }
+                mWindowManager.getStableInsets(info.displayId, mStableInsets);
                 mBoundedPinnedStackBounds.set(mWindowManager.getPictureInPictureMovementBounds(
                         info.displayId));
             }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
new file mode 100644
index 0000000..9c03830
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.pip.phone;
+
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+
+import android.app.ActivityManager.StackInfo;
+import android.app.IActivityManager;
+import android.content.ComponentName;
+import android.os.RemoteException;
+import android.util.Log;
+
+public class PipUtils {
+
+    private static final String TAG = "PipUtils";
+
+    /**
+     * @return the ComponentName of the top activity in the pinned stack, or null if none exists.
+     */
+    public static ComponentName getTopPinnedActivity(IActivityManager activityManager) {
+        try {
+            StackInfo pinnedStackInfo = activityManager.getStackInfo(PINNED_STACK_ID);
+            if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
+                    pinnedStackInfo.taskIds.length > 0) {
+                return pinnedStackInfo.topActivity;
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Unable to get pinned stack.");
+        }
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index a622656..56947e5 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -590,7 +590,7 @@
         @Override
         public void onTaskStackChanged() {
             if (DEBUG) Log.d(TAG, "onTaskStackChanged()");
-            if (!checkCurrentUserId()) {
+            if (!checkCurrentUserId(DEBUG)) {
                 return;
             }
             if (mState != STATE_NO_PIP) {
@@ -627,7 +627,7 @@
         @Override
         public void onActivityPinned() {
             if (DEBUG) Log.d(TAG, "onActivityPinned()");
-            if (!checkCurrentUserId()) {
+            if (!checkCurrentUserId(DEBUG)) {
                 return;
             }
             StackInfo stackInfo = getPinnedStackInfo();
@@ -658,9 +658,9 @@
         }
 
         @Override
-        public void onPinnedActivityRestartAttempt() {
+        public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) {
             if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
-            if (!checkCurrentUserId()) {
+            if (!checkCurrentUserId(DEBUG)) {
                 return;
             }
             // If PIPed activity is launched again by Launcher or intent, make it fullscreen.
@@ -670,7 +670,7 @@
         @Override
         public void onPinnedStackAnimationEnded() {
             if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()");
-            if (!checkCurrentUserId()) {
+            if (!checkCurrentUserId(DEBUG)) {
                 return;
             }
             switch (mState) {
@@ -693,26 +693,6 @@
                     break;
             }
         }
-
-        // {@link android.app.ITaskStackListener} isn't multi-user aware.
-        // Check the current uid and current SystemUI's running uid
-        // so we can handle the PIP status change only once.
-        private boolean checkCurrentUserId() {
-            try {
-                int processUserId = UserHandle.myUserId();
-                int currentUserId = mActivityManager.getCurrentUser().id;
-                if (processUserId != currentUserId) {
-                    if (DEBUG) {
-                        Log.d(TAG, "UID mismatch. SystemUI is running uid=" + processUserId
-                            + " and the current user is uid=" + currentUserId);
-                    }
-                    return false;
-                }
-            } catch (RemoteException e) {
-                Log.w(TAG, "Unable to get current user.");
-            }
-            return true;
-        }
     };
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index 26da551..b22ea4c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -1,9 +1,12 @@
 package com.android.systemui.qs;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
@@ -49,9 +52,14 @@
         while (numPages < getChildCount()) {
             removeViewAt(getChildCount() - 1);
         }
+        TypedArray array = getContext().obtainStyledAttributes(
+                new int[]{android.R.attr.colorForeground});
+        int color = array.getColor(0, 0);
+        array.recycle();
         while (numPages > getChildCount()) {
             ImageView v = new ImageView(mContext);
             v.setImageResource(R.drawable.minor_a_b);
+            v.setImageTintList(ColorStateList.valueOf(color));
             addView(v, new LayoutParams(mPageIndicatorWidth, mPageIndicatorHeight));
         }
         // Refresh state.
@@ -196,7 +204,7 @@
         for (int i = 0; i < N; i++) {
             getChildAt(i).measure(widthChildSpec, heightChildSpec);
         }
-        int width = (mPageIndicatorWidth - mPageDotWidth) * N + mPageDotWidth;
+        int width = (mPageIndicatorWidth - mPageDotWidth) * (N - 1) + mPageDotWidth;
         setMeasuredDimension(width, mPageIndicatorHeight);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 1c242e9..a231e79 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -29,7 +29,6 @@
     private PageIndicator mPageIndicator;
 
     private int mNumPages;
-    private View mDecorGroup;
     private PageListener mPageListener;
 
     private int mPosition;
@@ -145,14 +144,14 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mPageIndicator = (PageIndicator) findViewById(R.id.page_indicator);
-        mDecorGroup = findViewById(R.id.page_decor);
-        ((LayoutParams) mDecorGroup.getLayoutParams()).isDecor = true;
-
-        mPages.add((TilePage) LayoutInflater.from(mContext)
+        mPages.add((TilePage) LayoutInflater.from(getContext())
                 .inflate(R.layout.qs_paged_page, this, false));
     }
 
+    public void setPageIndicator(PageIndicator indicator) {
+        mPageIndicator = indicator;
+    }
+
     @Override
     public int getOffsetTop(TileRecord tile) {
         final ViewGroup parent = (ViewGroup) tile.tileView.getParent();
@@ -196,7 +195,7 @@
                 if (++index == mPages.size()) {
                     if (DEBUG) Log.d(TAG, "Adding page for "
                             + tile.tile.getClass().getSimpleName());
-                    mPages.add((TilePage) LayoutInflater.from(mContext)
+                    mPages.add((TilePage) LayoutInflater.from(getContext())
                             .inflate(R.layout.qs_paged_page, this, false));
                 }
             }
@@ -211,7 +210,7 @@
             }
             if (DEBUG) Log.d(TAG, "Size: " + mNumPages);
             mPageIndicator.setNumPages(mNumPages);
-            mDecorGroup.setVisibility(mNumPages > 1 ? View.VISIBLE : View.GONE);
+            mPageIndicator.setVisibility(mNumPages > 1 ? View.VISIBLE : View.GONE);
             setAdapter(mAdapter);
             mAdapter.notifyDataSetChanged();
             setCurrentItem(0, false);
@@ -243,8 +242,7 @@
                 maxHeight = height;
             }
         }
-        setMeasuredDimension(getMeasuredWidth(), maxHeight
-                + (mDecorGroup.getVisibility() != View.GONE ? mDecorGroup.getMeasuredHeight() : 0));
+        setMeasuredDimension(getMeasuredWidth(), maxHeight);
     }
 
     private final Runnable mDistribute = new Runnable() {
@@ -265,7 +263,7 @@
         public TilePage(Context context, AttributeSet attrs) {
             super(context, attrs);
             updateResources();
-            setContentDescription(mContext.getString(R.string.accessibility_desc_quick_settings));
+            setContentDescription(getContext().getString(R.string.accessibility_desc_quick_settings));
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index fdefcf9..409943d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -194,6 +194,7 @@
                 translationYBuilder.addFloat(label, "translationY", -yDiff, 0);
 
                 mTopFiveQs.add(tileIcon);
+                mTopFiveQs.add(tileView.getBgCicle());
                 mAllViews.add(tileIcon);
                 mAllViews.add(quickTileView);
             } else if (mFullRows && isIconInAnimatedRow(count)) {
@@ -223,9 +224,10 @@
             // Make brightness appear static position and alpha in through second half.
             View brightness = mQsPanel.getBrightnessView();
             if (brightness != null) {
-                firstPageBuilder.addFloat(brightness, "translationY", mQsPanel.getHeight(), 0);
+//                firstPageBuilder.addFloat(brightness, "translationY", mQsPanel.getHeight(), 0);
                 mBrightnessAnimator = new TouchAnimator.Builder()
                         .addFloat(brightness, "alpha", 0, 1)
+                        .addFloat(mQsPanel.getPageIndicator(), "alpha", 0, 1)
                         .setStartDelay(.5f)
                         .build();
                 mAllViews.add(brightness);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index f4da5ec..91b4d0d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -18,18 +18,12 @@
 
 import android.content.Context;
 import android.graphics.Point;
-import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
-import com.android.systemui.plugins.qs.QS.HeightListener;
 import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
-import com.android.systemui.statusbar.phone.QSTileHost;
-import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
 
 /**
  * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
@@ -95,7 +89,7 @@
         updateBottom();
     }
 
-    void updateBottom() {
+    public void updateBottom() {
         int height = calculateContainerHeight();
         setBottom(getTop() + height);
         mQSDetail.setBottom(getTop() + height);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
index 9c4a149..f28a0e7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSIconView.java
@@ -16,14 +16,20 @@
 
 package com.android.systemui.qs;
 
+import static com.android.systemui.qs.QSTile.getColorForState;
+
+import android.animation.ValueAnimator;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
+import android.graphics.Color;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
+
 import com.android.systemui.R;
 
 import java.util.Objects;
@@ -34,6 +40,8 @@
     protected final int mIconSizePx;
     protected final int mTilePaddingBelowIconPx;
     private boolean mAnimationEnabled = true;
+    private int mState = -1;
+    private int mTint;
 
     public QSIconView(Context context) {
         super(context);
@@ -65,7 +73,6 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         final int w = getMeasuredWidth();
-        final int h = getMeasuredHeight();
         int top = 0;
         final int iconLeft = (w - mIcon.getMeasuredWidth()) / 2;
         layout(mIcon, iconLeft, top);
@@ -100,8 +107,43 @@
         } else {
             iv.clearColorFilter();
         }
+        if (state.state != mState) {
+            int color = getColorForState(getContext(), state.state);
+            mState = state.state;
+            if (iv.isShown()) {
+                animateGrayScale(mTint, color, iv);
+                mTint = color;
+            } else {
+                setTint(iv, color);
+                mTint = color;
+            }
+        }
     }
 
+    public static void animateGrayScale(int fromColor, int toColor, ImageView iv) {
+        final float fromAlpha = Color.alpha(fromColor);
+        final float toAlpha = Color.alpha(toColor);
+        final float fromChannel = Color.red(fromColor);
+        final float toChannel = Color.red(toColor);
+
+        ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
+        anim.setDuration(350);
+
+        anim.addUpdateListener(animation -> {
+            float fraction = animation.getAnimatedFraction();
+            int alpha = (int) (fromAlpha + (toAlpha - fromAlpha) * fraction);
+            int channel = (int) (fromChannel + (toChannel - fromChannel) * fraction);
+
+            setTint(iv, Color.argb(alpha, channel, channel, channel));
+        });
+        anim.start();
+    }
+
+    public static void setTint(ImageView iv, int color) {
+        iv.setImageTintList(ColorStateList.valueOf(color));
+    }
+
+
     protected int getIconMeasureMode() {
         return MeasureSpec.EXACTLY;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 9feaa0a..2de32cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -54,6 +54,7 @@
     protected final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
     protected final View mBrightnessView;
     private final H mHandler = new H();
+    private final View mPageIndicator;
 
     private int mPanelPaddingBottom;
     private int mBrightnessPaddingTop;
@@ -84,21 +85,31 @@
 
         setOrientation(VERTICAL);
 
-        mBrightnessView = LayoutInflater.from(context).inflate(
-                R.layout.quick_settings_brightness_dialog, this, false);
-        addView(mBrightnessView);
-
         setupTileLayout();
 
         mFooter = new QSFooter(this, context);
         addView(mFooter.getView());
 
+        mPageIndicator = LayoutInflater.from(context).inflate(
+                R.layout.qs_page_indicator, this, false);
+        addView(mPageIndicator);
+        if (mTileLayout instanceof PagedTileLayout) {
+            ((PagedTileLayout) mTileLayout).setPageIndicator((PageIndicator) mPageIndicator);
+        }
+
         updateResources();
 
+        mBrightnessView = LayoutInflater.from(context).inflate(
+                R.layout.quick_settings_brightness_dialog, this, false);
+        addView(mBrightnessView);
+
         mBrightnessController = new BrightnessController(getContext(),
                 (ImageView) findViewById(R.id.brightness_icon),
                 (ToggleSliderView) findViewById(R.id.brightness_slider));
+    }
 
+    public View getPageIndicator() {
+        return mPageIndicator;
     }
 
     protected void setupTileLayout() {
@@ -359,20 +370,10 @@
         };
         r.tile.addCallback(callback);
         r.callback = callback;
-        final View.OnClickListener click = new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                onTileClick(r.tile);
-            }
-        };
-        final View.OnLongClickListener longClick = new View.OnLongClickListener() {
-            @Override
-            public boolean onLongClick(View v) {
-                r.tile.longClick();
-                return true;
-            }
-        };
-        r.tileView.init(click, longClick);
+        r.tileView.init(v -> r.tile.click(), v -> r.tile.secondaryClick(), v -> {
+            r.tile.longClick();
+            return true;
+        });
         r.tile.refreshState();
         mRecords.add(r);
 
@@ -402,10 +403,6 @@
         });
     }
 
-    protected void onTileClick(QSTile<?> tile) {
-        tile.click();
-    }
-
     public void closeDetail() {
         if (mCustomizePanel != null && mCustomizePanel.isShown()) {
             // Treat this as a detail panel for now, to make things easy.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index f73241c..dad37b0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -24,6 +24,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.service.quicksettings.Tile;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -52,8 +53,12 @@
 import java.util.Collection;
 import java.util.Objects;
 
+import com.android.settingslib.Utils;
+
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
+import com.android.systemui.R;
+
 /**
  * Base quick-settings tile, extend this to create a new tile.
  *
@@ -79,7 +84,9 @@
     private String mTileSpec;
 
     public abstract TState newTileState();
+
     abstract protected void handleClick();
+
     abstract protected void handleUpdateState(TState state, Object arg);
 
     /**
@@ -134,7 +141,9 @@
         return null; // optional
     }
 
-    protected DetailAdapter createDetailAdapter() { throw new UnsupportedOperationException(); }
+    protected DetailAdapter createDetailAdapter() {
+        throw new UnsupportedOperationException();
+    }
 
     /**
      * Is a startup check whether this device currently supports this tile.
@@ -319,6 +328,21 @@
 
     public abstract CharSequence getTileLabel();
 
+    public static int getColorForState(Context context, int state) {
+        switch (state) {
+            case Tile.STATE_UNAVAILABLE:
+                return Utils.getDisabled(context,
+                        Utils.getColorAttr(context, android.R.attr.textColorTertiary));
+            case Tile.STATE_INACTIVE:
+                return Utils.getColorAttr(context, android.R.attr.textColorSecondary);
+            case Tile.STATE_ACTIVE:
+                return Utils.getColorAttr(context, android.R.attr.colorPrimary);
+            default:
+                Log.e("QSTile", "Invalid state " + state);
+                return 0;
+        }
+    }
+
     protected final class H extends Handler {
         private static final int ADD_CALLBACK = 1;
         private static final int CLICK = 2;
@@ -546,6 +570,7 @@
 
     public static class State {
         public Icon icon;
+        public int state = Tile.STATE_ACTIVE;
         public CharSequence label;
         public CharSequence contentDescription;
         public CharSequence dualLabelContentDescription;
@@ -572,6 +597,7 @@
                     || !Objects.equals(other.expandedAccessibilityClassName,
                     expandedAccessibilityClassName)
                     || !Objects.equals(other.disabledByPolicy, disabledByPolicy)
+                    || !Objects.equals(other.state, state)
                     || !Objects.equals(other.enforcedAdmin, enforcedAdmin);
             other.icon = icon;
             other.label = label;
@@ -582,6 +608,7 @@
             other.expandedAccessibilityClassName = expandedAccessibilityClassName;
             other.autoMirrorDrawable = autoMirrorDrawable;
             other.disabledByPolicy = disabledByPolicy;
+            other.state = state;
             if (enforcedAdmin == null) {
                 other.enforcedAdmin = null;
             } else if (other.enforcedAdmin == null) {
@@ -609,6 +636,7 @@
             sb.append(",autoMirrorDrawable=").append(autoMirrorDrawable);
             sb.append(",disabledByPolicy=").append(disabledByPolicy);
             sb.append(",enforcedAdmin=").append(enforcedAdmin);
+            sb.append(",state=").append(state);
             return sb.append(']');
         }
     }
@@ -648,7 +676,6 @@
         public boolean connected;
         public boolean activityIn;
         public boolean activityOut;
-        public int overlayIconId;
         public boolean filter;
         public boolean isOverlayIconWide;
 
@@ -657,12 +684,10 @@
             final SignalState o = (SignalState) other;
             final boolean changed = o.connected != connected || o.activityIn != activityIn
                     || o.activityOut != activityOut
-                    || o.overlayIconId != overlayIconId
                     || o.isOverlayIconWide != isOverlayIconWide;
             o.connected = connected;
             o.activityIn = activityIn;
             o.activityOut = activityOut;
-            o.overlayIconId = overlayIconId;
             o.filter = filter;
             o.isOverlayIconWide = isOverlayIconWide;
             return super.copyTo(other) || changed;
@@ -674,7 +699,6 @@
             rt.insert(rt.length() - 1, ",connected=" + connected);
             rt.insert(rt.length() - 1, ",activityIn=" + activityIn);
             rt.insert(rt.length() - 1, ",activityOut=" + activityOut);
-            rt.insert(rt.length() - 1, ",overlayIconId=" + overlayIconId);
             rt.insert(rt.length() - 1, ",filter=" + filter);
             rt.insert(rt.length() - 1, ",wideOverlayIcon=" + isOverlayIconWide);
             return rt;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
index 2b7fcc5..a177cc3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileBaseView.java
@@ -15,31 +15,49 @@
  */
 package com.android.systemui.qs;
 
+import android.animation.ValueAnimator;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.service.quicksettings.Tile;
 import android.text.TextUtils;
+import android.util.Log;
+import android.view.Gravity;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
 import android.widget.LinearLayout;
 import android.widget.Switch;
 
+import com.android.settingslib.Utils;
+
 import com.android.systemui.R;
 
 public class QSTileBaseView extends LinearLayout {
 
+    private static final String TAG = "QSTileBaseView";
     private final H mHandler = new H();
+    private final ImageView mBg;
     protected QSIconView mIcon;
     protected RippleDrawable mRipple;
     private Drawable mTileBackground;
     private String mAccessibilityClass;
     private boolean mTileState;
     private boolean mCollapsedView;
+    private final int mColorActive;
+    private final int mColorInactive;
+    private final int mColorDisabled;
+    private int mCircleColor;
 
     public QSTileBaseView(Context context, QSIconView icon) {
         this(context, icon, false);
@@ -47,8 +65,26 @@
 
     public QSTileBaseView(Context context, QSIconView icon, boolean collapsedView) {
         super(context);
+        // Default to Quick Tile padding, and QSTileView will specify its own padding.
+        int padding = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding);
+
+        FrameLayout frame = new FrameLayout(context);
+        frame.setForegroundGravity(Gravity.CENTER);
+        int size = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
+        addView(frame, new LayoutParams(size, size));
+        mBg = new ImageView(getContext());
+        mBg.setScaleType(ScaleType.FIT_CENTER);
+        mBg.setImageResource(R.drawable.ic_qs_circle);
+        frame.addView(mBg);
         mIcon = icon;
-        addView(mIcon);
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        params.setMargins(0, padding, 0, padding);
+        frame.addView(mIcon, params);
+        mColorActive = Utils.getColorAttr(context, android.R.attr.textColorPrimary);
+        mColorDisabled = Utils.getDisabled(context,
+                Utils.getColorAttr(context, android.R.attr.textColorTertiary));
+        mColorInactive = Utils.getColorAttr(context, android.R.attr.textColorSecondary);
 
         mTileBackground = newTileBackground();
         if (mTileBackground instanceof RippleDrawable) {
@@ -57,18 +93,20 @@
         setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
         setBackground(mTileBackground);
 
-        // Default to Quick Tile padding, and QSTileView will specify its own padding.
-        int padding = context.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_padding);
-        setPadding(0, padding, 0, padding);
+        setPadding(0, 0, 0, 0);
         setClipChildren(false);
         setClipToPadding(false);
         mCollapsedView = collapsedView;
         setFocusable(true);
     }
 
+    public View getBgCicle() {
+        return mBg;
+    }
+
     protected Drawable newTileBackground() {
-        final int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless };
-        final TypedArray ta = mContext.obtainStyledAttributes(attrs);
+        final int[] attrs = new int[]{android.R.attr.selectableItemBackgroundBorderless};
+        final TypedArray ta = getContext().obtainStyledAttributes(attrs);
         final Drawable d = ta.getDrawable(0);
         ta.recycle();
         return d;
@@ -85,11 +123,12 @@
         // center the touch feedback on the center of the icon, and dial it down a bit
         final int cx = width / 2;
         final int cy = height / 2;
-        final int rad = (int)(mIcon.getHeight() * .85f);
+        final int rad = (int) (mIcon.getHeight() * .85f);
         mRipple.setHotspotBounds(cx - rad, cy - rad, cx + rad, cy + rad);
     }
 
-    public void init(OnClickListener click, OnLongClickListener longClick) {
+    public void init(OnClickListener click, OnClickListener secondaryClick,
+            OnLongClickListener longClick) {
         setClickable(true);
         setOnClickListener(click);
         setOnLongClickListener(longClick);
@@ -128,6 +167,16 @@
     }
 
     protected void handleStateChanged(QSTile.State state) {
+        int circleColor = getCircleColor(state.state);
+        if (circleColor != mCircleColor) {
+            if (mBg.isShown()) {
+                QSIconView.animateGrayScale(mCircleColor, circleColor, mBg);
+            } else {
+                QSIconView.setTint(mBg, circleColor);
+            }
+            mCircleColor = circleColor;
+        }
+
         mIcon.setIcon(state);
         if (mCollapsedView && !TextUtils.isEmpty(state.minimalContentDescription)) {
             setContentDescription(state.minimalContentDescription);
@@ -144,6 +193,19 @@
         }
     }
 
+    private int getCircleColor(int state) {
+        switch (state) {
+            case Tile.STATE_ACTIVE:
+                return mColorActive;
+            case Tile.STATE_INACTIVE:
+            case Tile.STATE_UNAVAILABLE:
+                return mColorDisabled;
+            default:
+                Log.e(TAG, "Invalid state " + state);
+                return 0;
+        }
+    }
+
     public QSIconView getIcon() {
         return mIcon;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index e59873a..7126f3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -16,27 +16,34 @@
 
 package com.android.systemui.qs;
 
+import static com.android.systemui.qs.QSTile.getColorForState;
+
 import android.content.Context;
 import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.util.MathUtils;
+import android.service.quicksettings.Tile;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
 import android.view.Gravity;
 import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
+
 import libcore.util.Objects;
 
 /** View that represents a standard quick settings tile. **/
 public class QSTileView extends QSTileBaseView {
-    private final int mTileSpacingPx;
-    private int mTilePaddingTopPx;
 
     protected TextView mLabel;
     private ImageView mPadLock;
+    private int mState;
+    private OnClickListener mClick;
+    private OnClickListener mSecondaryClick;
 
     public QSTileView(Context context, QSIconView icon) {
         this(context, icon, false);
@@ -45,13 +52,10 @@
     public QSTileView(Context context, QSIconView icon, boolean collapsedView) {
         super(context, icon, collapsedView);
 
-        final Resources res = context.getResources();
-        mTileSpacingPx = res.getDimensionPixelSize(R.dimen.qs_tile_spacing);
-
         setClipChildren(false);
+        setClipToPadding(false);
 
         setClickable(true);
-        updateTopPadding();
         setId(View.generateViewId());
         createLabel();
         setOrientation(VERTICAL);
@@ -62,27 +66,17 @@
         return mLabel;
     }
 
-    protected void updateTopPadding() {
-        Resources res = getResources();
-        int padding = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top);
-        int largePadding = res.getDimensionPixelSize(R.dimen.qs_tile_padding_top_large_text);
-        float largeFactor = (MathUtils.constrain(getResources().getConfiguration().fontScale,
-                1.0f, FontSizeUtils.LARGE_TEXT_SCALE) - 1f) / (FontSizeUtils.LARGE_TEXT_SCALE - 1f);
-        mTilePaddingTopPx = Math.round((1 - largeFactor) * padding + largeFactor * largePadding);
-        setPadding(mTileSpacingPx, mTilePaddingTopPx + mTileSpacingPx, mTileSpacingPx,
-                mTileSpacingPx);
-        requestLayout();
-    }
-
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        updateTopPadding();
         FontSizeUtils.updateFontSize(mLabel, R.dimen.qs_tile_text_size);
     }
 
     protected void createLabel() {
-        View view = LayoutInflater.from(mContext).inflate(R.layout.qs_tile_label, null);
+        ViewGroup view = (ViewGroup) LayoutInflater.from(getContext())
+                .inflate(R.layout.qs_tile_label, null);
+        view.setClipChildren(false);
+        view.setClipToPadding(false);
         mLabel = (TextView) view.findViewById(R.id.tile_label);
         mPadLock = (ImageView) view.findViewById(R.id.restricted_padlock);
         addView(view);
@@ -91,10 +85,32 @@
     @Override
     protected void handleStateChanged(QSTile.State state) {
         super.handleStateChanged(state);
-        if (!Objects.equal(mLabel.getText(), state.label)) {
+        if (!Objects.equal(mLabel.getText(), state.label) || mState != state.state) {
+            if (state.state == Tile.STATE_UNAVAILABLE) {
+                int color = getColorForState(getContext(), state.state);
+                state.label = new SpannableStringBuilder().append(state.label,
+                        new ForegroundColorSpan(color),
+                        SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
+            }
+            mState = state.state;
             mLabel.setText(state.label);
         }
         mLabel.setEnabled(!state.disabledByPolicy);
         mPadLock.setVisibility(state.disabledByPolicy ? View.VISIBLE : View.GONE);
     }
+
+    @Override
+    public void init(OnClickListener click, OnClickListener secondaryClick, OnLongClickListener longClick) {
+        mClick = click;
+        mSecondaryClick = secondaryClick;
+        super.init(click, secondaryClick, longClick);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getActionMasked() == MotionEvent.ACTION_UP)  {
+            setOnClickListener(event.getY() < (getMeasuredHeight() / 2) ? mClick : mSecondaryClick);
+        }
+        return super.onTouchEvent(event);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index de3e19c..16b351e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -56,7 +56,7 @@
         }
         mTileLayout = new HeaderTileLayout(context);
         mTileLayout.setListening(mListening);
-        addView((View) mTileLayout, 1 /* Between brightness and footer */);
+        addView((View) mTileLayout, 0 /* Between brightness and footer */);
     }
 
     @Override
@@ -113,11 +113,6 @@
     }
 
     @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)) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index b2bfa06..8555e31 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -33,7 +33,6 @@
 
     private FrameLayout mIconFrame;
     private ImageView mSignal;
-    private ImageView mOverlay;
     private ImageView mIn;
     private ImageView mOut;
 
@@ -62,8 +61,6 @@
         mIconFrame = new FrameLayout(mContext);
         mSignal = new ImageView(mContext);
         mIconFrame.addView(mSignal);
-        mOverlay = new ImageView(mContext);
-        mIconFrame.addView(mOverlay, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         return mIconFrame;
     }
 
@@ -109,17 +106,6 @@
     public void setIcon(QSTile.State state) {
         final SignalState s = (SignalState) state;
         setIcon(mSignal, s);
-        if (s.overlayIconId > 0) {
-            mOverlay.setVisibility(VISIBLE);
-            mOverlay.setImageResource(s.overlayIconId);
-        } else {
-            mOverlay.setVisibility(GONE);
-        }
-        if (s.overlayIconId > 0 && s.isOverlayIconWide) {
-            mSignal.setPaddingRelative(mWideOverlayIconStartPadding, 0, 0, 0);
-        } else {
-            mSignal.setPaddingRelative(0, 0, 0, 0);
-        }
         Drawable drawable = mSignal.getDrawable();
         if (state.autoMirrorDrawable && drawable != null) {
             drawable.setAutoMirrored(true);
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 9e3889b..cff4846 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -15,15 +15,10 @@
  */
 package com.android.systemui.qs.external;
 
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
-
 import android.app.ActivityManager;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.graphics.drawable.Drawable;
@@ -39,14 +34,19 @@
 import android.text.style.ForegroundColorSpan;
 import android.util.Log;
 import android.view.IWindowManager;
+import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
 import com.android.systemui.statusbar.phone.QSTileHost;
 import libcore.util.Objects;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+
 public class CustomTile extends QSTile<QSTile.State> implements TileChangeListener {
     public static final String PREFIX = "custom(";
 
@@ -63,7 +63,6 @@
     private final IQSTileService mService;
     private final TileServiceManager mServiceManager;
     private final int mUser;
-    private Context mAppContext;
     private android.graphics.drawable.Icon mDefaultIcon;
 
     private boolean mListening;
@@ -81,10 +80,6 @@
         mService = mServiceManager.getTileService();
         mServiceManager.setTileChangeListener(this);
         mUser = ActivityManager.getCurrentUser();
-        try {
-            mAppContext = mContext.createPackageContext(mComponent.getPackageName(), 0);
-        } catch (NameNotFoundException e) {
-        }
     }
 
     private void setTileIcon() {
@@ -287,27 +282,17 @@
         if (mServiceManager.hasPendingBind()) {
             tileState = Tile.STATE_UNAVAILABLE;
         }
+        state.state = tileState;
         Drawable drawable;
-        boolean mHasRes = false;
-        android.graphics.drawable.Icon icon = mTile.getIcon();
         try {
-            drawable = icon.loadDrawable(mAppContext);
-            mHasRes = icon.getType() == android.graphics.drawable.Icon.TYPE_RESOURCE;
+            drawable = mTile.getIcon().loadDrawable(mContext);
         } catch (Exception e) {
             Log.w(TAG, "Invalid icon, forcing into unavailable state");
             tileState = Tile.STATE_UNAVAILABLE;
-            drawable = mDefaultIcon.loadDrawable(mAppContext);
+            drawable = mDefaultIcon.loadDrawable(mContext);
         }
-        final int color = TileColorPicker.getInstance(mContext).getColor(tileState);
-        drawable.setTint(color);
-        state.icon = mHasRes ? new DrawableIconWithRes(drawable, icon.getResId())
-                : new DrawableIcon(drawable);
+        state.icon = new DrawableIcon(drawable);
         state.label = mTile.getLabel();
-        if (tileState == Tile.STATE_UNAVAILABLE) {
-            state.label = new SpannableStringBuilder().append(state.label,
-                    new ForegroundColorSpan(color),
-                    SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
-        }
         if (mTile.getContentDescription() != null) {
             state.contentDescription = mTile.getContentDescription();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index e57cd58..e8f90ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -23,6 +23,7 @@
 import android.net.ConnectivityManager;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -92,6 +93,7 @@
         } else {
             state.icon = mDisable;
         }
+        state.state = airplaneMode ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.contentDescription = state.label;
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
                 = Switch.class.getName();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 833375e..a82f550 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -19,10 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
 import android.service.quicksettings.Tile;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
@@ -44,7 +41,6 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QS.DetailAdapter;
 import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.external.TileColorPicker;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.policy.BatteryController;
 
@@ -105,6 +101,11 @@
 
     @Override
     protected void handleClick() {
+        mBatteryController.setPowerSaveMode(!mPowerSave);
+    }
+
+    @Override
+    protected void handleSecondaryClick() {
         showDetail(true);
     }
 
@@ -118,26 +119,10 @@
         int level = (arg != null) ? (Integer) arg : mLevel;
         String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
 
-        state.icon = new Icon() {
-            @Override
-            public Drawable getDrawable(Context context) {
-                BatteryMeterDrawable drawable =
-                        new BatteryMeterDrawable(context,
-                        context.getColor(R.color.batterymeter_frame_color));
-                drawable.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
-                drawable.onPowerSaveChanged(mPowerSave);
-                final int color = TileColorPicker.getInstance(context).getColor(Tile.STATE_ACTIVE);
-                drawable.setColorFilter(new PorterDuffColorFilter(color, Mode.SRC_IN));
-                return drawable;
-            }
-
-            @Override
-            public int getPadding() {
-                return mHost.getContext().getResources().getDimensionPixelSize(
-                        R.dimen.qs_battery_padding);
-            }
-        };
-        state.label = percentage;
+        state.state = mCharging ? Tile.STATE_UNAVAILABLE
+                : mPowerSave ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+        state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver);
+        state.label = mContext.getString(R.string.battery_detail_switch_title);
         state.contentDescription = mContext.getString(R.string.accessibility_quick_settings_battery,
                 percentage) + "," +
                 (mPowerSave ? mContext.getString(R.string.battery_saver_notification_title)
@@ -153,7 +138,7 @@
         mLevel = level;
         mPluggedIn = pluggedIn;
         mCharging = charging;
-        refreshState((Integer) level);
+        refreshState(level);
         if (mDetailShown) {
             mBatteryDetail.postBindView();
         }
@@ -213,11 +198,6 @@
             mDrawable.onBatteryLevelChanged(100, false, false);
             mDrawable.onPowerSaveChanged(true);
             mDrawable.disableShowPercent();
-
-            final int color = TileColorPicker.getInstance(mCurrentView.getContext())
-                    .getColor(Tile.STATE_ACTIVE);
-            mDrawable.setColorFilter(new PorterDuffColorFilter(color, Mode.SRC_IN));
-
             ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
             Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
             checkbox.setChecked(mPowerSave);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index f83b279..15f3c90 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
@@ -74,7 +75,7 @@
     }
 
     @Override
-    protected void handleSecondaryClick() {
+    protected void handleClick() {
         // Secondary clicks are header clicks, just toggle.
         final boolean isEnabled = (Boolean)mState.value;
         MetricsLogger.action(mContext, getMetricsCategory(), !isEnabled);
@@ -87,7 +88,7 @@
     }
 
     @Override
-    protected void handleClick() {
+    protected void handleSecondaryClick() {
         if (!mController.canConfigBluetooth()) {
             mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
             return;
@@ -140,11 +141,13 @@
             if (TextUtils.isEmpty(state.label)) {
                 state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
             }
+            state.state = Tile.STATE_ACTIVE;
         } else {
             state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_off);
             state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_bluetooth_off);
+            state.state = Tile.STATE_INACTIVE;
         }
 
         CharSequence bluetoothName = state.label;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 8afa91e..d61e2f2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
@@ -93,6 +94,11 @@
     }
 
     @Override
+    protected void handleSecondaryClick() {
+        handleClick();
+    }
+
+    @Override
     protected void handleClick() {
         if (mKeyguard.isSecure() && !mKeyguard.canSkipBouncer()) {
             mHost.startRunnableDismissingKeyguard(new Runnable() {
@@ -135,6 +141,7 @@
         if (!state.value && connecting) {
             state.label = mContext.getString(R.string.quick_settings_connecting);
         }
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.icon = ResourceIcon.get(state.value ? R.drawable.ic_qs_cast_on
                 : R.drawable.ic_qs_cast_off);
         mDetailAdapter.updateItems(devices);
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 1406c9f..5f7c803 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.service.quicksettings.Tile;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -86,6 +87,11 @@
 
     @Override
     protected void handleClick() {
+        mDataController.setMobileDataEnabled(!mDataController.isMobileDataEnabled());
+    }
+
+    @Override
+    protected void handleSecondaryClick() {
         MetricsLogger.action(mContext, getMetricsCategory());
         if (mDataController.isMobileDataSupported()) {
             showDetail(true);
@@ -111,10 +117,13 @@
                 : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
                 : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
                 : R.drawable.ic_qs_signal_no_signal;
-        state.icon = ResourceIcon.get(iconId);
+        if (cb.dataTypeIconId != 0) {
+            state.icon = ResourceIcon.get(cb.dataTypeIconId);
+        } else {
+            state.icon = ResourceIcon.get(iconId);
+        }
         state.isOverlayIconWide = cb.isDataTypeIconWide;
         state.autoMirrorDrawable = !cb.noSim;
-        state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) ? cb.dataTypeIconId : 0;
         state.filter = iconId != R.drawable.ic_qs_no_sim;
         state.activityIn = cb.enabled && cb.activityIn;
         state.activityOut = cb.enabled && cb.activityOut;
@@ -148,6 +157,7 @@
                 = Button.class.getName();
         state.value = mDataController.isMobileDataSupported()
                 && mDataController.isMobileDataEnabled();
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 77f063d..0a8afb0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -19,6 +19,7 @@
 import android.content.Intent;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
+import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -95,6 +96,7 @@
         final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue();
         final boolean enabled = value != 0;
         state.value = enabled;
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.label = mContext.getString(R.string.quick_settings_inversion_label);
         state.icon = enabled ? mEnable : mDisable;
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 65432dc..aadc8e7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -16,6 +16,7 @@
 
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -96,6 +97,7 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         state.value = arg instanceof Boolean ? (Boolean) arg
                 : mDataSaverController.isDataSaverEnabled();
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.label = mContext.getString(R.string.data_saver);
         state.contentDescription = state.label;
         state.icon = ResourceIcon.get(state.value ? R.drawable.ic_data_saver
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 198375d..a25b7ea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -25,6 +25,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.service.quicksettings.Tile;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
@@ -121,7 +122,17 @@
     }
 
     @Override
-    public void handleClick() {
+    protected void handleClick() {
+        if (mState.value) {
+            mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
+        } else {
+            int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
+            mController.setZen(zen, null, TAG);
+        }
+    }
+
+    @Override
+    protected void handleSecondaryClick() {
         if (mController.isVolumeRestricted()) {
             // Collapse the panels, so the user can see the toast.
             mHost.collapsePanels();
@@ -131,13 +142,9 @@
             return;
         }
         MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
-        if (mState.value) {
-            mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
-        } else {
-            showDetail(true);
-            int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
-            mController.setZen(zen, null, TAG);
-        }
+        showDetail(true);
+        int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
+        mController.setZen(zen, null, TAG);
     }
 
     @Override
@@ -151,6 +158,7 @@
         final boolean newValue = zen != Global.ZEN_MODE_OFF;
         final boolean valueChanged = state.value != newValue;
         state.value = newValue;
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
         switch (zen) {
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 416c7ce..4bbc458 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -29,7 +29,6 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.external.TileColorPicker;
 import com.android.systemui.statusbar.policy.FlashlightController;
 
 /** Quick settings tile: Control flashlight **/
@@ -47,11 +46,13 @@
     public FlashlightTile(Host host) {
         super(host);
         mFlashlightController = host.getFlashlightController();
+        mFlashlightController.addCallback(this);
     }
 
     @Override
     protected void handleDestroy() {
         super.handleDestroy();
+        mFlashlightController.removeCallback(this);
     }
 
     @Override
@@ -107,17 +108,12 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
         if (!mFlashlightController.isAvailable()) {
-            Drawable icon = mHost.getContext().getDrawable(R.drawable.ic_signal_flashlight_disable)
+            Drawable icon = mHost.getContext().getDrawable(R.drawable.ic_signal_flashlight_enable)
                     .mutate();
-            final int disabledColor = TileColorPicker.getInstance(mContext)
-                    .getColor(Tile.STATE_UNAVAILABLE);
-            icon.setTint(disabledColor);
             state.icon = new DrawableIcon(icon);
-            state.label = new SpannableStringBuilder().append(state.label,
-                    new ForegroundColorSpan(disabledColor),
-                    SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_flashlight_unavailable);
+            state.state = Tile.STATE_UNAVAILABLE;
             return;
         }
         if (arg instanceof Boolean) {
@@ -134,6 +130,7 @@
         state.contentDescription = mContext.getString(R.string.quick_settings_flashlight_label);
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
                 = Switch.class.getName();
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
     @Override
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 99485bb..9d495ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -32,7 +32,6 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.external.TileColorPicker;
 import com.android.systemui.statusbar.policy.HotspotController;
 
 /** Quick settings tile: Hotspot **/
@@ -126,11 +125,6 @@
         boolean wasAirplane = state.isAirplaneMode;
         state.isAirplaneMode = mAirplaneMode.getValue() != 0;
         if (state.isAirplaneMode) {
-            final int disabledColor = TileColorPicker.getInstance(mContext)
-                    .getColor(Tile.STATE_UNAVAILABLE);
-            state.label = new SpannableStringBuilder().append(state.label,
-                    new ForegroundColorSpan(disabledColor),
-                    SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
             state.icon = mUnavailable;
         } else if (wasAirplane) {
             state.icon = mDisableNoAnimation;
@@ -138,6 +132,8 @@
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
                 = Switch.class.getName();
         state.contentDescription = state.label;
+        state.state = state.isAirplaneMode ? Tile.STATE_UNAVAILABLE
+                : state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 8a9a696..002e2a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -20,6 +20,7 @@
 import android.os.UserManager;
 
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -115,6 +116,7 @@
             state.contentDescription = mContext.getString(
                     R.string.accessibility_quick_settings_location_off);
         }
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
                 = Switch.class.getName();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 10fde30..b8ba28d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManager;
 import android.content.Intent;
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.app.NightDisplayController;
@@ -81,6 +82,7 @@
                 : R.drawable.ic_qs_night_display_off);
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName =
                 Switch.class.getName();
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index cec5f15..9be67da 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -21,6 +21,7 @@
 import android.content.res.Configuration;
 
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -106,6 +107,7 @@
         state.contentDescription = getAccessibilityString(rotationLocked);
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
                 = Switch.class.getName();
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
     public static boolean isCurrentOrientationLockPortrait(RotationLockController controller,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 3876c88..7d99041 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -104,7 +105,7 @@
     }
 
     @Override
-    protected void handleSecondaryClick() {
+    protected void handleClick() {
         // Secondary clicks are header clicks, just toggle.
         mState.copyTo(mStateBeforeClick);
         MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
@@ -112,7 +113,7 @@
     }
 
     @Override
-    protected void handleClick() {
+    protected void handleSecondaryClick() {
         if (!mWifiController.canConfigWifi()) {
             mHost.startActivityDismissingKeyguard(new Intent(Settings.ACTION_WIFI_SETTINGS));
             return;
@@ -191,6 +192,7 @@
         state.dualLabelContentDescription = wifiName;
         state.expandedAccessibilityClassName = Button.class.getName();
         state.minimalAccessibilityClassName = Switch.class.getName();
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index ce7fbd3..207deff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -18,6 +18,7 @@
 
 import android.content.Intent;
 import android.provider.Settings;
+import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
 import com.android.internal.logging.MetricsLogger;
@@ -108,6 +109,7 @@
         }
         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
                 = Switch.class.getName();
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d5a6a58..06fadd1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -76,6 +76,8 @@
 import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
+import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
+import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
 import com.android.systemui.recents.misc.DozeTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
@@ -599,13 +601,12 @@
                 }
                 return true;
             }
-            case KeyEvent.KEYCODE_DPAD_UP: {
-                EventBus.getDefault().send(
-                        new FocusNextTaskViewEvent(0 /* timerIndicatorDuration */));
-                return true;
-            }
-            case KeyEvent.KEYCODE_DPAD_DOWN: {
-                EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT: {
+                final Direction direction = NavigateTaskViewEvent.getDirectionFromKeyCode(keyCode);
+                EventBus.getDefault().send(new NavigateTaskViewEvent(direction));
                 return true;
             }
             case KeyEvent.KEYCODE_DEL:
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java
new file mode 100644
index 0000000..5508d26
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.ui.focus;
+
+import android.view.KeyEvent;
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * Navigates the task view by arrow keys.
+ */
+public class NavigateTaskViewEvent extends EventBus.Event {
+    public enum Direction {
+        UNDEFINED, UP, DOWN, LEFT, RIGHT;
+    }
+
+    public Direction direction;
+    public NavigateTaskViewEvent(Direction direction) {
+        this.direction = direction;
+    }
+
+    public static Direction getDirectionFromKeyCode(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_UP:
+                return Direction.UP;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                return Direction.DOWN;
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                return Direction.LEFT;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                return Direction.RIGHT;
+            default:
+                return Direction.UNDEFINED;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index a2b86d1..49074a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -79,6 +79,7 @@
 
 import com.android.internal.app.AssistUtils;
 import com.android.internal.os.BackgroundThread;
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.R;
 import com.android.systemui.pip.tv.PipMenuActivity;
 import com.android.systemui.pip.tv.PipOnboardingActivity;
@@ -152,11 +153,30 @@
         public void onTaskStackChanged() { }
         public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
         public void onActivityPinned() { }
-        public void onPinnedActivityRestartAttempt() { }
+        public void onPinnedActivityRestartAttempt(ComponentName sourceComponent) { }
         public void onPinnedStackAnimationEnded() { }
         public void onActivityForcedResizable(String packageName, int taskId) { }
         public void onActivityDismissingDockedStack() { }
         public void onTaskProfileLocked(int taskId, int userId) { }
+
+        /**
+         * Checks that the current user matches the user's SystemUI process. Since
+         * {@link android.app.ITaskStackListener} is not multi-user aware, handlers of
+         * TaskStackListener should make this call to verify that we don't act on events from other
+         * user's processes.
+         */
+        protected final boolean checkCurrentUserId(boolean debug) {
+            int processUserId = UserHandle.myUserId();
+            int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+            if (processUserId != currentUserId) {
+                if (debug) {
+                    Log.d(TAG, "UID mismatch. SystemUI is running uid=" + processUserId
+                            + " and the current user is uid=" + currentUserId);
+                }
+                return false;
+            }
+            return true;
+        }
     }
 
     /**
@@ -178,9 +198,11 @@
         }
 
         @Override
-        public void onPinnedActivityRestartAttempt() throws RemoteException{
+        public void onPinnedActivityRestartAttempt(ComponentName sourceComponent)
+                throws RemoteException{
             mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
-            mHandler.sendEmptyMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
+            mHandler.obtainMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT, sourceComponent)
+                    .sendToTarget();
         }
 
         @Override
@@ -1214,7 +1236,8 @@
                 }
                 case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
                     for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                        mTaskStackListeners.get(i).onPinnedActivityRestartAttempt();
+                        mTaskStackListeners.get(i).onPinnedActivityRestartAttempt(
+                                (ComponentName) msg.obj);
                     }
                     break;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java b/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
index d64a676..79a774f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
@@ -30,6 +30,7 @@
 import android.util.Log;
 
 import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsConfiguration;
 
 /**
@@ -90,8 +91,10 @@
         mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
         mCornerShadowPaint.setStyle(Paint.Style.FILL);
         mCornerShadowPaint.setDither(true);
-        mCornerRadius = resources.getDimensionPixelSize(
-                R.dimen.recents_task_view_rounded_corners_radius);
+        mCornerRadius = Recents.getConfiguration().isGridEnabled ?
+                resources.getDimensionPixelSize(
+                    R.dimen.recents_grid_task_view_rounded_corners_radius) :
+                resources.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
         mCardBounds = new RectF();
         mEdgeShadowPaint = new Paint(mCornerShadowPaint);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index fc2550a..8ae7a83 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -87,6 +87,7 @@
 import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
+import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
 import com.android.systemui.recents.misc.DozeTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
@@ -265,8 +266,9 @@
         mStackScroller = new TaskStackViewScroller(context, this, mLayoutAlgorithm);
         mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
         mAnimationHelper = new TaskStackAnimationHelper(context, this);
-        mTaskCornerRadiusPx = res.getDimensionPixelSize(
-                R.dimen.recents_task_view_rounded_corners_radius);
+        mTaskCornerRadiusPx = Recents.getConfiguration().isGridEnabled ?
+                res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
+                res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
         mDividerSize = ssp.getDockedDividerSize(context);
         mDisplayOrientation = Utilities.getAppConfiguration(mContext).orientation;
         mDisplayRect = ssp.getDisplayRect();
@@ -1869,6 +1871,26 @@
         setRelativeFocusedTask(false, false /* stackTasksOnly */, true /* animated */);
     }
 
+    public final void onBusEvent(NavigateTaskViewEvent event) {
+        if (useGridLayout()) {
+            final int taskCount = mStack.getTaskCount();
+            final int currentIndex = mStack.indexOfStackTask(getFocusedTask());
+            final int nextIndex = mLayoutAlgorithm.mTaskGridLayoutAlgorithm.navigateFocus(taskCount,
+                    currentIndex, event.direction);
+            setFocusedTask(nextIndex, false, true);
+        } else {
+            switch (event.direction) {
+                case UP:
+                    EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
+                    break;
+                case DOWN:
+                    EventBus.getDefault().send(
+                        new FocusNextTaskViewEvent(0 /* timerIndicatorDuration */));
+                    break;
+            }
+        }
+    }
+
     public final void onBusEvent(UserInteractionEvent event) {
         // Poke the doze trigger on user interaction
         mUIDozeTrigger.poke();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index c0cc83f..0777163 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -201,7 +201,9 @@
         Resources res = context.getResources();
         mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
         mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
-        mCornerRadius = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
+        mCornerRadius = Recents.getConfiguration().isGridEnabled ?
+                res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
+                res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
         mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
         mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
         mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index bae5daa..792679b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -60,11 +60,11 @@
 
     // Drawing
     @ViewDebug.ExportedProperty(category="recents")
-    private Rect mTaskViewRect = new Rect();
+    protected Rect mTaskViewRect = new Rect();
     @ViewDebug.ExportedProperty(category="recents")
-    private Rect mThumbnailRect = new Rect();
+    protected Rect mThumbnailRect = new Rect();
     @ViewDebug.ExportedProperty(category="recents")
-    private float mThumbnailScale;
+    protected float mThumbnailScale;
     private float mFullscreenThumbnailScale;
     /** The height, in pixels, of the task view's title bar. */
     private int mTitleBarHeight;
@@ -72,14 +72,14 @@
     private boolean mOverlayHeaderOnThumbnailActionBar = true;
     private ThumbnailData mThumbnailData;
 
-    private int mCornerRadius;
+    protected int mCornerRadius;
     @ViewDebug.ExportedProperty(category="recents")
     private float mDimAlpha;
     private Matrix mMatrix = new Matrix();
-    private Paint mDrawPaint = new Paint();
+    protected Paint mDrawPaint = new Paint();
     private Paint mLockedPaint = new Paint();
-    private Paint mBgFillPaint = new Paint();
-    private BitmapShader mBitmapShader;
+    protected Paint mBgFillPaint = new Paint();
+    protected BitmapShader mBitmapShader;
     private LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
 
     // Clip the top of the thumbnail against the opaque header bar that overlaps this view
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java
new file mode 100644
index 0000000..2c3e42b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views.grid;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.util.AttributeSet;
+
+import com.android.systemui.R;
+import com.android.systemui.recents.views.TaskViewThumbnail;
+
+public class GridTaskViewThumbnail extends TaskViewThumbnail {
+
+    private Path mThumbnailOutline;
+    private Path mRestBackgroundOutline;
+    private Path mFullBackgroundOutline;
+    // True if either this view's size or thumbnail scale has changed and mThumbnailOutline should
+    // be updated.
+    private boolean mUpdateThumbnailOutline = true;
+
+    public GridTaskViewThumbnail(Context context) {
+        this(context, null);
+    }
+
+    public GridTaskViewThumbnail(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr,
+        int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mCornerRadius = getResources().getDimensionPixelSize(
+                R.dimen.recents_grid_task_view_rounded_corners_radius);
+    }
+
+    /**
+     * Called when the task view frame changes, allowing us to move the contents of the header
+     * to match the frame changes.
+     */
+    public void onTaskViewSizeChanged(int width, int height) {
+        mUpdateThumbnailOutline = true;
+        super.onTaskViewSizeChanged(width, height);
+    }
+
+    /**
+     * Updates the scale of the bitmap relative to this view.
+     */
+    public void updateThumbnailMatrix() {
+        mUpdateThumbnailOutline = true;
+        super.updateThumbnailMatrix();
+    }
+
+    private void updateThumbnailOutline() {
+        final int titleHeight = getResources().getDimensionPixelSize(
+            R.dimen.recents_grid_task_view_header_height);
+        final int viewWidth = mTaskViewRect.width();
+        final int viewHeight = mTaskViewRect.height() - titleHeight;
+        final int thumbnailWidth = Math.min(viewWidth,
+            (int) (mThumbnailRect.width() * mThumbnailScale));
+        final int thumbnailHeight = Math.min(viewHeight,
+            (int) (mThumbnailRect.height() * mThumbnailScale));
+        // Draw the thumbnail, we only round the bottom corners:
+        //
+        // outerLeft                outerRight
+        //    <----------------------->            mRestBackgroundOutline
+        //    _________________________            (thumbnailWidth < viewWidth)
+        //    |_______________________| outerTop     A ____ B
+        //    |                       |    ↑           |  |
+        //    |                       |    |           |  |
+        //    |                       |    |           |  |
+        //    |                       |    |           |  | C
+        //    \_______________________/    ↓           |__/
+        //  mCornerRadius             outerBottom    E    D
+        //
+        //  mRestBackgroundOutline (thumbnailHeight < viewHeight)
+        //  A _________________________ B
+        //    |                       | C
+        //  F \_______________________/
+        //    E                       D
+        final int outerLeft = 0;
+        final int outerTop = 0;
+        final int outerRight = outerLeft + thumbnailWidth;
+        final int outerBottom = outerTop + thumbnailHeight;
+        mThumbnailOutline = new Path();
+        mThumbnailOutline.moveTo(outerLeft, outerTop);
+        mThumbnailOutline.lineTo(outerRight, outerTop);
+        mThumbnailOutline.lineTo(outerRight, outerBottom - mCornerRadius);
+        mThumbnailOutline.arcTo(outerRight -  2 * mCornerRadius, outerBottom - 2 * mCornerRadius,
+                outerRight, outerBottom, 0, 90, false);
+        mThumbnailOutline.lineTo(outerLeft + mCornerRadius, outerBottom);
+        mThumbnailOutline.arcTo(outerLeft, outerBottom - 2 * mCornerRadius,
+                outerLeft + 2 * mCornerRadius, outerBottom, 90, 90, false);
+        mThumbnailOutline.lineTo(outerLeft, outerTop);
+        mThumbnailOutline.close();
+
+        if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
+            if (thumbnailWidth < viewWidth) {
+                final int l = Math.max(0, outerRight - mCornerRadius);
+                final int r = outerRight;
+                final int t = outerTop;
+                final int b = outerBottom;
+                mRestBackgroundOutline = new Path();
+                mRestBackgroundOutline.moveTo(l, t); // A
+                mRestBackgroundOutline.lineTo(r, t); // B
+                mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C
+                mRestBackgroundOutline.arcTo(r -  2 * mCornerRadius, b - 2 * mCornerRadius, r, b,
+                        0, 90, false); // D
+                mRestBackgroundOutline.lineTo(l, b); // E
+                mRestBackgroundOutline.lineTo(l, t); // A
+                mRestBackgroundOutline.close();
+
+            }
+            if (thumbnailHeight < viewHeight) {
+                final int l = outerLeft;
+                final int r = outerRight;
+                final int t = Math.max(0, thumbnailHeight - mCornerRadius);
+                final int b = outerBottom;
+                mRestBackgroundOutline = new Path();
+                mRestBackgroundOutline.moveTo(l, t); // A
+                mRestBackgroundOutline.lineTo(r, t); // B
+                mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C
+                mRestBackgroundOutline.arcTo(r -  2 * mCornerRadius, b - 2 * mCornerRadius, r, b,
+                        0, 90, false); // D
+                mRestBackgroundOutline.lineTo(l + mCornerRadius, b); // E
+                mRestBackgroundOutline.arcTo(l, b - 2 * mCornerRadius, l + 2 * mCornerRadius, b,
+                        90, 90, false); // F
+                mRestBackgroundOutline.lineTo(l, t); // A
+                mRestBackgroundOutline.close();
+
+            }
+        } else {
+            mFullBackgroundOutline = mThumbnailOutline;
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        final int titleHeight = getResources().getDimensionPixelSize(
+            R.dimen.recents_grid_task_view_header_height);
+        final int viewWidth = mTaskViewRect.width();
+        final int viewHeight = mTaskViewRect.height() - titleHeight;
+        final int thumbnailWidth = Math.min(viewWidth,
+            (int) (mThumbnailRect.width() * mThumbnailScale));
+        final int thumbnailHeight = Math.min(viewHeight,
+            (int) (mThumbnailRect.height() * mThumbnailScale));
+
+        if (mUpdateThumbnailOutline) {
+            updateThumbnailOutline();
+            mUpdateThumbnailOutline = false;
+        }
+        if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
+            // Draw the background, there will be some small overdraw with the thumbnail
+            if (thumbnailWidth < viewWidth) {
+                // Portrait thumbnail on a landscape task view
+                canvas.drawPath(mRestBackgroundOutline, mBgFillPaint);
+            }
+            if (thumbnailHeight < viewHeight) {
+                // Landscape thumbnail on a portrait task view
+                canvas.drawPath(mRestBackgroundOutline, mBgFillPaint);
+            }
+            canvas.drawPath(mThumbnailOutline, mDrawPaint);
+        } else {
+            canvas.drawPath(mFullBackgroundOutline, mBgFillPaint);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
index 70536b1..02d1cc1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
@@ -23,6 +23,8 @@
 import android.view.WindowManager;
 
 import com.android.systemui.R;
+import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
+import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskViewTransform;
@@ -63,6 +65,8 @@
         Rect size;
         int[] xOffsets;
         int[] yOffsets;
+        int tasksPerLine;
+        int lines;
 
         TaskGridRectInfo(int taskCount) {
             size = new Rect();
@@ -71,10 +75,10 @@
 
             int layoutTaskCount = Math.min(MAX_LAYOUT_TASK_COUNT, taskCount);
 
-            int tasksPerLine = layoutTaskCount < 2 ? 1 : (
+            tasksPerLine = layoutTaskCount < 2 ? 1 : (
                 layoutTaskCount < 5 ? 2 : (
                     layoutTaskCount < 7 ? 3 : 4));
-            int lines = layoutTaskCount < 3 ? 1 : 2;
+            lines = layoutTaskCount < 3 ? 1 : 2;
 
             // A couple of special cases.
             boolean landscapeWindow = mWindowRect.width() > mWindowRect.height();
@@ -101,11 +105,13 @@
             if (maxTaskHeight >= maxTaskWidth / mAppAspectRatio + mTitleBarHeight) {
                 // Width bound.
                 taskWidth = maxTaskWidth;
-                taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight);
+                // Here we should round the height to the nearest integer.
+                taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight + 0.5);
             } else {
                 // Height bound.
                 taskHeight = maxTaskHeight;
-                taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio);
+                // Here we should round the width to the nearest integer.
+                taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio + 0.5);
             }
             size.set(0, 0, taskWidth, taskHeight);
 
@@ -200,6 +206,48 @@
         return transformOut;
     }
 
+    /**
+     * Return the proper task index to focus for arrow key navigation.
+     * @param taskCount             The amount of tasks.
+     * @param currentFocusedIndex   The index of the currently focused task.
+     * @param direction             The direction we're navigating.
+     * @return  The index of the task that should get the focus.
+     */
+    public int navigateFocus(int taskCount, int currentFocusedIndex, Direction direction) {
+        if (taskCount < 1 || taskCount > MAX_LAYOUT_TASK_COUNT) {
+            return -1;
+        }
+        if (currentFocusedIndex == -1) {
+            return 0;
+        }
+        int newIndex = currentFocusedIndex;
+        final TaskGridRectInfo gridInfo = mTaskGridRectInfoList[taskCount - 1];
+        final int currentLine = (taskCount - 1 - currentFocusedIndex) / gridInfo.tasksPerLine;
+        switch (direction) {
+            case UP:
+                newIndex += gridInfo.tasksPerLine;
+                newIndex = newIndex >= taskCount ? currentFocusedIndex : newIndex;
+                break;
+            case DOWN:
+                newIndex -= gridInfo.tasksPerLine;
+                newIndex = newIndex < 0 ? currentFocusedIndex : newIndex;
+                break;
+            case LEFT:
+                newIndex++;
+                final int leftMostIndex = (taskCount - 1) - currentLine * gridInfo.tasksPerLine;
+                newIndex = newIndex > leftMostIndex ? currentFocusedIndex : newIndex;
+                break;
+            case RIGHT:
+                newIndex--;
+                int rightMostIndex =
+                    (taskCount - 1) - (currentLine + 1) * gridInfo.tasksPerLine + 1;
+                rightMostIndex = rightMostIndex < 0 ? 0 : rightMostIndex;
+                newIndex = newIndex < rightMostIndex ? currentFocusedIndex : newIndex;
+                break;
+        }
+        return newIndex;
+    }
+
     public void initialize(Rect windowRect) {
         mWindowRect = windowRect;
         // Define paddings in terms of percentage of the total area.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 68d5cd4..d77e9ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -159,6 +159,7 @@
     public void setNetworkController(NetworkControllerImpl nc) {
         if (DEBUG) Log.d(TAG, "NetworkController=" + nc);
         mNC = nc;
+        mNC.addCallback(this);
     }
 
     public void setSecurityController(SecurityController sc) {
@@ -214,7 +215,9 @@
         super.onAttachedToWindow();
 
         for (PhoneState state : mPhoneStates) {
-            mMobileSignalGroup.addView(state.mMobileGroup);
+            if (state.mMobileGroup.getParent() == null) {
+                mMobileSignalGroup.addView(state.mMobileGroup);
+            }
         }
 
         int endPadding = mMobileSignalGroup.getChildCount() > 0 ? mMobileSignalGroupEndPadding : 0;
@@ -224,7 +227,6 @@
 
         apply();
         applyIconTint();
-        mNC.addCallback(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index c0f245c..3423a3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -45,6 +45,7 @@
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.support.annotation.VisibleForTesting;
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -447,7 +448,8 @@
         return false;
     }
 
-    private boolean onHomeLongClick(View v) {
+    @VisibleForTesting
+    boolean onHomeLongClick(View v) {
         if (shouldDisableNavbarGestures()) {
             return false;
         }
@@ -562,6 +564,7 @@
 
     public void setAssistManager(AssistManager assistManager) {
         mAssistManager = assistManager;
+        mAssistManager.onConfigurationChanged();
     }
 
     public void setLightBarController(LightBarController lightBarController) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 191718e..001edb3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -74,6 +74,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.Process;
@@ -126,6 +127,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.classifier.FalsingLog;
@@ -847,6 +849,7 @@
                     mDozeServiceHost.firePowerSaveChanged(isPowerSave);
                 }
             }
+
             @Override
             public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
                 // noop
@@ -1029,8 +1032,10 @@
     }
 
     public static Handler getTimeTickHandler(Context context) {
-        return ((SystemUIApplication) context.getApplicationContext())
-                .getComponent(PhoneStatusBar.class).getTimeTickHandler();
+        PhoneStatusBar statusBar = ((SysUiServiceProvider) context.getApplicationContext())
+                .getComponent(PhoneStatusBar.class);
+        return statusBar != null ? statusBar.getTimeTickHandler() :
+                new Handler(Looper.getMainLooper());
     }
 
     protected void createNavigationBar() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 08a91bb..2fa961d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -21,9 +21,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
+import android.icu.text.NumberFormat;
 import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -32,21 +36,25 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.keyguard.KeyguardStatusView;
+import com.android.settingslib.Utils;
+import com.android.systemui.BatteryMeterView;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QS.ActivityStarter;
 import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
-import com.android.systemui.qs.QSPanel;
 import com.android.systemui.plugins.qs.QS.Callback;
+import com.android.systemui.qs.QSPanel;
 import com.android.systemui.qs.QuickQSPanel;
 import com.android.systemui.qs.TouchAnimator;
 import com.android.systemui.qs.TouchAnimator.Builder;
+import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
 import com.android.systemui.statusbar.policy.UserInfoController;
@@ -54,7 +62,8 @@
 import com.android.systemui.tuner.TunerService;
 
 public class QuickStatusBarHeader extends BaseStatusBarHeader implements
-        NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener {
+        NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener,
+        BatteryStateChangeCallback {
 
     private static final String TAG = "QuickStatusBarHeader";
 
@@ -67,14 +76,14 @@
 
     private TextView mAlarmStatus;
     private View mAlarmStatusCollapsed;
+    private ViewGroup mDateTimeGroup;
+    private ViewGroup mDateTimeAlarmGroup;
 
     private QSPanel mQsPanel;
 
     private boolean mExpanded;
     private boolean mAlarmShowing;
 
-    private ViewGroup mDateTimeGroup;
-    private ViewGroup mDateTimeAlarmGroup;
     private TextView mEmergencyOnly;
 
     protected ExpandableIndicator mExpandIndicator;
@@ -95,6 +104,7 @@
     protected View mEdit;
     private boolean mShowFullAlarm;
     private float mDateTimeTranslation;
+    private TextView mBatteryLevel;
 
     public QuickStatusBarHeader(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -130,6 +140,8 @@
         mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
         mAlarmStatus.setOnClickListener(this);
 
+        mBatteryLevel = (TextView) findViewById(R.id.battery_level);
+
         mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = (ImageView) mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
 
@@ -236,13 +248,11 @@
         mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
     }
 
-    @Override
     @VisibleForTesting
     public void onDetachedFromWindow() {
         setListening(false);
         mHost.getUserInfoController().removeCallback(this);
         mHost.getNetworkController().removeEmergencyListener(this);
-        mHost.getUserInfoController().removeCallback(this);
         super.onDetachedFromWindow();
     }
 
@@ -325,6 +335,19 @@
         if (isAPhone) {
             mHost.getNetworkController().addEmergencyListener(this);
         }
+
+        // Set the light/dark theming on the header status UI to match the current theme.
+        SignalClusterView cluster = (SignalClusterView) findViewById(R.id.signal_cluster);
+        cluster.setNetworkController((NetworkControllerImpl) host.getNetworkController());
+        cluster.setSecurityController(host.getSecurityController());
+        int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
+        float intensity = colorForeground / (float) Color.WHITE;
+        cluster.setIconTint(colorForeground, intensity,
+                new Rect(0, 0, 0, 0));
+        BatteryMeterView battery = (BatteryMeterView) findViewById(R.id.battery);
+        battery.setBatteryController(host.getBatteryController());
+        int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary);
+        battery.setRawColors(colorForeground, colorSecondary);
     }
 
     @Override
@@ -367,7 +390,7 @@
     }
 
     public void setBatteryController(BatteryController batteryController) {
-        // Don't care
+        batteryController.addCallback(this);
     }
 
     public void setUserInfoController(UserInfoController userInfoController) {
@@ -391,6 +414,17 @@
     }
 
     @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) {
+        // Don't care.
+    }
+
+    @Override
     public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
         mMultiUserAvatar.setImageDrawable(picture);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 2e279b2..7e5a7da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -491,7 +491,7 @@
     private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
         @Override
         public void run() {
-            mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
+            mPhoneStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE);
         }
     };
 
@@ -527,7 +527,7 @@
                     }
                 } else {
                     mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
-                    mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
+                    mPhoneStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE);
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index ed8c7ff..b59cf68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -224,7 +224,7 @@
     static final int ICON_CARRIER_NETWORK_CHANGE =
             R.drawable.stat_sys_signal_carrier_network_change_animation;
 
-    static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
+    static final int ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled;
 
     static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte;
     static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index dec8ba6..6516369 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -17,6 +17,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.systemui.tests">
 
+    <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
@@ -28,6 +29,7 @@
     <uses-permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE" />
     <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
     <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+    <uses-permission android:name="android.permission.ACCESS_VR_MANAGER" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 34743ff..e140e98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -16,12 +16,17 @@
 
 import static org.mockito.Mockito.mock;
 
+import android.content.Context;
+import android.view.WindowManager;
+
 import com.android.systemui.FragmentTestCase;
+import com.android.systemui.assist.AssistManager;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 
 import org.junit.Before;
+import org.junit.Test;
 
 public class NavigationBarFragmentTest extends FragmentTestCase {
 
@@ -37,4 +42,17 @@
         mContext.putComponent(Divider.class, mock(Divider.class));
     }
 
+    @Test
+    public void testHomeLongPress() {
+        mContext.addMockSystemService(Context.WINDOW_SERVICE, mock(WindowManager.class));
+        NavigationBarFragment navigationBarFragment = (NavigationBarFragment) mFragment;
+
+        AssistManager assistManager = new AssistManager(mContext.getComponent(PhoneStatusBar.class),
+                mContext);
+        navigationBarFragment.setAssistManager(assistManager);
+
+        postAndWait(() -> mFragments.dispatchResume());
+        navigationBarFragment.onHomeLongClick(navigationBarFragment.getView());
+    }
+
 }
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 62ea9e3..88bc99f 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3303,6 +3303,14 @@
     RESERVED_FOR_LOGBUILDER_TIMESTAMP = 805;
     RESERVED_FOR_LOGBUILDER_PACKAGENAME = 806;
 
+    // ACTION: "Force stop" action on an app
+    ACTION_APP_FORCE_STOP = 807;
+
+    // OPEN: Settings > Apps > Gear > Special Access > Install other apps
+    // CATEGORY: SETTINGS
+    // OS: 8.0
+    MANAGE_EXTERNAL_SOURCES = 808;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
new file mode 100644
index 0000000..c9d5c27
--- /dev/null
+++ b/proto/src/task_snapshot.proto
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ syntax = "proto3";
+
+ package com.android.server.wm;
+
+ option java_package = "com.android.server.wm";
+ option java_outer_classname = "WindowManagerProtos";
+
+ message TaskSnapshotProto {
+     int32 orientation = 1;
+     int32 inset_left = 2;
+     int32 inset_top = 3;
+     int32 inset_right = 4;
+     int32 inset_bottom = 5;
+ }
\ No newline at end of file
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 31ecb75..7e82586 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -577,15 +577,18 @@
         public ArrayList<String> fullPackages;
         public IBackupObserver observer;
         public boolean userInitiated;
+        public boolean nonIncrementalBackup;
 
         BackupParams(IBackupTransport transport, String dirName, ArrayList<String> kvPackages,
-                ArrayList<String> fullPackages, IBackupObserver observer, boolean userInitiated) {
+                ArrayList<String> fullPackages, IBackupObserver observer, boolean userInitiated,
+                boolean nonIncrementalBackup) {
             this.transport = transport;
             this.dirName = dirName;
             this.kvPackages = kvPackages;
             this.fullPackages = fullPackages;
             this.observer = observer;
             this.userInitiated = userInitiated;
+            this.nonIncrementalBackup = nonIncrementalBackup;
         }
     }
 
@@ -794,7 +797,7 @@
                     try {
                         String dirName = transport.transportDirName();
                         PerformBackupTask pbt = new PerformBackupTask(transport, dirName,
-                                queue, oldJournal, null, null, false);
+                                queue, oldJournal, null, null, false, false /* nonIncremental */);
                         Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
                         sendMessage(pbtMessage);
                     } catch (Exception e) {
@@ -1033,7 +1036,8 @@
                 mWakelock.acquire();
 
                 PerformBackupTask pbt = new PerformBackupTask(params.transport, params.dirName,
-                    kvQueue, null, params.observer, params.fullPackages, true);
+                        kvQueue, null, params.observer, params.fullPackages, true,
+                        params.nonIncrementalBackup);
                 Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
                 sendMessage(pbtMessage);
                 break;
@@ -2492,7 +2496,7 @@
         return token;
     }
 
-    public int requestBackup(String[] packages, IBackupObserver observer) {
+    public int requestBackup(String[] packages, IBackupObserver observer, int flags) {
         mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup");
 
         if (packages == null || packages.length < 1) {
@@ -2510,6 +2514,10 @@
         ArrayList<String> fullBackupList = new ArrayList<>();
         ArrayList<String> kvBackupList = new ArrayList<>();
         for (String packageName : packages) {
+            if (PACKAGE_MANAGER_SENTINEL.equals(packageName)) {
+                kvBackupList.add(packageName);
+                continue;
+            }
             try {
                 PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
                         PackageManager.GET_SIGNATURES);
@@ -2543,9 +2551,12 @@
             sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
             return BackupManager.ERROR_TRANSPORT_ABORTED;
         }
+
+        boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0;
+
         Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP);
         msg.obj = new BackupParams(transport, dirName, kvBackupList, fullBackupList, observer,
-                true);
+                true, nonIncrementalBackup);
         mBackupHandler.sendMessage(msg);
         return BackupManager.SUCCESS;
     }
@@ -2673,17 +2684,20 @@
         ParcelFileDescriptor mNewState;
         int mStatus;
         boolean mFinished;
-        boolean mUserInitiated;
+        final boolean mUserInitiated;
+        final boolean mNonIncremental;
 
         public PerformBackupTask(IBackupTransport transport, String dirName,
                 ArrayList<BackupRequest> queue, File journal, IBackupObserver observer,
-                ArrayList<String> pendingFullBackups, boolean userInitiated) {
+                ArrayList<String> pendingFullBackups, boolean userInitiated,
+                boolean nonIncremental) {
             mTransport = transport;
             mOriginalQueue = queue;
             mJournal = journal;
             mObserver = observer;
             mPendingFullBackups = pendingFullBackups;
             mUserInitiated = userInitiated;
+            mNonIncremental = nonIncremental;
 
             mStateDir = new File(mBaseStateDir, dirName);
 
@@ -2748,6 +2762,10 @@
             // the way.
             mQueue = (ArrayList<BackupRequest>) mOriginalQueue.clone();
 
+            // When the transport is forcing non-incremental key/value payloads, we send the
+            // metadata only if it explicitly asks for it.
+            boolean skipPm = mNonIncremental;
+
             // The app metadata pseudopackage might also be represented in the
             // backup queue if apps have been added/removed since the last time
             // we performed a backup.  Drop it from the working queue now that
@@ -2758,6 +2776,7 @@
                         Slog.i(TAG, "Metadata in queue; eliding");
                     }
                     mQueue.remove(i);
+                    skipPm = false;
                     break;
                 }
             }
@@ -2785,22 +2804,27 @@
                     }
                 }
 
-                // The package manager doesn't have a proper <application> etc, but since
-                // it's running here in the system process we can just set up its agent
-                // directly and use a synthetic BackupRequest.  We always run this pass
-                // because it's cheap and this way we guarantee that we don't get out of
-                // step even if we're selecting among various transports at run time.
-                if (mStatus == BackupTransport.TRANSPORT_OK) {
-                    PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
-                            mPackageManager);
-                    mStatus = invokeAgentForBackup(PACKAGE_MANAGER_SENTINEL,
-                            IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport);
-                    addBackupTrace("PMBA invoke: " + mStatus);
+                if (skipPm) {
+                    Slog.d(TAG, "Skipping backup of package metadata.");
+                    executeNextState(BackupState.RUNNING_QUEUE);
+                } else {
+                    // The package manager doesn't have a proper <application> etc, but since
+                    // it's running here in the system process we can just set up its agent
+                    // directly and use a synthetic BackupRequest.  We always run this pass
+                    // because it's cheap and this way we guarantee that we don't get out of
+                    // step even if we're selecting among various transports at run time.
+                    if (mStatus == BackupTransport.TRANSPORT_OK) {
+                        PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
+                                mPackageManager);
+                        mStatus = invokeAgentForBackup(PACKAGE_MANAGER_SENTINEL,
+                                IBackupAgent.Stub.asInterface(pmAgent.onBind()), mTransport);
+                        addBackupTrace("PMBA invoke: " + mStatus);
 
-                    // Because the PMBA is a local instance, it has already executed its
-                    // backup callback and returned.  Blow away the lingering (spurious)
-                    // pending timeout message for it.
-                    mBackupHandler.removeMessages(MSG_TIMEOUT);
+                        // Because the PMBA is a local instance, it has already executed its
+                        // backup callback and returned.  Blow away the lingering (spurious)
+                        // pending timeout message for it.
+                        mBackupHandler.removeMessages(MSG_TIMEOUT);
+                    }
                 }
 
                 if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
@@ -3066,6 +3090,7 @@
             if (DEBUG) Slog.d(TAG, "invokeAgentForBackup on " + packageName);
             addBackupTrace("invoking " + packageName);
 
+            File blankStateName = new File(mStateDir, "blank_state");
             mSavedStateName = new File(mStateDir, packageName);
             mBackupDataName = new File(mDataDir, packageName + ".data");
             mNewStateName = new File(mStateDir, packageName + ".new");
@@ -3088,9 +3113,10 @@
                 }
 
                 // In a full backup, we pass a null ParcelFileDescriptor as
-                // the saved-state "file". This is by definition an incremental,
-                // so we build a saved state file to pass.
-                mSavedState = ParcelFileDescriptor.open(mSavedStateName,
+                // the saved-state "file". For key/value backups we pass the old state if
+                // an incremental backup is required, and a blank state otherwise.
+                mSavedState = ParcelFileDescriptor.open(
+                        mNonIncremental ? blankStateName : mSavedStateName,
                         ParcelFileDescriptor.MODE_READ_ONLY |
                         ParcelFileDescriptor.MODE_CREATE);  // Make an empty file if necessary
 
@@ -3120,6 +3146,10 @@
                         e.toString());
                 agentErrorCleanup();
                 return BackupTransport.AGENT_ERROR;
+            } finally {
+                if (mNonIncremental) {
+                    blankStateName.delete();
+                }
             }
 
             // At this point the agent is off and running.  The next thing to happen will
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 312b878..d677f5e 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -338,9 +338,10 @@
     }
 
     @Override
-    public int requestBackup(String[] packages, IBackupObserver observer) throws RemoteException {
+    public int requestBackup(String[] packages, IBackupObserver observer, int flags)
+            throws RemoteException {
         BackupManagerService svc = mService;
-        return (svc != null) ? svc.requestBackup(packages, observer) : null;
+        return (svc != null) ? svc.requestBackup(packages, observer, flags) : null;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 570843e..1f62945 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -881,11 +881,9 @@
             }
             code = AppOpsManager.opToSwitch(code);
             UidState uidState = getUidStateLocked(uid, false);
-            if (uidState != null && uidState.opModes != null) {
-                final int uidMode = uidState.opModes.get(code);
-                if (uidMode != AppOpsManager.MODE_ALLOWED) {
-                    return uidMode;
-                }
+            if (uidState != null && uidState.opModes != null
+                    && uidState.opModes.indexOfKey(code) >= 0) {
+                return uidState.opModes.get(code);
             }
             Op op = getOpLocked(code, uid, resolvedPackageName, false);
             if (op == null) {
@@ -2126,6 +2124,7 @@
                 UidState uidState = mUidStates.valueAt(i);
 
                 pw.print("  Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
+                needSep = true;
 
                 SparseIntArray opModes = uidState.opModes;
                 if (opModes != null) {
@@ -2166,6 +2165,55 @@
                     }
                 }
             }
+            if (needSep) {
+                pw.println();
+            }
+
+            final int userRestrictionCount = mOpUserRestrictions.size();
+            for (int i = 0; i < userRestrictionCount; i++) {
+                IBinder token = mOpUserRestrictions.keyAt(i);
+                ClientRestrictionState restrictionState = mOpUserRestrictions.valueAt(i);
+                pw.println("  User restrictions for token " + token + ":");
+
+                final int restrictionCount = restrictionState.perUserRestrictions != null
+                        ? restrictionState.perUserRestrictions.size() : 0;
+                if (restrictionCount > 0) {
+                    pw.println("      Restricted ops:");
+                    for (int j = 0; j < restrictionCount; j++) {
+                        int userId = restrictionState.perUserRestrictions.keyAt(j);
+                        boolean[] restrictedOps = restrictionState.perUserRestrictions.valueAt(j);
+                        if (restrictedOps == null) {
+                            continue;
+                        }
+                        StringBuilder restrictedOpsValue = new StringBuilder();
+                        restrictedOpsValue.append("[");
+                        final int restrictedOpCount = restrictedOps.length;
+                        for (int k = 0; k < restrictedOpCount; k++) {
+                            if (restrictedOps[k]) {
+                                if (restrictedOpsValue.length() > 1) {
+                                    restrictedOpsValue.append(", ");
+                                }
+                                restrictedOpsValue.append(AppOpsManager.opToName(k));
+                            }
+                        }
+                        restrictedOpsValue.append("]");
+                        pw.print("        "); pw.print("user: "); pw.print(userId);
+                                pw.print(" restricted ops: "); pw.println(restrictedOpsValue);
+                    }
+                }
+
+                final int excludedPackageCount = restrictionState.perUserExcludedPackages != null
+                        ? restrictionState.perUserExcludedPackages.size() : 0;
+                if (excludedPackageCount > 0) {
+                    pw.println("      Excluded packages:");
+                    for (int j = 0; j < excludedPackageCount; j++) {
+                        int userId = restrictionState.perUserExcludedPackages.keyAt(j);
+                        String[] packageNames = restrictionState.perUserExcludedPackages.valueAt(j);
+                        pw.print("        "); pw.print("user: "); pw.print(userId);
+                                pw.print(" packages: "); pw.println(Arrays.toString(packageNames));
+                    }
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 9f63e30..97edb15 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -114,6 +115,7 @@
 
     private AlarmManager mAlarmManager;
     private IBatteryStats mBatteryStats;
+    private ActivityManagerInternal mLocalActivityManager;
     private PowerManagerInternal mLocalPowerManager;
     private PowerManager mPowerManager;
     private ConnectivityService mConnectivityService;
@@ -1272,6 +1274,11 @@
             DeviceIdleController.this.setAlarmsActive(active);
         }
 
+        /** Is the app on any of the power save whitelists, whether system or user? */
+        public boolean isAppOnWhitelist(int appid) {
+            return DeviceIdleController.this.isAppOnWhitelistInternal(appid);
+        }
+
         /**
          * Returns the array of app ids whitelisted by user. Take care not to
          * modify this, as it is a reference to the original copy. But the reference
@@ -1289,6 +1296,12 @@
         mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
     }
 
+    boolean isAppOnWhitelistInternal(int appid) {
+        synchronized (this) {
+            return Arrays.binarySearch(mPowerSaveWhitelistAllAppIdArray, appid) >= 0;
+        }
+    }
+
     int[] getPowerSaveWhitelistUserAppIds() {
         synchronized (this) {
             return mPowerSaveWhitelistUserAppIdArray;
@@ -1362,6 +1375,7 @@
             synchronized (this) {
                 mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
                 mBatteryStats = BatteryStatsService.getService();
+                mLocalActivityManager = getLocalService(ActivityManagerInternal.class);
                 mLocalPowerManager = getLocalService(PowerManagerInternal.class);
                 mPowerManager = getContext().getSystemService(PowerManager.class);
                 mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
@@ -1431,6 +1445,7 @@
                 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
                 getContext().registerReceiver(mReceiver, filter);
 
+                mLocalActivityManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
                 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
                 mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
                 mDisplayManager.registerDisplayListener(mDisplayListener, null);
@@ -1652,7 +1667,7 @@
                 } catch (RemoteException e) {
                 }
                 postTempActiveTimeoutMessage(appId, duration);
-                updateTempWhitelistAppIdsLocked();
+                updateTempWhitelistAppIdsLocked(appId, true);
                 if (mNetworkPolicyTempWhitelistCallback != null) {
                     if (!sync) {
                         mHandler.post(mNetworkPolicyTempWhitelistCallback);
@@ -1698,7 +1713,7 @@
                 if (DEBUG) {
                     Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
                 }
-                updateTempWhitelistAppIdsLocked();
+                updateTempWhitelistAppIdsLocked(uid, false);
                 if (mNetworkPolicyTempWhitelistCallback != null) {
                     mHandler.post(mNetworkPolicyTempWhitelistCallback);
                 }
@@ -2318,6 +2333,13 @@
                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
         mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
                 mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
+        if (mLocalActivityManager != null) {
+            if (DEBUG) {
+                Slog.d(TAG, "Setting activity manager whitelist to "
+                        + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
+            }
+            mLocalActivityManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
+        }
         if (mLocalPowerManager != null) {
             if (DEBUG) {
                 Slog.d(TAG, "Setting wakelock whitelist to "
@@ -2334,7 +2356,7 @@
         }
     }
 
-    private void updateTempWhitelistAppIdsLocked() {
+    private void updateTempWhitelistAppIdsLocked(int appId, boolean adding) {
         final int size = mTempWhitelistAppIdEndTimes.size();
         if (mTempWhitelistAppIdArray.length != size) {
             mTempWhitelistAppIdArray = new int[size];
@@ -2342,6 +2364,14 @@
         for (int i = 0; i < size; i++) {
             mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
         }
+        if (mLocalActivityManager != null) {
+            if (DEBUG) {
+                Slog.d(TAG, "Setting activity manager temp whitelist to "
+                        + Arrays.toString(mTempWhitelistAppIdArray));
+            }
+            mLocalActivityManager.updateDeviceIdleTempWhitelist(mTempWhitelistAppIdArray, appId,
+                    adding);
+        }
         if (mLocalPowerManager != null) {
             if (DEBUG) {
                 Slog.d(TAG, "Setting wakelock temp whitelist to "
@@ -2512,8 +2542,9 @@
         pw.println("    Add (prefix with +) or remove (prefix with -) packages.");
         pw.println("  tempwhitelist");
         pw.println("    Print packages that are temporarily whitelisted.");
-        pw.println("  tempwhitelist [-u] [package ..]");
-        pw.println("    Temporarily place packages in whitelist for 10 seconds.");
+        pw.println("  tempwhitelist [-u USER] [-d DURATION] [package ..]");
+        pw.println("    Temporarily place packages in whitelist for DURATION milliseconds.");
+        pw.println("    If no DURATION is specified, 10 seconds is used");
     }
 
     class Shell extends ShellCommand {
@@ -2796,6 +2827,7 @@
                 }
             }
         } else if ("tempwhitelist".equals(cmd)) {
+            long duration = 10000;
             String opt;
             while ((opt=shell.getNextOption()) != null) {
                 if ("-u".equals(opt)) {
@@ -2805,12 +2837,19 @@
                         return -1;
                     }
                     shell.userId = Integer.parseInt(opt);
+                } else if ("-d".equals(opt)) {
+                    opt = shell.getNextArg();
+                    if (opt == null) {
+                        pw.println("-d requires a duration");
+                        return -1;
+                    }
+                    duration = Long.parseLong(opt);
                 }
             }
             String arg = shell.getNextArg();
             if (arg != null) {
                 try {
-                    addPowerSaveTempWhitelistAppChecked(arg, 10000L, shell.userId, "shell");
+                    addPowerSaveTempWhitelistAppChecked(arg, duration, shell.userId, "shell");
                 } catch (RemoteException re) {
                     pw.println("Failed: " + re);
                 }
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 962ac6f..1bdff6b 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -22,13 +22,20 @@
 import android.os.StatFs;
 import android.os.SystemClock;
 import android.os.storage.StorageManager;
+import android.service.diskstats.DiskStatsAppSizesProto;
+import android.service.diskstats.DiskStatsCachedValuesProto;
+import android.service.diskstats.DiskStatsFreeSpaceProto;
+import android.service.diskstats.DiskStatsServiceDumpProto;
 import android.util.Log;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
 
 import libcore.io.IoUtils;
 
+import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
@@ -78,30 +85,68 @@
         long after = SystemClock.uptimeMillis();
         if (tmp.exists()) tmp.delete();
 
-        if (error != null) {
-            pw.print("Test-Error: ");
-            pw.println(error.toString());
+        boolean protoFormat = hasOption(args, "--proto");
+        ProtoOutputStream proto = null;
+
+        if (protoFormat) {
+            proto = new ProtoOutputStream(fd);
+            pw = null;
+            proto.write(DiskStatsServiceDumpProto.HAS_TEST_ERROR, error != null);
+            if (error != null) {
+                proto.write(DiskStatsServiceDumpProto.ERROR_MESSAGE, error.toString());
+            } else {
+                proto.write(DiskStatsServiceDumpProto.WRITE_512B_LATENCY_MILLIS, after - before);
+            }
         } else {
-            pw.print("Latency: ");
-            pw.print(after - before);
-            pw.println("ms [512B Data Write]");
+            if (error != null) {
+                pw.print("Test-Error: ");
+                pw.println(error.toString());
+            } else {
+                pw.print("Latency: ");
+                pw.print(after - before);
+                pw.println("ms [512B Data Write]");
+            }
         }
 
-        reportFreeSpace(Environment.getDataDirectory(), "Data", pw);
-        reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw);
-        reportFreeSpace(new File("/system"), "System", pw);
+        reportFreeSpace(Environment.getDataDirectory(), "Data", pw, proto,
+                DiskStatsFreeSpaceProto.FOLDER_DATA);
+        reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw, proto,
+                DiskStatsFreeSpaceProto.FOLDER_CACHE);
+        reportFreeSpace(new File("/system"), "System", pw, proto,
+                DiskStatsFreeSpaceProto.FOLDER_SYSTEM);
 
-        if (StorageManager.isFileEncryptedNativeOnly()) {
+        boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
+        boolean blockBased = fileBased ? false : StorageManager.isBlockEncrypted();
+        if (protoFormat) {
+            if (fileBased) {
+                proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
+                        DiskStatsServiceDumpProto.ENCRYPTION_FILE_BASED);
+            } else if (blockBased) {
+                proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
+                        DiskStatsServiceDumpProto.ENCRYPTION_FULL_DISK);
+            } else {
+                proto.write(DiskStatsServiceDumpProto.ENCRYPTION,
+                        DiskStatsServiceDumpProto.ENCRYPTION_NONE);
+            }
+        } else if (fileBased) {
             pw.println("File-based Encryption: true");
         }
 
-        reportCachedValues(pw);
+        if (protoFormat) {
+            reportCachedValuesProto(proto);
+        } else {
+            reportCachedValues(pw);
+        }
 
+        if (protoFormat) {
+            proto.flush();
+        }
         // TODO: Read /proc/yaffs and report interesting values;
         // add configurable (through args) performance test parameters.
     }
 
-    private void reportFreeSpace(File path, String name, PrintWriter pw) {
+    private void reportFreeSpace(File path, String name, PrintWriter pw,
+            ProtoOutputStream proto, int folderType) {
         try {
             StatFs statfs = new StatFs(path.getPath());
             long bsize = statfs.getBlockSize();
@@ -112,22 +157,44 @@
                         "Invalid stat: bsize=" + bsize + " avail=" + avail + " total=" + total);
             }
 
-            pw.print(name);
-            pw.print("-Free: ");
-            pw.print(avail * bsize / 1024);
-            pw.print("K / ");
-            pw.print(total * bsize / 1024);
-            pw.print("K total = ");
-            pw.print(avail * 100 / total);
-            pw.println("% free");
+            if (proto != null) {
+                long freeSpaceToken = proto.start(DiskStatsServiceDumpProto.PARTITIONS_FREE_SPACE);
+                proto.write(DiskStatsFreeSpaceProto.FOLDER, folderType);
+                proto.write(DiskStatsFreeSpaceProto.AVAILABLE_SPACE, avail * bsize / 1024);
+                proto.write(DiskStatsFreeSpaceProto.TOTAL_SPACE, total * bsize / 1024);
+                proto.end(freeSpaceToken);
+            } else {
+                pw.print(name);
+                pw.print("-Free: ");
+                pw.print(avail * bsize / 1024);
+                pw.print("K / ");
+                pw.print(total * bsize / 1024);
+                pw.print("K total = ");
+                pw.print(avail * 100 / total);
+                pw.println("% free");
+            }
         } catch (IllegalArgumentException e) {
-            pw.print(name);
-            pw.print("-Error: ");
-            pw.println(e.toString());
+            if (proto != null) {
+                // Empty proto
+            } else {
+                pw.print(name);
+                pw.print("-Error: ");
+                pw.println(e.toString());
+            }
             return;
         }
     }
 
+    private boolean hasOption(String[] args, String arg) {
+        for (String opt : args) {
+            if (arg.equals(opt)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // If you change this method, make sure to modify the Proto version of this method as well.
     private void reportCachedValues(PrintWriter pw) {
         try {
             String jsonString = IoUtils.readFileAsString(DISKSTATS_DUMP_FILE);
@@ -159,4 +226,52 @@
         }
     }
 
+    private void reportCachedValuesProto(ProtoOutputStream proto) {
+        try {
+            String jsonString = IoUtils.readFileAsString(DISKSTATS_DUMP_FILE);
+            JSONObject json = new JSONObject(jsonString);
+            long cachedValuesToken = proto.start(DiskStatsServiceDumpProto.CACHED_FOLDER_SIZES);
+
+            proto.write(DiskStatsCachedValuesProto.AGG_APPS_SIZE,
+                    json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY));
+            proto.write(DiskStatsCachedValuesProto.AGG_APPS_CACHE_SIZE,
+                    json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY));
+            proto.write(DiskStatsCachedValuesProto.PHOTOS_SIZE,
+                    json.getLong(DiskStatsFileLogger.PHOTOS_KEY));
+            proto.write(DiskStatsCachedValuesProto.VIDEOS_SIZE,
+                    json.getLong(DiskStatsFileLogger.VIDEOS_KEY));
+            proto.write(DiskStatsCachedValuesProto.AUDIO_SIZE,
+                    json.getLong(DiskStatsFileLogger.AUDIO_KEY));
+            proto.write(DiskStatsCachedValuesProto.DOWNLOADS_SIZE,
+                    json.getLong(DiskStatsFileLogger.DOWNLOADS_KEY));
+            proto.write(DiskStatsCachedValuesProto.SYSTEM_SIZE,
+                    json.getLong(DiskStatsFileLogger.SYSTEM_KEY));
+            proto.write(DiskStatsCachedValuesProto.OTHER_SIZE,
+                    json.getLong(DiskStatsFileLogger.MISC_KEY));
+
+            JSONArray packageNamesArray = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY);
+            JSONArray appSizesArray = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY);
+            JSONArray cacheSizesArray = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY);
+            final int len = packageNamesArray.length();
+            if (len == appSizesArray.length() && len == cacheSizesArray.length()) {
+                for (int i = 0; i < len; i++) {
+                    long packageToken = proto.start(DiskStatsCachedValuesProto.APP_SIZES);
+
+                    proto.write(DiskStatsAppSizesProto.PACKAGE_NAME,
+                            packageNamesArray.getString(i));
+                    proto.write(DiskStatsAppSizesProto.APP_SIZE, appSizesArray.getLong(i));
+                    proto.write(DiskStatsAppSizesProto.CACHE_SIZE, cacheSizesArray.getLong(i));
+
+                    proto.end(packageToken);
+                }
+            } else {
+                Slog.wtf(TAG, "Sizes of packageNamesArray, appSizesArray and cacheSizesArray "
+                        + "are not the same");
+            }
+
+            proto.end(cachedValuesToken);
+        } catch (IOException | JSONException e) {
+            Log.w(TAG, "exception reading diskstats cache file", e);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 62f4f19..0834eb8 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1360,6 +1360,7 @@
         }
 
         Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         Bundle data = new Bundle();
         state.fillInNotifierBundle(data);
         intent.putExtras(data);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 11e1a9d..0a6c62f 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -505,7 +505,9 @@
      * @param ua UserAccount that currently hosts the account and application
      */
     private void registerAccountTypesSupported(int uid, UserAccounts ua) {
-        /* Account types supported are drawn from the Android Manifest of the Application */
+        return;
+        // TODO clean up the code, manifest entry is deprecated
+        /*
         String interestedPackages = null;
         try {
             String[] allPackages = mPackageManager.getPackagesForUid(uid);
@@ -527,6 +529,7 @@
             // TODO request visibility
             // requestAccountVisibility(interestedPackages.split(";"), uid, ua);
         }
+        */
     }
 
     /**
@@ -536,6 +539,8 @@
      * @param visibleAccount to send to package
      */
     private void sendNotification(String desiredPackage, Account visibleAccount) {
+        // TODO replace with callback
+        /*
         Intent intent = new Intent();
         intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
         intent.setAction(AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED);
@@ -543,6 +548,7 @@
         // TODO update documentation, add account extra if new account became visible
         // intent.putExtra("android.accounts.KEY_ACCOUNT", (Account) visibleAccount);
         mContext.sendBroadcast(intent);
+        */
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7661127..4b89b40 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -305,6 +305,7 @@
     }
 
     ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
+            int id, Notification notification,
             int callingPid, int callingUid, String callingPackage, final int userId)
             throws TransactionTooLargeException {
         if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
@@ -324,7 +325,6 @@
             callerFg = true;
         }
 
-
         ServiceLookupResult res =
             retrieveServiceLocked(service, resolvedType, callingPackage,
                     callingPid, callingUid, userId, true, callerFg, false);
@@ -343,10 +343,11 @@
             return null;
         }
 
-        if (!r.startRequested) {
+        // Non-null notification means this is a start directly into the foreground
+        if (!r.startRequested && notification == null) {
             final long token = Binder.clearCallingIdentity();
             try {
-                // Before going further -- if this app is not allowed to run in the
+                // Before going further -- if this app is not allowed to start services in the
                 // background, then at this point we aren't going to let it period.
                 final int allowed = mAm.checkAllowBackgroundLocked(
                         r.appInfo.uid, r.packageName, callingPid, false);
@@ -355,7 +356,14 @@
                             + service + " to " + r.name.flattenToShortString()
                             + " from pid=" + callingPid + " uid=" + callingUid
                             + " pkg=" + callingPackage);
-                    return null;
+                    if (allowed == ActivityManager.APP_START_MODE_DELAYED) {
+                        // In this case we are silently disabling the app, to disrupt as
+                        // little as possible existing apps.
+                        return null;
+                    }
+                    // This app knows it is in the new model where this operation is not
+                    // allowed, so tell it what has happened.
+                    return new ComponentName("?", "app is in background");
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -450,7 +458,11 @@
             }
         }
 
-        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
+        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
+        if (notification != null) {
+            setServiceForegroundInnerLocked(r, callingUid, notification, 0);
+        }
+        return cmp;
     }
 
     private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r,
@@ -595,9 +607,8 @@
             for (int i=services.mServicesByName.size()-1; i>=0; i--) {
                 ServiceRecord service = services.mServicesByName.valueAt(i);
                 if (service.appInfo.uid == uid && service.startRequested) {
-                    if (service.appInfo.isEphemeralApp() ||
-                            mAm.mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
-                            uid, service.packageName) != AppOpsManager.MODE_ALLOWED) {
+                    if (mAm.checkAllowBackgroundLocked(service.appInfo.uid, service.packageName,
+                            -1, false) != ActivityManager.APP_START_MODE_NORMAL) {
                         if (stopping == null) {
                             stopping = new ArrayList<>();
                             stopping.add(service);
@@ -696,50 +707,55 @@
         try {
             ServiceRecord r = findServiceLocked(className, token, userId);
             if (r != null) {
-                if (id != 0) {
-                    if (notification == null) {
-                        throw new IllegalArgumentException("null notification");
-                    }
-                    if (r.foregroundId != id) {
-                        cancelForegroudNotificationLocked(r);
-                        r.foregroundId = id;
-                    }
-                    notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-                    r.foregroundNoti = notification;
-                    r.isForeground = true;
-                    r.postNotification();
-                    if (r.app != null) {
-                        updateServiceForegroundLocked(r.app, true);
-                    }
-                    getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r);
-                    mAm.notifyPackageUse(r.serviceInfo.packageName,
-                                         PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
-                } else {
-                    if (r.isForeground) {
-                        r.isForeground = false;
-                        if (r.app != null) {
-                            mAm.updateLruProcessLocked(r.app, false, null);
-                            updateServiceForegroundLocked(r.app, true);
-                        }
-                    }
-                    if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
-                        cancelForegroudNotificationLocked(r);
-                        r.foregroundId = 0;
-                        r.foregroundNoti = null;
-                    } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
-                        r.stripForegroundServiceFlagFromNotification();
-                        if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) {
-                            r.foregroundId = 0;
-                            r.foregroundNoti = null;
-                        }
-                    }
-                }
+                setServiceForegroundInnerLocked(r, userId, notification, flags);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
     }
 
+    private void setServiceForegroundInnerLocked(ServiceRecord r, int id,
+            Notification notification, int flags) {
+        if (id != 0) {
+            if (notification == null) {
+                throw new IllegalArgumentException("null notification");
+            }
+            if (r.foregroundId != id) {
+                cancelForegroudNotificationLocked(r);
+                r.foregroundId = id;
+            }
+            notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
+            r.foregroundNoti = notification;
+            r.isForeground = true;
+            r.postNotification();
+            if (r.app != null) {
+                updateServiceForegroundLocked(r.app, true);
+            }
+            getServiceMapLocked(r.userId).ensureNotStartingBackgroundLocked(r);
+            mAm.notifyPackageUse(r.serviceInfo.packageName,
+                                 PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE);
+        } else {
+            if (r.isForeground) {
+                r.isForeground = false;
+                if (r.app != null) {
+                    mAm.updateLruProcessLocked(r.app, false, null);
+                    updateServiceForegroundLocked(r.app, true);
+                }
+            }
+            if ((flags & Service.STOP_FOREGROUND_REMOVE) != 0) {
+                cancelForegroudNotificationLocked(r);
+                r.foregroundId = 0;
+                r.foregroundNoti = null;
+            } else if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
+                r.stripForegroundServiceFlagFromNotification();
+                if ((flags & Service.STOP_FOREGROUND_DETACH) != 0) {
+                    r.foregroundId = 0;
+                    r.foregroundNoti = null;
+                }
+            }
+        }
+    }
+
     private void cancelForegroudNotificationLocked(ServiceRecord r) {
         if (r.foregroundId != 0) {
             // First check to see if this app has any other active foreground services
@@ -1444,6 +1460,8 @@
             // If service is not currently running, can't yet bind.
             return false;
         }
+        if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
+                + " rebind=" + rebind);
         if ((!i.requested || rebind) && i.apps.size() > 0) {
             try {
                 bumpServiceExecutingLocked(r, execInFg, "bind");
@@ -1907,6 +1925,7 @@
                     mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
                             si.getUriPermissionsLocked());
                 }
+                // TODO b/34123112; Insert ephemeral grant here
                 bumpServiceExecutingLocked(r, execInFg, "start");
                 if (!oomAdjusted) {
                     oomAdjusted = true;
@@ -2014,6 +2033,7 @@
                         bumpServiceExecutingLocked(r, false, "bring down unbind");
                         mAm.updateOomAdjLocked(r.app);
                         ibr.hasBound = false;
+                        ibr.requested = false;
                         r.app.thread.scheduleUnbindService(r,
                                 ibr.intent.getIntent());
                     } catch (Exception e) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 43bb5ee..88e0d03 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -48,6 +48,7 @@
     static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false;
     static final boolean DEBUG_ANR = false;
     static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false;
+    static final boolean DEBUG_BACKGROUND_CHECK = DEBUG_ALL || false;
     static final boolean DEBUG_BACKUP = DEBUG_ALL || false;
     static final boolean DEBUG_BROADCAST = DEBUG_ALL || false;
     static final boolean DEBUG_BROADCAST_BACKGROUND = DEBUG_BROADCAST || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7fd91cb..d765bd6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -62,6 +62,7 @@
 import static com.android.internal.util.XmlUtils.writeLongAttribute;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_BACKGROUND;
@@ -119,6 +120,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.FORCE_NEW_TASK_FLAGS;
+import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
 import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
 import static com.android.server.am.ActivityStackSupervisor.FORCE_FOCUS;
 import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
@@ -310,7 +312,6 @@
 
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
-
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.AssistUtils;
@@ -341,6 +342,7 @@
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
 import com.android.server.ServiceThread;
+import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
 import com.android.server.Watchdog;
@@ -384,10 +386,10 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import dalvik.system.VMRuntime;
+
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
 
-import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
 public class ActivityManagerService extends IActivityManager.Stub
         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
 
@@ -758,6 +760,23 @@
     ProcessRecord mHeavyWeightProcess = null;
 
     /**
+     * Are we enforcing background restrictions?
+     */
+    final boolean mEnforceBackgroundCheck;
+
+    /**
+     * Non-persistent app uid whitelist for background restrictions
+     */
+    int[] mBackgroundUidWhitelist = new int[] {
+            Process.BLUETOOTH_UID
+    };
+
+    /**
+     * Broadcast actions that will always be deliverable to unlaunched/background apps
+     */
+    final ArraySet<String> mBackgroundLaunchBroadcasts;
+
+    /**
      * All of the processes we currently have running organized by pid.
      * The keys are the pid running the application.
      *
@@ -1135,6 +1154,16 @@
     DeviceIdleController.LocalService mLocalDeviceIdleController;
 
     /**
+     * Set of app ids that are whitelisted for device idle and thus background check.
+     */
+    int[] mDeviceIdleWhitelist = new int[0];
+
+    /**
+     * Set of app ids that are temporarily allowed to escape bg check due to high-pri message
+     */
+    int[] mDeviceIdleTempWhitelist = new int[0];
+
+    /**
      * Information about and control over application operations
      */
     final AppOpsService mAppOpsService;
@@ -2590,6 +2619,19 @@
         mPermissionReviewRequired = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_permissionReviewRequired);
 
+        mEnforceBackgroundCheck = SystemProperties.getBoolean("debug.bgcheck", false);
+        mBackgroundLaunchBroadcasts = SystemConfig.getInstance().getAllowImplicitBroadcasts();
+        if (DEBUG_BACKGROUND_CHECK) {
+            Slog.d(TAG, "Enforcing O+ bg restrictions: " + mEnforceBackgroundCheck);
+            StringBuilder sb = new StringBuilder(200);
+            sb.append("  ");
+            for (String a : mBackgroundLaunchBroadcasts) {
+                sb.append(' '); sb.append(a);
+            }
+            Slog.d(TAG, "Background implicit broadcasts:");
+            Slog.d(TAG, sb.toString());
+        }
+
         mHandlerThread = new ServiceThread(TAG,
                 android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
         mHandlerThread.start();
@@ -4190,7 +4232,7 @@
                             validateUid = mValidateUids.get(item.uid);
                             if (validateUid == null && change != UidRecord.CHANGE_GONE
                                     && change != UidRecord.CHANGE_GONE_IDLE) {
-                                validateUid = new UidRecord(item.uid);
+                                validateUid = new UidRecord(item.uid, false);
                                 mValidateUids.put(item.uid, validateUid);
                             }
                         }
@@ -5504,6 +5546,7 @@
 
                     final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
                             Uri.fromParts("package", packageName, null));
+                    intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                     intent.putExtra(Intent.EXTRA_UID, pkgUidF);
                     intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUidF));
                     broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
@@ -5524,11 +5567,9 @@
                     removeUriPermissionsForPackageLocked(packageName, userId, true);
                 }
 
-                // Remove all zen rules created by this package; revoke it's zen access.
+                // Reset notification settings.
                 INotificationManager inm = NotificationManager.getService();
-                inm.removeAutomaticZenRules(packageName);
-                inm.setNotificationPolicyAccessGranted(packageName, false);
-
+                inm.clearData(packageName, pkgUidF);
             } catch (RemoteException e) {
             }
         } finally {
@@ -6279,10 +6320,13 @@
         }
         UidRecord uidRec = mActiveUids.get(proc.uid);
         if (uidRec == null) {
-            uidRec = new UidRecord(proc.uid);
+            uidRec = new UidRecord(proc.uid, proc.persistent);
             // This is the first appearance of the uid, report it now!
             if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                     "Creating new process uid: " + uidRec);
+            if (Arrays.binarySearch(mDeviceIdleTempWhitelist, UserHandle.getAppId(proc.uid)) >= 0) {
+                uidRec.setWhitelist = uidRec.curWhitelist = true;
+            }
             mActiveUids.put(proc.uid, uidRec);
             noteUidProcessState(uidRec.uid, uidRec.curProcState);
             enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE);
@@ -8026,9 +8070,97 @@
         }
     }
 
+    // Unified app-op and target sdk check
+    int appRestrictedInBackgroundLocked(int uid, String packageName) {
+        if (packageName == null) {
+            packageName = mPackageManagerInt.getNameForUid(uid);
+            if (packageName == null) {
+                Slog.w(TAG, "No package known for uid " + uid);
+                return ActivityManager.APP_START_MODE_NORMAL;
+            }
+        }
+
+        // !!! TODO: cache the package/versionCode lookups to fast path this
+        ApplicationInfo app = getPackageManagerInternalLocked().getApplicationInfo(packageName,
+                UserHandle.getUserId(uid));
+        if (app != null) {
+            // Apps that target O+ are always subject to background check
+            if (mEnforceBackgroundCheck && app.targetSdkVersion >= Build.VERSION_CODES.O) {
+                if (DEBUG_BACKGROUND_CHECK) {
+                    Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
+                }
+                return ActivityManager.APP_START_MODE_DELAYED_RIGID;
+            }
+            // ...and legacy apps get an AppOp check
+            int appop = mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND,
+                    uid, packageName);
+            if (DEBUG_BACKGROUND_CHECK) {
+                Slog.i(TAG, "Legacy app " + uid + "/" + packageName + " bg appop " + appop);
+            }
+            switch (appop) {
+                case AppOpsManager.MODE_ALLOWED:
+                    return ActivityManager.APP_START_MODE_NORMAL;
+                case AppOpsManager.MODE_IGNORED:
+                    return ActivityManager.APP_START_MODE_DELAYED;
+                default:
+                    return ActivityManager.APP_START_MODE_DELAYED_RIGID;
+            }
+        } else {
+            Slog.w(TAG, "Unknown app " + packageName + " / " + uid);
+        }
+        return ActivityManager.APP_START_MODE_NORMAL;
+    }
+
+    // Service launch is available to apps with run-in-background exemptions but
+    // some other background operations are not.  If we're doing a check
+    // of service-launch policy, allow those callers to proceed unrestricted.
+    int appServicesRestrictedInBackgroundLocked(int uid, String packageName) {
+        if (packageName == null) {
+            packageName = mPackageManagerInt.getNameForUid(uid);
+            if (packageName == null) {
+                Slog.w(TAG, "No package known for uid " + uid);
+                return ActivityManager.APP_START_MODE_NORMAL;
+            }
+        }
+
+        // Persistent app?  NB: expects that persistent uids are always active.
+        final UidRecord uidRec = mActiveUids.get(uid);
+        if (uidRec != null && uidRec.persistent) {
+            if (DEBUG_BACKGROUND_CHECK) {
+                Slog.i(TAG, "App " + uid + "/" + packageName
+                        + " is persistent; not restricted in background");
+            }
+            return ActivityManager.APP_START_MODE_NORMAL;
+        }
+
+        // Non-persistent but background whitelisted?
+        if (uidOnBackgroundWhitelist(uid)) {
+            if (DEBUG_BACKGROUND_CHECK) {
+                Slog.i(TAG, "App " + uid + "/" + packageName
+                        + " on background whitelist; not restricted in background");
+            }
+            return ActivityManager.APP_START_MODE_NORMAL;
+        }
+
+        // Is this app on the battery whitelist?
+        if (isOnDeviceIdleWhitelistLocked(uid)) {
+            if (DEBUG_BACKGROUND_CHECK) {
+                Slog.i(TAG, "App " + uid + "/" + packageName
+                        + " on idle whitelist; not restricted in background");
+            }
+            return ActivityManager.APP_START_MODE_NORMAL;
+        }
+
+        // None of the service-policy criteria apply, so we apply the common criteria
+        return appRestrictedInBackgroundLocked(uid, packageName);
+    }
+
     int checkAllowBackgroundLocked(int uid, String packageName, int callingPid,
             boolean alwaysRestrict) {
         UidRecord uidRec = mActiveUids.get(uid);
+        if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid + " pkg="
+                + packageName + " rec=" + uidRec + " always=" + alwaysRestrict + " idle="
+                + (uidRec != null ? uidRec.idle : false));
         if (uidRec == null || alwaysRestrict || uidRec.idle) {
             boolean ephemeral;
             if (uidRec == null) {
@@ -8042,6 +8174,7 @@
                 // We are hard-core about ephemeral apps not running in the background.
                 return ActivityManager.APP_START_MODE_DISABLED;
             } else {
+                /** Don't want to allow this exception in the final background check impl?
                 if (callingPid >= 0) {
                     ProcessRecord proc;
                     synchronized (mPidsSelfLocked) {
@@ -8054,15 +8187,26 @@
                         return ActivityManager.APP_START_MODE_NORMAL;
                     }
                 }
-                if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid,
-                        packageName) != AppOpsManager.MODE_ALLOWED) {
-                    return ActivityManager.APP_START_MODE_DELAYED;
-                }
+                */
+
+                final int startMode = (alwaysRestrict)
+                        ? appRestrictedInBackgroundLocked(uid, packageName)
+                        : appServicesRestrictedInBackgroundLocked(uid, packageName);
+                if (DEBUG_BACKGROUND_CHECK) Slog.d(TAG, "checkAllowBackground: uid=" + uid
+                        + " pkg=" + packageName + " startMode=" + startMode
+                        + " onwhitelist=" + isOnDeviceIdleWhitelistLocked(uid));
+                return startMode;
             }
         }
         return ActivityManager.APP_START_MODE_NORMAL;
     }
 
+    boolean isOnDeviceIdleWhitelistLocked(int uid) {
+        final int appId = UserHandle.getAppId(uid);
+        return Arrays.binarySearch(mDeviceIdleWhitelist, appId) >= 0
+                || Arrays.binarySearch(mDeviceIdleTempWhitelist, appId) >= 0;
+    }
+
     private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) {
         ProviderInfo pi = null;
         ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userHandle);
@@ -8079,6 +8223,12 @@
         return pi;
     }
 
+    void grantEphemeralAccessLocked(int userId, Intent intent,
+            int targetAppId, int ephemeralAppId) {
+        getPackageManagerInternalLocked().
+                grantEphemeralAccess(userId, intent, targetAppId, ephemeralAppId);
+    }
+
     private UriPermission findUriPermissionLocked(int targetUid, GrantUri grantUri) {
         final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
         if (targetUris != null) {
@@ -11651,6 +11801,16 @@
         return r;
     }
 
+    private boolean uidOnBackgroundWhitelist(final int uid) {
+        final int N = mBackgroundUidWhitelist.length;
+        for (int i = 0; i < N; i++) {
+            if (uid == mBackgroundUidWhitelist[i]) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
             String abiOverride) {
         ProcessRecord app;
@@ -14977,6 +15137,8 @@
                     }
                 }
             }
+            pw.println("  mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
+            pw.println("  mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
         }
         if (dumpPackage == null) {
             pw.println("  mWakefulness="
@@ -17284,7 +17446,8 @@
 
     @Override
     public ComponentName startService(IApplicationThread caller, Intent service,
-            String resolvedType, String callingPackage, int userId)
+            String resolvedType, int id, Notification notification,
+            String callingPackage, int userId)
             throws TransactionTooLargeException {
         enforceNotIsolatedCaller("startService");
         // Refuse possible leaked file descriptors
@@ -17303,7 +17466,8 @@
             final int callingUid = Binder.getCallingUid();
             final long origId = Binder.clearCallingIdentity();
             ComponentName res = mServices.startServiceLocked(caller, service,
-                    resolvedType, callingPid, callingUid, callingPackage, userId);
+                    resolvedType, id, notification,
+                    callingPid, callingUid, callingPackage, userId);
             Binder.restoreCallingIdentity(origId);
             return res;
         }
@@ -17317,7 +17481,7 @@
                     "startServiceInPackage: " + service + " type=" + resolvedType);
             final long origId = Binder.clearCallingIdentity();
             ComponentName res = mServices.startServiceLocked(null, service,
-                    resolvedType, -1, uid, callingPackage, userId);
+                    resolvedType, 0, null, -1, uid, callingPackage, userId);
             Binder.restoreCallingIdentity(origId);
             return res;
         }
@@ -18176,6 +18340,13 @@
         }
 
         if (action != null) {
+            if (mBackgroundLaunchBroadcasts.contains(action)) {
+                if (DEBUG_BACKGROUND_CHECK) {
+                    Slog.i(TAG, "Broadcast action " + action + " forcing include-background");
+                }
+                intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+            }
+
             switch (action) {
                 case Intent.ACTION_UID_REMOVED:
                 case Intent.ACTION_PACKAGE_REMOVED:
@@ -19300,7 +19471,8 @@
                 UserHandle.USER_ALL);
         if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
             intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
-            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
             if (initLocale || !mProcessesReady) {
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             }
@@ -21623,12 +21795,18 @@
         for (int i=mActiveUids.size()-1; i>=0; i--) {
             final UidRecord uidRec = mActiveUids.valueAt(i);
             int uidChange = UidRecord.CHANGE_PROCSTATE;
-            if (uidRec.setProcState != uidRec.curProcState) {
+            if (uidRec.setProcState != uidRec.curProcState
+                    || uidRec.setWhitelist != uidRec.curWhitelist) {
                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                         "Changes in " + uidRec + ": proc state from " + uidRec.setProcState
-                        + " to " + uidRec.curProcState);
-                if (ActivityManager.isProcStateBackground(uidRec.curProcState)) {
-                    if (!ActivityManager.isProcStateBackground(uidRec.setProcState)) {
+                        + " to " + uidRec.curProcState + ", whitelist from " + uidRec.setWhitelist
+                        + " to " + uidRec.curWhitelist);
+                if (ActivityManager.isProcStateBackground(uidRec.curProcState)
+                        && !uidRec.curWhitelist) {
+                    // UID is now in the background (and not on the temp whitelist).  Was it
+                    // previously in the foreground (or on the temp whitelist)?
+                    if (!ActivityManager.isProcStateBackground(uidRec.setProcState)
+                            || uidRec.setWhitelist) {
                         uidRec.lastBackgroundTime = nowElapsed;
                         if (!mHandler.hasMessages(IDLE_UIDS_MSG)) {
                             // Note: the background settle time is in elapsed realtime, while
@@ -21646,6 +21824,7 @@
                     uidRec.lastBackgroundTime = 0;
                 }
                 uidRec.setProcState = uidRec.curProcState;
+                uidRec.setWhitelist = uidRec.curWhitelist;
                 enqueueUidChangeLocked(uidRec, -1, uidChange);
                 noteUidProcessState(uidRec.uid, uidRec.curProcState);
             }
@@ -21789,6 +21968,20 @@
         enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE);
     }
 
+    final void setAppIdTempWhitelistStateLocked(int appId, boolean onWhitelist) {
+        boolean changed = false;
+        for (int i=mActiveUids.size()-1; i>=0; i--) {
+            final UidRecord uidRec = mActiveUids.valueAt(i);
+            if (UserHandle.getAppId(uidRec.uid) == appId && uidRec.curWhitelist != onWhitelist) {
+                uidRec.curWhitelist = onWhitelist;
+                changed = true;
+            }
+        }
+        if (changed) {
+            updateOomAdjLocked();
+        }
+    }
+
     final void trimApplications() {
         synchronized (this) {
             int i;
@@ -22494,6 +22687,21 @@
         }
 
         @Override
+        public void setDeviceIdleWhitelist(int[] appids) {
+            synchronized (ActivityManagerService.this) {
+                mDeviceIdleWhitelist = appids;
+            }
+        }
+
+        @Override
+        public void updateDeviceIdleTempWhitelist(int[] appids, int changingAppId, boolean adding) {
+            synchronized (ActivityManagerService.this) {
+                mDeviceIdleTempWhitelist = appids;
+                setAppIdTempWhitelistStateLocked(changingAppId, adding);
+            }
+        }
+
+        @Override
         public void updatePersistentConfigurationForUser(@NonNull Configuration values,
                 int userId) {
             Preconditions.checkNotNull(values, "Configuration must not be null");
@@ -22776,6 +22984,52 @@
         return mUserController.restartUser(userId, /* foreground */ false);
     }
 
+    @Override
+    public void scheduleApplicationInfoChanged(List<String> packageNames, int userId) {
+        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
+                "scheduleApplicationInfoChanged()");
+
+        synchronized (this) {
+            final long origId = Binder.clearCallingIdentity();
+            try {
+                updateApplicationInfoLocked(packageNames, userId);
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
+        }
+    }
+
+    void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
+        final boolean updateFrameworkRes = packagesToUpdate.contains("android");
+        for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
+            final ProcessRecord app = mLruProcesses.get(i);
+            if (app.thread == null) {
+                continue;
+            }
+
+            if (userId != UserHandle.USER_ALL && app.userId != userId) {
+                continue;
+            }
+
+            final int packageCount = app.pkgList.size();
+            for (int j = 0; j < packageCount; j++) {
+                final String packageName = app.pkgList.keyAt(j);
+                if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
+                    try {
+                        final ApplicationInfo ai = mPackageManagerInt.getApplicationInfo(
+                                packageName, app.userId);
+                        if (ai != null) {
+                            app.thread.scheduleApplicationInfoChanged(ai);
+                        }
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, String.format("Failed to update %s ApplicationInfo for %s",
+                                    packageName, app));
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * Attach an agent to the specified process (proces name or PID)
      */
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 29a4781..202868a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -171,7 +171,7 @@
                     return runKill(pw);
                 case "kill-all":
                     return runKillAll(pw);
-                case "make-idle":
+                case "make-uid-idle":
                     return runMakeIdle(pw);
                 case "monitor":
                     return runMonitor(pw);
@@ -235,6 +235,8 @@
                     return runSupportsMultiwindow(pw);
                 case "supports-split-screen-multi-window":
                     return runSupportsSplitScreenMultiwindow(pw);
+                case "update-appinfo":
+                    return runUpdateApplicationInfo(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -490,7 +492,7 @@
         pw.println("Starting service: " + intent);
         pw.flush();
         ComponentName cn = mInterface.startService(null, intent, intent.getType(),
-                SHELL_PACKAGE_NAME, mUserId);
+                -1, null, SHELL_PACKAGE_NAME, mUserId);
         if (cn == null) {
             err.println("Error: Not found; no service started.");
             return -1;
@@ -500,6 +502,9 @@
         } else if (cn.getPackageName().equals("!!")) {
             err.println("Error: " + cn.getClassName());
             return -1;
+        } else if (cn.getPackageName().equals("?")) {
+            err.println("Error: " + cn.getClassName());
+            return -1;
         }
         return 0;
     }
@@ -2323,6 +2328,19 @@
         return 0;
     }
 
+    int runUpdateApplicationInfo(PrintWriter pw) throws RemoteException {
+        int userid = UserHandle.parseUserArg(getNextArgRequired());
+        ArrayList<String> packages = new ArrayList<>();
+        packages.add(getNextArgRequired());
+        String packageName;
+        while ((packageName = getNextArg()) != null) {
+            packages.add(packageName);
+        }
+        mInternal.scheduleApplicationInfoChanged(packages, userid);
+        pw.println("Packages updated with most recent ApplicationInfos.");
+        return 0;
+    }
+
     private Resources getResources(PrintWriter pw) throws RemoteException {
         // system resources does not contain all the device configuration, construct it manually.
         Configuration config = mInterface.getConfiguration();
@@ -2466,6 +2484,9 @@
             pw.println("      Kill all processes associated with the given application.");
             pw.println("  kill-all");
             pw.println("      Kill all processes that are safe to kill (cached, etc).");
+            pw.println("  make-uid-idle [--user <USER_ID> | all | current] <PACKAGE>");
+            pw.println("      If the given application's uid is in the background and waiting to");
+            pw.println("      become idle (not allowing background services), do that now.");
             pw.println("  monitor [--gdb <port>]");
             pw.println("      Start monitoring for crashes or ANRs.");
             pw.println("      --gdb: start gdbserv on the given port at crash/ANR");
@@ -2584,6 +2605,9 @@
             pw.println("           Test command for sizing <TASK_ID> by <STEP_SIZE>");
             pw.println("           increments within the screen applying the optional [DELAY_MS] between");
             pw.println("           each step.");
+            pw.println("  update-appinfo <USER_ID> <PACKAGE_NAME> [<PACKAGE_NAME>...]");
+            pw.println("      Update the ApplicationInfo objects of the listed packages for <USER_ID>");
+            pw.println("      without restarting any processes.");
             pw.println("  write");
             pw.println("      Write all pending state to storage.");
             pw.println();
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 2634385..46e00479 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -582,7 +582,10 @@
             // The activity was already running in the pinned stack so it wasn't started, but either
             // brought to the front or the new intent was delivered to it since it was already in
             // front. Notify anyone interested in this piece of information.
-            mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt();
+            final ComponentName sourceComponent = sourceRecord == null ? null :
+                    sourceRecord.realActivity;
+            mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
+                    sourceComponent);
             return;
         }
     }
@@ -1128,7 +1131,8 @@
 
         mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
                 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
-
+        mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
+                mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
         if (mSourceRecord != null && mSourceRecord.isRecentsActivity()) {
             mStartActivity.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
         }
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 8104a43..61e555b 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -1157,8 +1157,7 @@
 
             if (!skip) {
                 final int allowed = mService.checkAllowBackgroundLocked(
-                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1,
-                        true);
+                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1, true);
                 if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                     // We won't allow this receiver to be launched if the app has been
                     // completely disabled from launches, or it was not explicitly sent
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index d035fa9..2990dff 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -97,7 +97,7 @@
     };
 
     private final TaskStackConsumer mNotifyPinnedActivityRestartAttempt = (l, m) -> {
-        l.onPinnedActivityRestartAttempt();
+        l.onPinnedActivityRestartAttempt((ComponentName) m.obj);
     };
 
     private final TaskStackConsumer mNotifyPinnedStackAnimationEnded = (l, m) -> {
@@ -267,10 +267,11 @@
      * running in the pinned stack and the activity was not actually started, but the task is
      * either brought to the front or a new Intent is delivered to it.
      */
-    void notifyPinnedActivityRestartAttempt() {
+    void notifyPinnedActivityRestartAttempt(ComponentName sourceComponent) {
         mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
         final Message msg =
-                mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
+                mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG,
+                        sourceComponent);
         forAllLocalListeners(mNotifyPinnedActivityRestartAttempt, msg);
         msg.sendToTarget();
     }
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 7a62f2c..9dde39e 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -651,6 +651,8 @@
                                         "omitting from persistentTaskIds task=" + task);
                             }
                         }
+                        mService.mWindowManager.removeObsoleteTaskFiles(persistentTaskIds,
+                                mRecentTasks.usersWithRecentsLoadedLocked());
                     }
                     removeObsoleteFiles(persistentTaskIds);
                 }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index a72a958..db6c0f7 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -788,6 +788,9 @@
             inRecents = false;
             mService.notifyTaskPersisterLocked(this, false);
         }
+
+        // TODO: Use window container controller once tasks are better synced between AM and WM
+        mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId);
     }
 
     void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index d1a15bd..64e3417 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -26,10 +26,13 @@
  */
 public final class UidRecord {
     final int uid;
+    final boolean persistent;
     int curProcState;
     int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
     long lastBackgroundTime;
     boolean ephemeral;
+    boolean curWhitelist;
+    boolean setWhitelist;
     boolean idle;
     int numProcs;
 
@@ -49,8 +52,9 @@
 
     ChangeItem pendingChange;
 
-    public UidRecord(int _uid) {
+    public UidRecord(int _uid, boolean _persist) {
         uid = _uid;
+        persistent = _persist;
         reset();
     }
 
@@ -69,6 +73,9 @@
         if (ephemeral) {
             sb.append(" ephemeral");
         }
+        if (curWhitelist) {
+            sb.append(" whitelist");
+        }
         if (lastBackgroundTime > 0) {
             sb.append(" bg:");
             TimeUtils.formatDuration(SystemClock.elapsedRealtime()-lastBackgroundTime, sb);
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index f516e99..5bf92d7 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -419,7 +419,8 @@
                 if (userId != UserHandle.USER_SYSTEM) {
                     Slog.d(TAG, "Initializing user #" + userId);
                     Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
-                    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+                            | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                     mInjector.broadcastIntentLocked(intent, null,
                             new IIntentReceiver.Stub() {
                                 @Override
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 5f9efe7..85d1d1e 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -23,6 +23,7 @@
 import android.net.Network;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
+import android.net.TrafficStats;
 import android.os.SystemClock;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -381,7 +382,12 @@
         protected void setupSocket(
                 int sockType, int protocol, long writeTimeout, long readTimeout, int dstPort)
                 throws ErrnoException, IOException {
-            mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
+            final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+            try {
+                mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol);
+            } finally {
+                TrafficStats.setThreadStatsTag(oldTag);
+            }
             // Setting SNDTIMEO is purely for defensive purposes.
             Os.setsockoptTimeval(mFileDescriptor,
                     SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(writeTimeout));
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index c40780e..fbda901 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -779,6 +779,7 @@
         int httpResponseCode = 599;
         String redirectUrl = null;
         final Stopwatch probeTimer = new Stopwatch().start();
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
         try {
             urlConnection = (HttpURLConnection) mNetworkAgentInfo.network.openConnection(url);
             urlConnection.setInstanceFollowRedirects(probeType == ValidationProbeEvent.PROBE_PAC);
@@ -839,6 +840,7 @@
             if (urlConnection != null) {
                 urlConnection.disconnect();
             }
+            TrafficStats.setThreadStatsTag(oldTag);
         }
         logValidationProbe(probeTimer.stop(), probeType, httpResponseCode);
         return new CaptivePortalProbeResult(httpResponseCode, redirectUrl, url.toString());
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 58c76ec..34826b6 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -25,6 +25,7 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.net.ProxyInfo;
+import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -103,11 +104,15 @@
             String file;
             synchronized (mProxyLock) {
                 if (Uri.EMPTY.equals(mPacUrl)) return;
+                final int oldTag = TrafficStats
+                        .getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_PAC);
                 try {
                     file = get(mPacUrl);
                 } catch (IOException ioe) {
                     file = null;
                     Log.w(TAG, "Failed to load PAC file: " + ioe);
+                } finally {
+                    TrafficStats.setThreadStatsTag(oldTag);
                 }
             }
             if (file != null) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 0c80166..bd88ddb 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -16,6 +16,11 @@
 
 package com.android.server.connectivity;
 
+import static android.hardware.usb.UsbManager.USB_CONNECTED;
+import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -208,13 +213,13 @@
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
-        mContext.registerReceiver(mStateReceiver, filter);
+        mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler());
 
         filter = new IntentFilter();
         filter.addAction(Intent.ACTION_MEDIA_SHARED);
         filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
         filter.addDataScheme("file");
-        mContext.registerReceiver(mStateReceiver, filter);
+        mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler());
 
         mDhcpRange = context.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_dhcp_range);
@@ -779,69 +784,84 @@
     private class StateReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context content, Intent intent) {
-            String action = intent.getAction();
-            if (action == null) { return; }
+            final String action = intent.getAction();
+            if (action == null) return;
+
             if (action.equals(UsbManager.ACTION_USB_STATE)) {
-                synchronized (Tethering.this.mPublicSync) {
-                    boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
-                    mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
-                    // start tethering if we have a request pending
-                    if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
-                        tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_USB);
-                    }
-                    mUsbTetherRequested = false;
-                }
+                handleUsbAction(intent);
             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
-                NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
-                        ConnectivityManager.EXTRA_NETWORK_INFO);
-                if (networkInfo != null &&
-                        networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
-                    if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
-                    mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
-                }
+                handleConnectivityAction(intent);
             } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
-                synchronized (Tethering.this.mPublicSync) {
-                    int curState =  intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE,
-                            WifiManager.WIFI_AP_STATE_DISABLED);
-                    switch (curState) {
-                        case WifiManager.WIFI_AP_STATE_ENABLING:
-                            // We can see this state on the way to both enabled and failure states.
-                            break;
-                        case WifiManager.WIFI_AP_STATE_ENABLED:
-                            // When the AP comes up and we've been requested to tether it, do so.
-                            if (mWifiTetherRequested) {
-                                tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_WIFI);
-                            }
-                            break;
-                        case WifiManager.WIFI_AP_STATE_DISABLED:
-                        case WifiManager.WIFI_AP_STATE_DISABLING:
-                        case WifiManager.WIFI_AP_STATE_FAILED:
-                        default:
-                            if (DBG) {
-                                Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" +
-                                    curState);
-                            }
-                            // Tell appropriate interface state machines that they should tear
-                            // themselves down.
-                            for (int i = 0; i < mTetherStates.size(); i++) {
-                                TetherInterfaceStateMachine tism =
-                                        mTetherStates.valueAt(i).mStateMachine;
-                                if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
-                                    tism.sendMessage(
-                                            TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
-                                    break;  // There should be at most one of these.
-                                }
-                            }
-                            // Regardless of whether we requested this transition, the AP has gone
-                            // down.  Don't try to tether again unless we're requested to do so.
-                            mWifiTetherRequested = false;
-                            break;
-                    }
-                }
+                handleWifiApAction(intent);
             } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
                 updateConfiguration();
             }
         }
+
+        private void handleConnectivityAction(Intent intent) {
+            final NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
+                    ConnectivityManager.EXTRA_NETWORK_INFO);
+            if (networkInfo == null ||
+                    networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) {
+                return;
+            }
+
+            if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString());
+            mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
+        }
+
+        private void handleUsbAction(Intent intent) {
+            final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
+            final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
+            synchronized (Tethering.this.mPublicSync) {
+                mRndisEnabled = rndisEnabled;
+                // start tethering if we have a request pending
+                if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
+                    tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_USB);
+                }
+                mUsbTetherRequested = false;
+            }
+        }
+
+        private void handleWifiApAction(Intent intent) {
+            final int curState =  intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+            synchronized (Tethering.this.mPublicSync) {
+                switch (curState) {
+                    case WifiManager.WIFI_AP_STATE_ENABLING:
+                        // We can see this state on the way to both enabled and failure states.
+                        break;
+                    case WifiManager.WIFI_AP_STATE_ENABLED:
+                        // When the AP comes up and we've been requested to tether it, do so.
+                        if (mWifiTetherRequested) {
+                            tetherMatchingInterfaces(true, ConnectivityManager.TETHERING_WIFI);
+                        }
+                        break;
+                    case WifiManager.WIFI_AP_STATE_DISABLED:
+                    case WifiManager.WIFI_AP_STATE_DISABLING:
+                    case WifiManager.WIFI_AP_STATE_FAILED:
+                    default:
+                        if (DBG) {
+                            Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" +
+                                curState);
+                        }
+                        // Tell appropriate interface state machines that they should tear
+                        // themselves down.
+                        for (int i = 0; i < mTetherStates.size(); i++) {
+                            TetherInterfaceStateMachine tism =
+                                    mTetherStates.valueAt(i).mStateMachine;
+                            if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
+                                tism.sendMessage(
+                                        TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
+                                break;  // There should be at most one of these.
+                            }
+                        }
+                        // Regardless of whether we requested this transition, the AP has gone
+                        // down.  Don't try to tether again unless we're requested to do so.
+                        mWifiTetherRequested = false;
+                    break;
+                }
+            }
+        }
     }
 
     private void tetherMatchingInterfaces(boolean enable, int interfaceType) {
@@ -891,10 +911,6 @@
     public int setUsbTethering(boolean enable) {
         if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
         UsbManager usbManager = mContext.getSystemService(UsbManager.class);
-        if (usbManager == null) {
-            return enable ? ConnectivityManager.TETHER_ERROR_MASTER_ERROR
-                          : ConnectivityManager.TETHER_ERROR_NO_ERROR;
-        }
 
         synchronized (mPublicSync) {
             if (enable) {
@@ -1083,7 +1099,7 @@
         private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
         private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
 
-        private int mPreviousMobileApn = ConnectivityManager.TYPE_NONE;
+        private int mPreviousMobileType = ConnectivityManager.TYPE_NONE;
 
         private static final int UPSTREAM_SETTLE_TIME_MS     = 10000;
 
@@ -1118,13 +1134,13 @@
                 return false;
             }
 
-            protected boolean turnOnUpstreamMobileConnection(int apnType) {
+            protected boolean requestUpstreamMobileConnection(int apnType) {
                 if (apnType == ConnectivityManager.TYPE_NONE) { return false; }
 
-                if (apnType != mPreviousMobileApn) {
+                if (apnType != mPreviousMobileType) {
                     // Unregister any previous mobile upstream callback because
                     // this request, if any, will be different.
-                    turnOffUpstreamMobileConnection();
+                    unrequestUpstreamMobileConnection();
                 }
 
                 if (mUpstreamNetworkMonitor.mobileNetworkRequested()) {
@@ -1136,25 +1152,25 @@
                     case ConnectivityManager.TYPE_MOBILE_DUN:
                     case ConnectivityManager.TYPE_MOBILE:
                     case ConnectivityManager.TYPE_MOBILE_HIPRI:
-                        mPreviousMobileApn = apnType;
+                        mPreviousMobileType = apnType;
                         break;
                     default:
                         return false;
                 }
 
-                // TODO: This should be called by the code that observes
-                // configuration changes, once the above code in this function
-                // is simplified (i.e. eradicated).
-                mUpstreamNetworkMonitor.mobileUpstreamRequiresDun(
+                // TODO: Replace this with a call to pass the current tethering
+                // configuration to mUpstreamNetworkMonitor and let it handle
+                // choosing APN type accordingly.
+                mUpstreamNetworkMonitor.updateMobileRequiresDun(
                         apnType == ConnectivityManager.TYPE_MOBILE_DUN);
 
                 mUpstreamNetworkMonitor.registerMobileNetworkRequest();
                 return true;
             }
 
-            protected void turnOffUpstreamMobileConnection() {
+            protected void unrequestUpstreamMobileConnection() {
                 mUpstreamNetworkMonitor.releaseMobileNetworkRequest();
-                mPreviousMobileApn = ConnectivityManager.TYPE_NONE;
+                mPreviousMobileType = ConnectivityManager.TYPE_NONE;
             }
 
             protected boolean turnOnMasterTetherSettings() {
@@ -1233,11 +1249,11 @@
                     case ConnectivityManager.TYPE_MOBILE_DUN:
                     case ConnectivityManager.TYPE_MOBILE_HIPRI:
                         // If we're on DUN, put our own grab on it.
-                        turnOnUpstreamMobileConnection(upType);
+                        requestUpstreamMobileConnection(upType);
                         break;
                     case ConnectivityManager.TYPE_NONE:
                         if (tryCell &&
-                                turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn)) {
+                                requestUpstreamMobileConnection(mPreferredUpstreamMobileApn)) {
                             // We think mobile should be coming up; don't set a retry.
                         } else {
                             sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
@@ -1250,7 +1266,7 @@
                          * If we found NONE we don't want to do this as we want any previous
                          * requests to keep trying to bring up something we can use.
                          */
-                        turnOffUpstreamMobileConnection();
+                        unrequestUpstreamMobileConnection();
                         break;
                 }
 
@@ -1330,96 +1346,127 @@
             }
         }
 
-        private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0);
-        private SimChangeBroadcastReceiver mBroadcastReceiver = null;
+        private class SimChangeListener {
+            private final Context mContext;
+            private final AtomicInteger mSimBcastGenerationNumber;
+            private BroadcastReceiver mBroadcastReceiver;
 
-        private void startListeningForSimChanges() {
-            if (DBG) Log.d(TAG, "startListeningForSimChanges");
-            if (mBroadcastReceiver == null) {
+            SimChangeListener(Context ctx) {
+                mContext = ctx;
+                mSimBcastGenerationNumber = new AtomicInteger(0);
+            }
+
+            public int generationNumber() {
+                return mSimBcastGenerationNumber.get();
+            }
+
+            public void startListening() {
+                if (DBG) Log.d(TAG, "startListening for SIM changes");
+
+                if (mBroadcastReceiver != null) return;
+
                 mBroadcastReceiver = new SimChangeBroadcastReceiver(
                         mSimBcastGenerationNumber.incrementAndGet());
                 final IntentFilter filter = new IntentFilter();
                 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
 
-                mContext.registerReceiver(mBroadcastReceiver, filter);
+                mContext.registerReceiver(mBroadcastReceiver, filter, null,
+                        mTetherMasterSM.getHandler());
             }
-        }
 
-        private void stopListeningForSimChanges() {
-            if (DBG) Log.d(TAG, "stopListeningForSimChanges");
-            if (mBroadcastReceiver != null) {
+            public void stopListening() {
+                if (DBG) Log.d(TAG, "stopListening for SIM changes");
+
+                if (mBroadcastReceiver == null) return;
+
                 mSimBcastGenerationNumber.incrementAndGet();
                 mContext.unregisterReceiver(mBroadcastReceiver);
                 mBroadcastReceiver = null;
             }
-        }
 
-        class SimChangeBroadcastReceiver extends BroadcastReceiver {
-            // used to verify this receiver is still current
-            final private int mGenerationNumber;
-
-            // we're interested in edge-triggered LOADED notifications, so
-            // ignore LOADED unless we saw an ABSENT state first
-            private boolean mSimAbsentSeen = false;
-
-            public SimChangeBroadcastReceiver(int generationNumber) {
-                super();
-                mGenerationNumber = generationNumber;
+            public boolean hasMobileHotspotProvisionApp() {
+                try {
+                    if (!mContext.getResources().getString(com.android.internal.R.string.
+                            config_mobile_hotspot_provision_app_no_ui).isEmpty()) {
+                        Log.d(TAG, "re-evaluate provisioning");
+                        return true;
+                    }
+                } catch (Resources.NotFoundException e) {}
+                Log.d(TAG, "no prov-check needed for new SIM");
+                return false;
             }
 
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                if (DBG) {
-                    Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber +
-                            ", current generationNumber=" + mSimBcastGenerationNumber.get());
-                }
-                if (mGenerationNumber != mSimBcastGenerationNumber.get()) return;
+            private boolean isSimCardAbsent(String state) {
+                return IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state);
+            }
 
-                final String state =
-                        intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+            private boolean isSimCardLoaded(String state) {
+                return IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state);
+            }
 
-                Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" +
-                        mSimAbsentSeen);
-                if (!mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) {
-                    mSimAbsentSeen = true;
+            private void startProvisionIntent(int tetherType) {
+                final Intent startProvIntent = new Intent();
+                startProvIntent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
+                startProvIntent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
+                startProvIntent.setComponent(TETHER_SERVICE);
+                mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
+            }
+
+            private class SimChangeBroadcastReceiver extends BroadcastReceiver {
+                // used to verify this receiver is still current
+                final private int mGenerationNumber;
+
+                // we're interested in edge-triggered LOADED notifications, so
+                // ignore LOADED unless we saw an ABSENT state first
+                private boolean mSimAbsentSeen = false;
+
+                public SimChangeBroadcastReceiver(int generationNumber) {
+                    mGenerationNumber = generationNumber;
                 }
 
-                if (mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) {
-                    mSimAbsentSeen = false;
-                    try {
-                        if (mContext.getResources().getString(com.android.internal.R.string.
-                                config_mobile_hotspot_provision_app_no_ui).isEmpty() == false) {
-                            ArrayList<Integer> tethered = new ArrayList<Integer>();
-                            synchronized (mPublicSync) {
-                                for (int i = 0; i < mTetherStates.size(); i++) {
-                                    TetherState tetherState = mTetherStates.valueAt(i);
-                                    if (tetherState.mLastState !=
-                                            IControlsTethering.STATE_TETHERED) {
-                                        continue;  // Skip interfaces that aren't tethered.
-                                    }
-                                    String iface = mTetherStates.keyAt(i);
-                                    int interfaceType = ifaceNameToType(iface);
-                                    if (interfaceType != ConnectivityManager.TETHERING_INVALID) {
-                                        tethered.add(new Integer(interfaceType));
-                                    }
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    final int currentGenerationNumber = mSimBcastGenerationNumber.get();
+
+                    if (DBG) {
+                        Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber +
+                                ", current generationNumber=" + currentGenerationNumber);
+                    }
+                    if (mGenerationNumber != currentGenerationNumber) return;
+
+                    final String state = intent.getStringExtra(
+                            IccCardConstants.INTENT_KEY_ICC_STATE);
+                    Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" +
+                            mSimAbsentSeen);
+
+                    if (isSimCardAbsent(state)) {
+                        if (!mSimAbsentSeen) mSimAbsentSeen = true;
+                        return;
+                    }
+
+                    if (isSimCardLoaded(state) && mSimAbsentSeen) {
+                        mSimAbsentSeen = false;
+
+                        if (!hasMobileHotspotProvisionApp()) return;
+
+                        ArrayList<Integer> tethered = new ArrayList<Integer>();
+                        synchronized (mPublicSync) {
+                            for (int i = 0; i < mTetherStates.size(); i++) {
+                                TetherState tetherState = mTetherStates.valueAt(i);
+                                if (tetherState.mLastState != IControlsTethering.STATE_TETHERED) {
+                                    continue;  // Skip interfaces that aren't tethered.
+                                }
+                                String iface = mTetherStates.keyAt(i);
+                                int interfaceType = ifaceNameToType(iface);
+                                if (interfaceType != ConnectivityManager.TETHERING_INVALID) {
+                                    tethered.add(new Integer(interfaceType));
                                 }
                             }
-                            for (int tetherType : tethered) {
-                                Intent startProvIntent = new Intent();
-                                startProvIntent.putExtra(
-                                        ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
-                                startProvIntent.putExtra(
-                                        ConnectivityManager.EXTRA_RUN_PROVISION, true);
-                                startProvIntent.setComponent(TETHER_SERVICE);
-                                mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
-                            }
-                            Log.d(TAG, "re-evaluate provisioning");
-                        } else {
-                            Log.d(TAG, "no prov-check needed for new SIM");
                         }
-                    } catch (Resources.NotFoundException e) {
-                        Log.d(TAG, "no prov-check needed for new SIM");
-                        // not defined, do nothing
+
+                        for (int tetherType : tethered) {
+                            startProvisionIntent(tetherType);
+                        }
                     }
                 }
             }
@@ -1455,12 +1502,13 @@
         }
 
         class TetherModeAliveState extends TetherMasterUtilState {
+            final SimChangeListener simChange = new SimChangeListener(mContext);
             boolean mTryCell = true;
             @Override
             public void enter() {
                 // TODO: examine if we should check the return value.
                 turnOnMasterTetherSettings(); // may transition us out
-                startListeningForSimChanges();
+                simChange.startListening();
                 mUpstreamNetworkMonitor.start();
 
                 mTryCell = true;  // better try something first pass or crazy tests cases will fail
@@ -1470,9 +1518,9 @@
 
             @Override
             public void exit() {
-                turnOffUpstreamMobileConnection();
+                unrequestUpstreamMobileConnection();
                 mUpstreamNetworkMonitor.stop();
-                stopListeningForSimChanges();
+                simChange.stopListening();
                 notifyTetheredOfNewUpstreamIface(null);
                 handleNewUpstreamNetworkState(null);
             }
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 4c950de..23481dc 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -109,7 +109,7 @@
         mNetworkMap.clear();
     }
 
-    public void mobileUpstreamRequiresDun(boolean dunRequired) {
+    public void updateMobileRequiresDun(boolean dunRequired) {
         final boolean valueChanged = (mDunRequired != dunRequired);
         mDunRequired = dunRequired;
         if (valueChanged && mobileNetworkRequested()) {
@@ -123,7 +123,10 @@
     }
 
     public void registerMobileNetworkRequest() {
-        if (mMobileNetworkCallback != null) return;
+        if (mMobileNetworkCallback != null) {
+            Log.e(TAG, "registerMobileNetworkRequest() already registered");
+            return;
+        }
 
         final NetworkRequest.Builder builder = new NetworkRequest.Builder()
                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
@@ -139,11 +142,10 @@
         // Therefore, to avoid duplicate notifications, we only register a no-op.
         mMobileNetworkCallback = new NetworkCallback();
 
-        // TODO: Change the timeout from 0 (no onUnavailable callback) to use some
-        // moderate callback time (once timeout callbacks are implemented). This might
-        // be useful for updating some UI. Additionally, we should definitely log a
-        // message to aid in any subsequent debugging
-        if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
+        // TODO: Change the timeout from 0 (no onUnavailable callback) to some
+        // moderate callback timeout. This might be useful for updating some UI.
+        // Additionally, we log a message to aid in any subsequent debugging.
+        Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
 
         // The following use of the legacy type system cannot be removed until
         // after upstream selection no longer finds networks by legacy type.
diff --git a/services/core/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsXtraDownloader.java
index bf779859..62332c9 100644
--- a/services/core/java/com/android/server/location/GpsXtraDownloader.java
+++ b/services/core/java/com/android/server/location/GpsXtraDownloader.java
@@ -16,22 +16,19 @@
 
 package com.android.server.location;
 
+import android.net.TrafficStats;
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.IOException;
 import java.util.Properties;
 import java.util.Random;
 import java.util.concurrent.TimeUnit;
 
-import libcore.io.Streams;
-
 /**
  * A class for downloading GPS XTRA data.
  *
@@ -94,7 +91,12 @@
 
         // load balance our requests among the available servers
         while (result == null) {
-            result = doDownload(mXtraServers[mNextServerIndex]);
+            final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_GPS);
+            try {
+                result = doDownload(mXtraServers[mNextServerIndex]);
+            } finally {
+                TrafficStats.setThreadStatsTag(oldTag);
+            }
 
             // increment mNextServerIndex and wrap around if necessary
             mNextServerIndex++;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9018302..6c66a60 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -702,16 +702,19 @@
                 int changeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                         UserHandle.USER_ALL);
                 String pkgList[] = null;
+                int uidList[] = null;
                 boolean removingPackage = queryRemove &&
                         !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                 if (DBG) Slog.i(TAG, "action=" + action + " removing=" + removingPackage);
                 if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                    uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
                 } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                     reason = REASON_PACKAGE_SUSPENDED;
                 } else if (queryRestart) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+                    uidList = new int[] {intent.getIntExtra(Intent.EXTRA_UID, -1)};
                 } else {
                     Uri uri = intent.getData();
                     if (uri == null) {
@@ -743,8 +746,8 @@
                         }
                     }
                     pkgList = new String[]{pkgName};
+                    uidList = new int[] {intent.getIntExtra(Intent.EXTRA_UID, -1)};
                 }
-
                 if (pkgList != null && (pkgList.length > 0)) {
                     for (String pkgName : pkgList) {
                         if (cancelNotifications) {
@@ -756,7 +759,8 @@
                 mListeners.onPackagesChanged(removingPackage, pkgList);
                 mNotificationAssistants.onPackagesChanged(removingPackage, pkgList);
                 mConditionProviders.onPackagesChanged(removingPackage, pkgList);
-                mRankingHelper.onPackagesChanged(removingPackage, changeUserId, pkgList);
+                mRankingHelper.onPackagesChanged(removingPackage, changeUserId, pkgList, uidList);
+                savePolicyFile();
             }
         }
     };
@@ -1527,14 +1531,16 @@
         @Override
         public NotificationChannel getNotificationChannel(String pkg, String channelId) {
             checkCallerIsSystemOrSameApp(pkg);
-            return mRankingHelper.getNotificationChannel(pkg, Binder.getCallingUid(), channelId);
+            return mRankingHelper.getNotificationChannel(
+                    pkg, Binder.getCallingUid(), channelId, false /* includeDeleted */);
         }
 
         @Override
         public NotificationChannel getNotificationChannelForPackage(String pkg, int uid,
-                String channelId) {
+                String channelId, boolean includeDeleted) {
             checkCallerIsSystem();
-            return mRankingHelper.getNotificationChannel(pkg, uid, channelId);
+            return mRankingHelper.getNotificationChannel
+                    (pkg, uid, channelId, includeDeleted);
         }
 
         @Override
@@ -1566,17 +1572,42 @@
 
         @Override
         public ParceledListSlice<NotificationChannel> getNotificationChannelsForPackage(String pkg,
-                int uid) {
+                int uid, boolean includeDeleted) {
             checkCallerIsSystem();
-            return mRankingHelper.getNotificationChannels(pkg, uid);
+            return mRankingHelper.getNotificationChannels(pkg, uid, includeDeleted);
         }
 
         @Override
         public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg) {
             checkCallerIsSystemOrSameApp(pkg);
-            return mRankingHelper.getNotificationChannels(pkg, Binder.getCallingUid());
+            return mRankingHelper.getNotificationChannels(
+                    pkg, Binder.getCallingUid(), false /* includeDeleted */);
         }
 
+
+        @Override
+        public void clearData(String packageName, int uid) throws RemoteException {
+            checkCallerIsSystem();
+
+            // Cancel posted notifications
+            cancelAllNotificationsInt(MY_UID, MY_PID, packageName, null, 0, 0, true,
+                    UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
+
+            // Listener & assistant
+            mListeners.onPackagesChanged(true, new String[] {packageName});
+            mNotificationAssistants.onPackagesChanged(true, new String[] {packageName});
+
+            // Zen
+            mConditionProviders.onPackagesChanged(true, new String[] {packageName});
+
+            // Reset notification preferences
+            mRankingHelper.onPackagesChanged(true, UserHandle.getCallingUserId(),
+                    new String[] {packageName}, new int[] {uid});
+
+            savePolicyFile();
+        }
+
+
         /**
          * System-only API for getting a list of current (i.e. not cleared) notifications.
          *
@@ -2475,7 +2506,7 @@
                 INotificationListener token, String pkg) throws RemoteException {
             ManagedServiceInfo info = mNotificationAssistants.checkServiceTokenLocked(token);
             int uid = mPackageManager.getPackageUid(pkg, 0, info.userid);
-            return mRankingHelper.getNotificationChannels(pkg, uid);
+            return mRankingHelper.getNotificationChannels(pkg, uid, false /* includeDeleted */);
         }
     };
 
@@ -2493,7 +2524,8 @@
                     adjustment.getSignals().getParcelableArrayList(Adjustment.KEY_SNOOZE_CRITERIA);
             if (!TextUtils.isEmpty(overrideChannelId)) {
                 n.setNotificationChannelOverride(mRankingHelper.getNotificationChannel(
-                        n.sbn.getPackageName(), n.sbn.getUid(), overrideChannelId));
+                        n.sbn.getPackageName(), n.sbn.getUid(), overrideChannelId,
+                        false /* includeDeleted */));
             }
             n.setPeopleOverride(people);
             n.setSnoozeCriteria(snoozeCriterionList);
@@ -2846,7 +2878,7 @@
                     + " id=" + id + " notification=" + notification);
         }
         final NotificationChannel channel =  mRankingHelper.getNotificationChannelWithFallback(pkg,
-                callingUid, notification.getChannel());
+                callingUid, notification.getChannel(), false /* includeDeleted */);
         final StatusBarNotification n = new StatusBarNotification(
                 pkg, opPkg, channel, id, tag, callingUid, callingPid, notification,
                 user, null, System.currentTimeMillis());
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 5c1e99c..c2cef09 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -27,8 +27,10 @@
             boolean fromTargetApp);
     void updateNotificationChannel(String pkg, int uid, NotificationChannel channel);
     void updateNotificationChannelFromAssistant(String pkg, int uid, NotificationChannel channel);
-    NotificationChannel getNotificationChannel(String pkg, int uid, String channelId);
-    NotificationChannel getNotificationChannelWithFallback(String pkg, int uid, String channelId);
+    NotificationChannel getNotificationChannel(String pkg, int uid, String channelId, boolean includeDeleted);
+    NotificationChannel getNotificationChannelWithFallback(String pkg, int uid, String channelId, boolean includeDeleted);
     void deleteNotificationChannel(String pkg, int uid, String channelId);
-    ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid);
+    void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId);
+    void permanentlyDeleteNotificationChannels(String pkg, int uid);
+    ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid, boolean includeDeleted);
 }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 3fcce3c..e44fb7f 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -18,6 +18,7 @@
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
 import android.app.Notification;
@@ -29,7 +30,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
 import android.os.Build;
-import android.os.Process;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.text.TextUtils;
@@ -432,9 +432,13 @@
         if (IMPORTANCE_NONE == r.importance) {
             throw new IllegalArgumentException("Package blocked");
         }
-        if (r.channels.containsKey(channel.getId()) || channel.getName().equals(
-                mContext.getString(R.string.default_notification_channel_label))) {
-            // Channel already exists, no-op.
+        NotificationChannel existing = r.channels.get(channel.getId());
+        // Keep existing settings
+        if (existing != null) {
+            if (existing.isDeleted()) {
+                existing.setDeleted(false);
+                updateConfig();
+            }
             return;
         }
         if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE
@@ -471,7 +475,7 @@
             throw new IllegalArgumentException("Invalid package");
         }
         NotificationChannel channel = r.channels.get(updatedChannel.getId());
-        if (channel == null) {
+        if (channel == null || channel.isDeleted()) {
             throw new IllegalArgumentException("Channel does not exist");
         }
         if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
@@ -489,7 +493,7 @@
             throw new IllegalArgumentException("Invalid package");
         }
         NotificationChannel channel = r.channels.get(updatedChannel.getId());
-        if (channel == null) {
+        if (channel == null || channel.isDeleted()) {
             throw new IllegalArgumentException("Channel does not exist");
         }
 
@@ -519,6 +523,9 @@
         if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SHOW_BADGE) == 0) {
             channel.setShowBadge(updatedChannel.canShowBadge());
         }
+        if (updatedChannel.isDeleted()) {
+            updatedChannel.setDeleted(true);
+        }
 
         r.channels.put(channel.getId(), channel);
         updateConfig();
@@ -526,13 +533,13 @@
 
     @Override
     public NotificationChannel getNotificationChannelWithFallback(String pkg, int uid,
-            String channelId) {
+            String channelId, boolean includeDeleted) {
         Record r = getOrCreateRecord(pkg, uid);
         if (channelId == null) {
             channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
         }
         NotificationChannel channel = r.channels.get(channelId);
-        if (channel != null) {
+        if (channel != null && (includeDeleted || !channel.isDeleted())) {
             return channel;
         } else {
             return r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID);
@@ -540,16 +547,21 @@
     }
 
     @Override
-    public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId) {
+    public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId,
+            boolean includeDeleted) {
         Preconditions.checkNotNull(pkg);
         Record r = getOrCreateRecord(pkg, uid);
         if (r == null) {
-            throw new IllegalArgumentException("Invalid package");
+            return null;
         }
         if (channelId == null) {
             channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
         }
-        return r.channels.get(channelId);
+        final NotificationChannel nc = r.channels.get(channelId);
+        if (nc != null && (includeDeleted || !nc.isDeleted())) {
+            return nc;
+        }
+        return null;
     }
 
     @Override
@@ -558,24 +570,57 @@
         Preconditions.checkNotNull(channelId);
         Record r = getRecord(pkg, uid);
         if (r == null) {
-            throw new IllegalArgumentException("Invalid package");
+            return;
         }
-        if (r != null) {
-            r.channels.remove(channelId);
+        NotificationChannel channel = r.channels.get(channelId);
+        if (channel != null) {
+            channel.setDeleted(true);
         }
     }
 
     @Override
-    public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid) {
+    @VisibleForTesting
+    public void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId) {
+        Preconditions.checkNotNull(pkg);
+        Preconditions.checkNotNull(channelId);
+        Record r = getRecord(pkg, uid);
+        if (r == null) {
+            return;
+        }
+        r.channels.remove(channelId);
+    }
+
+    @Override
+    public void permanentlyDeleteNotificationChannels(String pkg, int uid) {
+        Preconditions.checkNotNull(pkg);
+        Record r = getRecord(pkg, uid);
+        if (r == null) {
+            return;
+        }
+        int N = r.channels.size() - 1;
+        for (int i = N; i >= 0; i--) {
+            String key = r.channels.keyAt(i);
+            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(key)) {
+                r.channels.remove(key);
+            }
+        }
+    }
+
+    @Override
+    public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
+            boolean includeDeleted) {
         Preconditions.checkNotNull(pkg);
         List<NotificationChannel> channels = new ArrayList<>();
         Record r = getRecord(pkg, uid);
         if (r == null) {
-            throw new IllegalArgumentException("Invalid package");
+            return ParceledListSlice.emptyList();
         }
         int N = r.channels.size();
         for (int i = 0; i < N; i++) {
-            channels.add(r.channels.valueAt(i));
+            final NotificationChannel nc = r.channels.valueAt(i);
+            if (includeDeleted || !nc.isDeleted()) {
+                channels.add(nc);
+            }
         }
         return new ParceledListSlice<>(channels);
     }
@@ -738,30 +783,46 @@
         return packageBans;
     }
 
-    public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList) {
-        if (removingPackage || pkgList == null || pkgList.length == 0) {
+    public void onPackagesChanged(boolean removingPackage, int changeUserId, String[] pkgList,
+            int[] uidList) {
+        if (pkgList == null || pkgList.length == 0) {
             return; // nothing to do
         }
         boolean updated = false;
-        for (String pkg : pkgList) {
-            final Record r = mRestoredWithoutUids.get(pkg);
-            if (r != null) {
+        if (removingPackage) {
+            // Remove notification settings for uninstalled package
+            int size = Math.min(pkgList.length, uidList.length);
+            for (int i = 0; i < size; i++) {
+                final String pkg = pkgList[i];
+                final int uid = uidList[i];
+                mRecords.remove(recordKey(pkg, uid));
+                mRestoredWithoutUids.remove(pkg);
+                updated = true;
+            }
+        } else {
+            for (String pkg : pkgList) {
+                // Package install
+                final Record r = mRestoredWithoutUids.get(pkg);
+                if (r != null) {
+                    try {
+                        r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
+                        mRestoredWithoutUids.remove(pkg);
+                        mRecords.put(recordKey(r.pkg, r.uid), r);
+                        updated = true;
+                    } catch (NameNotFoundException e) {
+                        // noop
+                    }
+                }
+                // Package upgrade
                 try {
-                    r.uid = mPm.getPackageUidAsUser(r.pkg, changeUserId);
-                    mRestoredWithoutUids.remove(pkg);
-                    mRecords.put(recordKey(r.pkg, r.uid), r);
-                    updated = true;
+                    Record fullRecord = getRecord(pkg,
+                            mPm.getPackageUidAsUser(pkg, changeUserId));
+                    if (fullRecord != null) {
+                        clampDefaultChannel(fullRecord);
+                    }
                 } catch (NameNotFoundException e) {
-                    // noop
                 }
             }
-            try {
-                Record fullRecord = getRecord(pkg,
-                        mPm.getPackageUidAsUser(pkg, changeUserId));
-                if (fullRecord != null) {
-                    clampDefaultChannel(fullRecord);
-                }
-            } catch (NameNotFoundException e) {}
         }
 
         if (updated) {
diff --git a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
index 1e3e0ca..e8be629 100644
--- a/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
+++ b/services/core/java/com/android/server/pm/EphemeralApplicationRegistry.java
@@ -17,6 +17,7 @@
 package com.android.server.pm;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.EphemeralApplicationInfo;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
@@ -27,10 +28,13 @@
 import android.graphics.drawable.Drawable;
 import android.os.Binder;
 import android.os.Environment;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
 import android.util.Xml;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
@@ -51,6 +55,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -62,7 +67,7 @@
 class EphemeralApplicationRegistry {
     private static final boolean DEBUG = false;
 
-    private static final boolean ENABLED = false;
+    private static final boolean ENABLED = true;
 
     private static final String LOG_TAG = "EphemeralAppRegistry";
 
@@ -90,6 +95,16 @@
     @GuardedBy("mService.mPackages")
     private SparseArray<List<UninstalledEphemeralAppState>> mUninstalledEphemeralApps;
 
+    /**
+     * Automatic grants for access to instant app metadata.
+     * The key is the target application UID.
+     * The value is a set of instant app UIDs.
+     * UserID -> TargetAppId -> InstantAppId
+     */
+    private SparseArray<SparseArray<SparseBooleanArray>> mEphemeralGrants;
+    /** The set of all installed instant apps. UserID -> AppID */
+    private SparseArray<SparseBooleanArray> mInstalledEphemeralAppUids;
+
     public EphemeralApplicationRegistry(PackageManagerService service) {
         mService = service;
     }
@@ -189,6 +204,9 @@
 
             // Propagate permissions before removing any state
             propagateEphemeralAppPermissionsIfNeeded(pkg, userId);
+            if (pkg.applicationInfo.isEphemeralApp()) {
+                addEphemeralAppLPw(userId, ps.appId);
+            }
 
             // Remove the in-memory state
             if (mUninstalledEphemeralApps != null) {
@@ -248,9 +266,11 @@
             if (pkg.applicationInfo.isEphemeralApp()) {
                 // Add a record for an uninstalled ephemeral app
                 addUninstalledEphemeralAppLPw(pkg, userId);
+                removeEphemeralAppLPw(userId, ps.appId);
             } else {
                 // Deleting an app prunes all ephemeral state such as cookie
                 deleteDir(getEphemeralApplicationDir(pkg.packageName, userId));
+                removeAppLPw(userId, ps.appId);
             }
         }
     }
@@ -262,9 +282,114 @@
         if (mUninstalledEphemeralApps != null) {
             mUninstalledEphemeralApps.remove(userId);
         }
+        if (mInstalledEphemeralAppUids != null) {
+            mInstalledEphemeralAppUids.remove(userId);
+        }
+        if (mEphemeralGrants != null) {
+            mEphemeralGrants.remove(userId);
+        }
         deleteDir(getEphemeralApplicationsDir(userId));
     }
 
+    public boolean isEphemeralAccessGranted(int userId, int targetAppId, int ephemeralAppId) {
+        if (mEphemeralGrants == null) {
+            return false;
+        }
+        final SparseArray<SparseBooleanArray> targetAppList = mEphemeralGrants.get(userId);
+        if (targetAppList == null) {
+            return false;
+        }
+        final SparseBooleanArray ephemeralGrantList = targetAppList.get(targetAppId);
+        if (ephemeralGrantList == null) {
+            return false;
+        }
+        return ephemeralGrantList.get(ephemeralAppId);
+    }
+
+    public void grantEphemeralAccessLPw(int userId, Intent intent,
+            int targetAppId, int ephemeralAppId) {
+        if (mInstalledEphemeralAppUids == null) {
+            return;     // no ephemeral apps installed; no need to grant
+        }
+        SparseBooleanArray ephemeralAppList = mInstalledEphemeralAppUids.get(userId);
+        if (ephemeralAppList == null || !ephemeralAppList.get(ephemeralAppId)) {
+            return;     // ephemeral app id isn't installed; no need to grant
+        }
+        if (ephemeralAppList.get(targetAppId)) {
+            return;     // target app id is an ephemeral app; no need to grant
+        }
+        if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
+            final Set<String> categories = intent.getCategories();
+            if (categories != null && categories.contains(Intent.CATEGORY_BROWSABLE)) {
+                return;  // launched via VIEW/BROWSABLE intent; no need to grant
+            }
+        }
+        if (mEphemeralGrants == null) {
+            mEphemeralGrants = new SparseArray<>();
+        }
+        SparseArray<SparseBooleanArray> targetAppList = mEphemeralGrants.get(userId);
+        if (targetAppList == null) {
+            targetAppList = new SparseArray<>();
+            mEphemeralGrants.put(userId, targetAppList);
+        }
+        SparseBooleanArray ephemeralGrantList = targetAppList.get(targetAppId);
+        if (ephemeralGrantList == null) {
+            ephemeralGrantList = new SparseBooleanArray();
+            targetAppList.put(targetAppId, ephemeralGrantList);
+        }
+        ephemeralGrantList.put(ephemeralAppId, true /*granted*/);
+    }
+
+    public void addEphemeralAppLPw(int userId, int ephemeralAppId) {
+        if (mInstalledEphemeralAppUids == null) {
+            mInstalledEphemeralAppUids = new SparseArray<>();
+        }
+        SparseBooleanArray ephemeralAppList = mInstalledEphemeralAppUids.get(userId);
+        if (ephemeralAppList == null) {
+            ephemeralAppList = new SparseBooleanArray();
+            mInstalledEphemeralAppUids.put(userId, ephemeralAppList);
+        }
+        ephemeralAppList.put(ephemeralAppId, true /*installed*/);
+    }
+
+    private void removeEphemeralAppLPw(int userId, int ephemeralAppId) {
+        // remove from the installed list
+        if (mInstalledEphemeralAppUids == null) {
+            return; // no ephemeral apps on the system
+        }
+        final SparseBooleanArray ephemeralAppList = mInstalledEphemeralAppUids.get(userId);
+        if (ephemeralAppList == null) {
+            Slog.w(LOG_TAG, "Remove ephemeral not in install list");
+            return;
+        } else {
+            ephemeralAppList.delete(ephemeralAppId);
+        }
+        // remove any grants
+        if (mEphemeralGrants == null) {
+            return; // no grants on the system
+        }
+        final SparseArray<SparseBooleanArray> targetAppList = mEphemeralGrants.get(userId);
+        if (targetAppList == null) {
+            return; // no grants for this user
+        }
+        final int numApps = targetAppList.size();
+        for (int i = targetAppList.size() - 1; i >= 0; --i) {
+            targetAppList.valueAt(i).delete(ephemeralAppId);
+        }
+    }
+
+    private void removeAppLPw(int userId, int targetAppId) {
+        // remove from the installed list
+        if (mEphemeralGrants == null) {
+            return; // no grants on the system
+        }
+        final SparseArray<SparseBooleanArray> targetAppList = mEphemeralGrants.get(userId);
+        if (targetAppList == null) {
+            return; // no grants for this user
+        }
+        targetAppList.delete(targetAppId);
+    }
+
     private void addUninstalledEphemeralAppLPw(PackageParser.Package pkg, int userId) {
         EphemeralApplicationInfo uninstalledApp = createEphemeralAppInfoForPackage(pkg, userId);
         if (uninstalledApp == null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6669889..e3fa0c4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -68,6 +68,7 @@
 import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES;
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
+import static android.content.pm.PackageManager.MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL;
 import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN;
 import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
 import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR;
@@ -80,7 +81,6 @@
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDWR;
-
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
 import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
@@ -2224,6 +2224,7 @@
             Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
 
             mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this);
+            mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this);
 
             File dataDir = Environment.getDataDirectory();
             mAppInstallDir = new File(dataDir, "app");
@@ -2806,8 +2807,6 @@
                 setUpEphemeralInstallerActivityLP(mEphemeralInstallerComponent);
             }
 
-            mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this);
-
             // Read and update the usage of dex files.
             // Do this at the end of PM init so that all the packages have their
             // data directory reconciled.
@@ -3257,6 +3256,31 @@
         if (p == null) {
             return null;
         }
+        // Filter out ephemeral app metadata:
+        //   * The system/shell/root can see metadata for any app
+        //   * An installed app can see metadata for 1) other installed apps
+        //     and 2) ephemeral apps that have explicitly interacted with it
+        //   * Ephemeral apps can only see their own metadata
+        final int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
+        if (callingAppId != Process.SYSTEM_UID
+                && callingAppId != Process.SHELL_UID
+                && callingAppId != Process.ROOT_UID) {
+            final String ephemeralPackageName = getEphemeralPackageName(Binder.getCallingUid());
+            if (ephemeralPackageName != null) {
+                // ephemeral apps can only get information on themselves
+                if (!ephemeralPackageName.equals(p.packageName)) {
+                    return null;
+                }
+            } else {
+                if (p.applicationInfo.isEphemeralApp()) {
+                    // only get access to the ephemeral app if we've been granted access
+                    if (!mEphemeralApplicationRegistry.isEphemeralAccessGranted(
+                            userId, callingAppId, ps.appId)) {
+                        return null;
+                    }
+                }
+            }
+        }
 
         final PermissionsState permissionsState = ps.getPermissionsState();
 
@@ -3336,22 +3360,19 @@
 
         // reader
         synchronized (mPackages) {
-            // Normalize package name to hanlde renamed packages
+            // Normalize package name to handle renamed packages
             packageName = normalizePackageNameLPr(packageName);
 
             final boolean matchFactoryOnly = (flags & MATCH_FACTORY_ONLY) != 0;
-            PackageParser.Package p = null;
             if (matchFactoryOnly) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 if (ps != null) {
                     return generatePackageInfo(ps, flags, userId);
                 }
             }
-            if (p == null) {
-                p = mPackages.get(packageName);
-                if (matchFactoryOnly && p != null && !isSystemApp(p)) {
-                    return null;
-                }
+            PackageParser.Package p = mPackages.get(packageName);
+            if (matchFactoryOnly && p != null && !isSystemApp(p)) {
+                return null;
             }
             if (DEBUG_PACKAGE_INFO)
                 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
@@ -3745,6 +3766,19 @@
     }
 
     /**
+     * Update given intent when being used to request {@link ResolveInfo}.
+     */
+    private Intent updateIntentForResolve(Intent intent) {
+        if (intent.getSelector() != null) {
+            intent = intent.getSelector();
+        }
+        if (DEBUG_PREFERRED) {
+            intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
+        }
+        return intent;
+    }
+
+    /**
      * Update given flags when being used to request {@link ResolveInfo}.
      */
     int updateFlagsForResolve(int flags, int userId, Object cookie) {
@@ -5128,6 +5162,26 @@
     }
 
     @Override
+    public ResolveInfo findPersistentPreferredActivity(Intent intent, int userId) {
+        if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.SYSTEM_UID)) {
+            throw new SecurityException(
+                    "findPersistentPreferredActivity can only be run by the system");
+        }
+        if (!sUserManager.exists(userId)) {
+            return null;
+        }
+        intent = updateIntentForResolve(intent);
+        final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
+        final int flags = updateFlagsForResolve(0, userId, intent);
+        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
+                userId);
+        synchronized (mPackages) {
+            return findPersistentPreferredActivityLP(intent, resolvedType, flags, query, false,
+                    userId);
+        }
+    }
+
+    @Override
     public void setLastChosenActivity(Intent intent, String resolvedType, int flags,
             IntentFilter filter, int match, ComponentName activity) {
         final int userId = UserHandle.getCallingUserId();
@@ -5393,13 +5447,9 @@
             boolean removeMatches, boolean debug, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForResolve(flags, userId, intent);
+        intent = updateIntentForResolve(intent);
         // writer
         synchronized (mPackages) {
-            if (intent.getSelector() != null) {
-                intent = intent.getSelector();
-            }
-            if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
-
             // Try to find a matching persistent preferred activity.
             ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query,
                     debug, userId);
@@ -5965,7 +6015,7 @@
                     int status = (int)(packedStatus >> 32);
                     int linkGeneration = (int)(packedStatus & 0xFFFFFFFF);
                     if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
-                        if (DEBUG_DOMAIN_VERIFICATION) {
+                        if (DEBUG_DOMAIN_VERIFICATION || debug) {
                             Slog.i(TAG, "  + always: " + info.activityInfo.packageName
                                     + " : linkgen=" + linkGeneration);
                         }
@@ -5974,18 +6024,18 @@
                         info.preferredOrder = linkGeneration;
                         alwaysList.add(info);
                     } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
-                        if (DEBUG_DOMAIN_VERIFICATION) {
+                        if (DEBUG_DOMAIN_VERIFICATION || debug) {
                             Slog.i(TAG, "  + never: " + info.activityInfo.packageName);
                         }
                         neverList.add(info);
                     } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
-                        if (DEBUG_DOMAIN_VERIFICATION) {
+                        if (DEBUG_DOMAIN_VERIFICATION || debug) {
                             Slog.i(TAG, "  + always-ask: " + info.activityInfo.packageName);
                         }
                         alwaysAskList.add(info);
                     } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED ||
                             status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK) {
-                        if (DEBUG_DOMAIN_VERIFICATION) {
+                        if (DEBUG_DOMAIN_VERIFICATION || debug) {
                             Slog.i(TAG, "  + ask: " + info.activityInfo.packageName);
                         }
                         undefinedList.add(info);
@@ -8839,6 +8889,10 @@
             // Modify state for the given package setting
             commitPackageSettings(pkg, pkgSetting, user, scanFlags,
                     (policyFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
+            if (isEphemeral(pkg)) {
+                final int userId = user == null ? 0 : user.getIdentifier();
+                mEphemeralApplicationRegistry.addEphemeralAppLPw(userId, pkgSetting.appId);
+            }
         }
         return pkg;
     }
@@ -12143,7 +12197,7 @@
         IActivityManager am = ActivityManager.getService();
         if (am != null) {
             try {
-                am.startService(null, intent, null, mContext.getOpPackageName(),
+                am.startService(null, intent, null, -1, null, mContext.getOpPackageName(),
                         UserHandle.USER_SYSTEM);
             } catch (RemoteException e) {
             }
@@ -16627,7 +16681,8 @@
                         extras, 0, null, null, removedUsers);
                 if (dataRemoved && !isRemovedPackageSystemUpdate) {
                     sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
-                            removedPackage, extras, 0, null, null, removedUsers);
+                            removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
+                            null, null, removedUsers);
                 }
             }
             if (removedAppId >= 0) {
@@ -19581,7 +19636,8 @@
                             count = 0;
                             for (PackageSetting ps : allPackageSettings) {
                                 final long status = ps.getDomainVerificationStatusForUser(userId);
-                                if (status >> 32 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) {
+                                if (status >> 32 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED
+                                        && !DEBUG_DOMAIN_VERIFICATION) {
                                     continue;
                                 }
                                 pw.println(prefix + "Package: " + ps.name);
@@ -21042,6 +21098,14 @@
                         "Cannot move system application");
             }
 
+            final boolean isInternalStorage = VolumeInfo.ID_PRIVATE_INTERNAL.equals(volumeUuid);
+            final boolean allow3rdPartyOnInternal = mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_allow3rdPartyAppOnInternal);
+            if (isInternalStorage && !allow3rdPartyOnInternal) {
+                throw new PackageManagerException(MOVE_FAILED_3RD_PARTY_NOT_ALLOWED_ON_INTERNAL,
+                        "3rd party apps are not allowed on internal storage");
+            }
+
             if (pkg.applicationInfo.isExternalAsec()) {
                 currentAsec = true;
                 currentVolumeUuid = StorageManager.UUID_PRIMARY_PHYSICAL;
@@ -21924,6 +21988,15 @@
                     responseObj, origIntent, resolvedType, launchIntent, callingPackage, userId);
         }
 
+        @Override
+        public void grantEphemeralAccess(int userId, Intent intent,
+                int targetAppId, int ephemeralAppId) {
+            synchronized (mPackages) {
+                mEphemeralApplicationRegistry.grantEphemeralAccessLPw(userId, intent,
+                        targetAppId, ephemeralAppId);
+            }
+        }
+
         public String getSetupWizardPackageName() {
             return mSetupWizardPackage;
         }
diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
index a156356..6e96726 100644
--- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -203,19 +203,13 @@
         // Next, validate the incoming shortcut, etc.
         final PinItemRequest request;
         if (inShortcut != null) {
-            request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity,
-                    true /* ignoreIfAlreadyPinned */);
+            request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity);
         } else {
             int launcherUid = mService.injectGetPackageUid(
                     confirmActivity.first.getPackageName(), launcherUserId);
             request = new PinItemRequest(inAppWidget,
                     new PinItemRequestInner(this, resultIntent, launcherUid));
         }
-
-        if (request == null) {
-            sendResultIntent(resultIntent, null);
-            return true;
-        }
         return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request);
     }
 
@@ -238,23 +232,17 @@
         mService.throwIfUserLockedL(launcherUserId);
 
         // Next, validate the incoming shortcut, etc.
-        PinItemRequest request = requestPinShortcutLocked(inShortcut, null,
-                Pair.create(defaultLauncher, launcherUserId), false /* ignoreIfAlreadyPinned */);
-        if (request == null) {
-            return null;
-        }
+        final PinItemRequest request = requestPinShortcutLocked(inShortcut, null,
+                Pair.create(defaultLauncher, launcherUserId));
         return new Intent().putExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST, request);
     }
 
     /**
      * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)}.
-     *
-     * @param ignoreIfAlreadyPinned if true and the {@param inShortcut} is already pinned for
-     *                              {@param confirmActivity}, null is returned instead.
      */
+    @NonNull
     private PinItemRequest requestPinShortcutLocked(ShortcutInfo inShortcut,
-            IntentSender resultIntent, Pair<ComponentName, Integer> confirmActivity,
-            boolean ignoreIfAlreadyPinned) {
+            IntentSender resultIntentOriginal, Pair<ComponentName, Integer> confirmActivity) {
         final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked(
                 inShortcut.getPackage(), inShortcut.getUserId());
 
@@ -272,16 +260,20 @@
         final String launcherPackage = confirmActivity.first.getPackageName();
         final int launcherUserId = confirmActivity.second;
 
+        IntentSender resultIntentToSend = resultIntentOriginal;
+
         if (existsAlready) {
             validateExistingShortcut(existing);
 
             final boolean isAlreadyPinned = mService.getLauncherShortcutsLocked(
                     launcherPackage, existing.getUserId(), launcherUserId).hasPinned(existing);
-            // See if it's already pinned.
-            if (ignoreIfAlreadyPinned && isAlreadyPinned) {
-                Log.i(TAG, "Launcher's already pinning shortcut " + existing.getId()
-                        + " for package " + existing.getPackage());
-                return null;
+            if (isAlreadyPinned) {
+                // When the shortcut is already pinned by this launcher, the request will always
+                // succeed, so just send the result at this point.
+                sendResultIntent(resultIntentOriginal, null);
+
+                // So, do not send the intent again.
+                resultIntentToSend = null;
             }
 
             // Pass a clone, not the original.
@@ -289,7 +281,7 @@
             shortcutForLauncher = existing.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
 
             if (!isAlreadyPinned) {
-                // FLAG_PINNED is still set, if it's pinned by other launchers.
+                // FLAG_PINNED may still be set, if it's pinned by other launchers.
                 shortcutForLauncher.clearFlags(ShortcutInfo.FLAG_PINNED);
             }
         } else {
@@ -320,8 +312,8 @@
 
         // Create a request object.
         final PinShortcutRequestInner inner =
-                new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, resultIntent,
-                        launcherPackage, launcherUserId,
+                new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher,
+                        resultIntentToSend, launcherPackage, launcherUserId,
                         mService.injectGetPackageUid(launcherPackage, launcherUserId),
                         existsAlready);
 
@@ -410,6 +402,16 @@
                 return false;
             }
 
+            final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked(
+                    launcherPackage, appUserId, launcherUserId);
+            launcher.attemptToRestoreIfNeededAndSave();
+            if (launcher.hasPinned(original)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Shortcut " + original + " already pinned.");
+                }
+                return true;
+            }
+
             final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked(
                     appPackageName, appUserId);
             final ShortcutInfo current = ps.findShortcutById(shortcutId);
@@ -447,9 +449,6 @@
                 Slog.d(TAG, "Pinning " + shortcutId);
             }
 
-            final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked(
-                    launcherPackage, appUserId, launcherUserId);
-            launcher.attemptToRestoreIfNeededAndSave();
             launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId);
 
             if (current == null) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e646ffc..1eb8b94 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1567,7 +1567,7 @@
         }
         synchronized(mUsersLock) {
             UserInfo userInfo = getUserInfoLU(userId);
-            if (!userInfo.canHaveProfile()) {
+            if (userInfo == null || !userInfo.canHaveProfile()) {
                 return false;
             }
             int usersCountAfterRemoving = getAliveUsersExcludingGuestsCountLU()
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index 90c711a..a3837b2 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -338,9 +338,11 @@
         mTotalMemory = (long)mDataFileStats.getBlockCount() *
                         mDataFileStats.getBlockSize();
         mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
-        mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
-        mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL);
         mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
         mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
diff --git a/services/core/java/com/android/server/vr/CompatibilityDisplay.java b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
new file mode 100644
index 0000000..15edaaf
--- /dev/null
+++ b/services/core/java/com/android/server/vr/CompatibilityDisplay.java
@@ -0,0 +1,119 @@
+
+package com.android.server.vr;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.vr.IVrStateCallbacks;
+import android.service.vr.IVrManager;
+import android.util.Log;
+
+import com.android.server.vr.VrManagerService;
+
+/**
+ * Creates a 2D Virtual Display while VR Mode is enabled. This display will be used to run and
+ * render 2D app within a VR experience. For example, bringing up the 2D calculator app in VR.
+ */
+class CompatibilityDisplay {
+    private final static String TAG = "CompatDisplay";
+    private final static boolean DEBUG = false;
+
+    // TODO: Go over these values and figure out what is best
+    private final static int HEIGHT = 960;
+    private final static int WIDTH = 720;
+    private final static int DPI = 320;
+
+    private final DisplayManager mDisplayManager;
+    private final IVrManager mVrManager;
+
+    // TODO: Lock initially created when VrStateCallback was connected through Binder. This may not
+    // be necessary with the direct access to VrManager.
+    private final Object vdLock = new Object();
+
+    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
+        @Override
+        public void onVrStateChanged(boolean enabled) {
+            if (enabled != mIsVrModeEnabled) {
+                mIsVrModeEnabled = enabled;
+                if (enabled) {
+                    // TODO: Consider not creating the display until ActivityManager needs one on
+                    // which to display a 2D application.
+                    startVirtualDisplay();
+                } else {
+                    stopVirtualDisplay();
+                }
+            }
+        }
+    };
+
+    private VirtualDisplay mVirtualDisplay;
+    private boolean mIsVrModeEnabled;
+
+    public CompatibilityDisplay(DisplayManager displayManager, IVrManager vrManager) {
+        mDisplayManager = displayManager;
+        mVrManager = vrManager;
+    }
+
+    /**
+     * Initializes the compabilitiy display by listening to VR mode changes.
+     */
+    public void init() {
+        startVrModeListener();
+    }
+
+    private void startVrModeListener() {
+        if (mVrManager != null) {
+            try {
+                mVrManager.registerListener(mVrStateCallbacks);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Could not register VR State listener.", e);
+            }
+        }
+    }
+
+    private void startVirtualDisplay() {
+        if (DEBUG) {
+            Log.d(TAG, "Starting VD, DM:" + mDisplayManager);
+        }
+
+        if (mDisplayManager == null) {
+            Log.w(TAG, "Cannot create virtual display because mDisplayManager == null");
+            return;
+        }
+
+        synchronized (vdLock) {
+            if (mVirtualDisplay != null) {
+                Log.e(TAG, "Starting the virtual display when one already exists", new Exception());
+                return;
+            }
+
+            mVirtualDisplay = mDisplayManager.createVirtualDisplay("VR 2D Display", WIDTH, HEIGHT,
+                    DPI,
+                    null /* Surface */, 0 /* flags */);
+        }
+
+        if (DEBUG) {
+            Log.d(TAG, "VD created: " + mVirtualDisplay);
+        }
+    }
+
+    private void stopVirtualDisplay() {
+        if (DEBUG) {
+            Log.i(TAG, "Santos, stopping VD");
+        }
+
+        synchronized (vdLock) {
+            if (mVirtualDisplay != null) {
+                mVirtualDisplay.release();
+                mVirtualDisplay = null;
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 84cf0c6..57587b0 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.hardware.display.DisplayManager;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -51,6 +52,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
+
 import com.android.internal.R;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
@@ -136,6 +138,7 @@
     private final NotificationAccessManager mNotifAccessManager = new NotificationAccessManager();
     /** Tracks the state of the screen and keyguard UI.*/
     private int mSystemSleepFlags = FLAG_NONE;
+    private CompatibilityDisplay mCompatibilityDisplay;
 
     private static final int MSG_VR_STATE_CHANGE = 0;
     private static final int MSG_PENDING_VR_STATE_CHANGE = 1;
@@ -493,6 +496,11 @@
 
                 mComponentObserver.rebuildAll();
             }
+
+            DisplayManager dm =
+                    (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
+            mCompatibilityDisplay = new CompatibilityDisplay(dm, mVrManager);
+            mCompatibilityDisplay.init();
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mLock) {
                 mVrModeAllowed = true;
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
index b99dda1..015c084 100644
--- a/services/core/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -77,6 +77,8 @@
         boolean dimFullscreen();
         /** Returns the display info. of the dim layer user. */
         DisplayInfo getDisplayInfo();
+        /** Returns true if the dim layer user is currently attached to a display */
+        boolean isAttachedToDisplay();
         /** Gets the bounds of the dim layer user. */
         void getDimBounds(Rect outBounds);
         String toShortString();
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 04ae72f..2ec2dba 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -191,8 +191,21 @@
         boolean result = false;
 
         for (int i = mState.size() - 1; i >= 0; i--) {
-            DimLayer.DimLayerUser user = mState.keyAt(i);
-            DimLayerState state = mState.valueAt(i);
+            final DimLayer.DimLayerUser user = mState.keyAt(i);
+            final DimLayerState state = mState.valueAt(i);
+
+            if (!user.isAttachedToDisplay()) {
+                // Leaked dim user that is no longer attached to the display. Go ahead and clean it
+                // clean-up and log what happened.
+                // TODO: This is a work around for b/34395537 as the dim user should have cleaned-up
+                // it self when it was detached from the display. Need to investigate how the dim
+                // user is leaking...
+                Slog.wtfStack(TAG_WM, "Leaked dim user=" + user.toShortString()
+                        + " state=" + state);
+                removeDimLayerUser(user);
+                continue;
+            }
+
             // We have to check that we are actually the shared fullscreen layer
             // for this path. If we began as non fullscreen and became fullscreen
             // (e.g. Docked stack closing), then we may not be the shared layer
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index e6bc7f4..ed1e2d9 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -835,6 +835,11 @@
     }
 
     @Override
+    public boolean isAttachedToDisplay() {
+        return mDisplayContent != null;
+    }
+
+    @Override
     public void getDimBounds(Rect outBounds) {
         // This dim layer user doesn't need this.
     }
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 34633c2..bfb4269 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -82,6 +82,7 @@
 
     // Used to calculate stack bounds across rotations
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
+    private final Rect mStableInsets = new Rect();
 
     // The size and position information that describes where the pinned stack will go by default.
     private int mDefaultStackGravity;
@@ -250,10 +251,12 @@
     }
 
     /**
-     * @return the repositioned PIP bounds given it's pre-change bounds, and the new display info.
+     * @return the repositioned PIP bounds given it's pre-change bounds, and the new display
+     *         content.
      */
-    Rect onDisplayChanged(Rect preChangeStackBounds, DisplayInfo displayInfo) {
+    Rect onDisplayChanged(Rect preChangeStackBounds, DisplayContent displayContent) {
         final Rect postChangeStackBounds = new Rect(preChangeStackBounds);
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
         if (!mDisplayInfo.equals(displayInfo)) {
             // Calculate the snap fraction of the current stack along the old movement bounds, and
             // then update the stack bounds to the same fraction along the rotated movement bounds.
@@ -269,8 +272,9 @@
             if (mIsMinimized) {
                 final Point displaySize = new Point(mDisplayInfo.logicalWidth,
                         mDisplayInfo.logicalHeight);
+                mService.getStableInsetsLocked(displayContent.getDisplayId(), mStableInsets);
                 mSnapAlgorithm.applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds,
-                        displaySize);
+                        displaySize, mStableInsets);
             }
         }
         return postChangeStackBounds;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 824d460..680d0f2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -628,7 +628,12 @@
 
     @Override
     public DisplayInfo getDisplayInfo() {
-        return mStack.getDisplayContent().getDisplayInfo();
+        return getDisplayContent().getDisplayInfo();
+    }
+
+    @Override
+    public boolean isAttachedToDisplay() {
+        return getDisplayContent() != null;
     }
 
     void forceWindowsScaleable(boolean force) {
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 267566b..7bc577e 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -693,6 +693,11 @@
     }
 
     @Override
+    public boolean isAttachedToDisplay() {
+        return mTask != null && mTask.getDisplayContent() != null;
+    }
+
+    @Override
     public void getDimBounds(Rect out) {
         // This dim layer user doesn't need this.
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index df8679d..10ecf3b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -22,11 +22,13 @@
 import android.app.ActivityManager.StackId;
 import android.app.ActivityManager.TaskSnapshot;
 import android.graphics.GraphicBuffer;
+import android.os.Environment;
 import android.util.ArraySet;
 import android.view.WindowManagerPolicy.StartingSurface;
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.io.File;
 import java.io.PrintWriter;
 
 /**
@@ -45,14 +47,21 @@
 class TaskSnapshotController {
 
     private final WindowManagerService mService;
-    private final TaskSnapshotCache mCache = new TaskSnapshotCache();
 
+    private final TaskSnapshotCache mCache = new TaskSnapshotCache();
+    private final TaskSnapshotPersister mPersister = new TaskSnapshotPersister(
+            Environment::getDataSystemCeDirectory);
+    private final TaskSnapshotLoader mLoader = new TaskSnapshotLoader(mPersister);
     private final ArraySet<Task> mTmpTasks = new ArraySet<>();
 
     TaskSnapshotController(WindowManagerService service) {
         mService = service;
     }
 
+    void systemReady() {
+        mPersister.start();
+    }
+
     void onTransitionStarting() {
         if (!ENABLE_TASK_SNAPSHOTS) {
             return;
@@ -69,6 +78,7 @@
             final TaskSnapshot snapshot = snapshotTask(task);
             if (snapshot != null) {
                 mCache.putSnapshot(task, snapshot);
+                mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
                 if (task.getController() != null) {
                     task.getController().reportSnapshotChanged(snapshot);
                 }
@@ -141,6 +151,17 @@
         mCache.cleanCache(wtoken);
     }
 
+    void notifyTaskRemovedFromRecents(int taskId, int userId) {
+        mPersister.onTaskRemovedFromRecents(taskId, userId);
+    }
+
+    /**
+     * See {@link TaskSnapshotPersister#removeObsoleteFiles}
+     */
+    void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) {
+        mPersister.removeObsoleteFiles(persistentTaskIds, runningUserIds);
+    }
+
     void dump(PrintWriter pw, String prefix) {
         mCache.dump(pw, prefix);
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
new file mode 100644
index 0000000..4340822
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.app.ActivityManager.TaskSnapshot;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapFactory.Options;
+import android.graphics.GraphicBuffer;
+import android.graphics.Rect;
+import android.util.Slog;
+
+import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+/**
+ * Loads a persisted {@link TaskSnapshot} from disk.
+ * <p>
+ * Do not hold the window manager lock when accessing this class.
+ * <p>
+ * Test class: {@link TaskSnapshotPersisterLoaderTest}
+ */
+class TaskSnapshotLoader {
+
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskSnapshotLoader" : TAG_WM;
+
+    private final TaskSnapshotPersister mPersister;
+
+    TaskSnapshotLoader(TaskSnapshotPersister persister) {
+        mPersister = persister;
+    }
+
+    /**
+     * Loads a task from the disk.
+     * <p>
+     * Do not hold the window manager lock when calling this method, as we directly read data from
+     * disk here, which might be slow.
+     *
+     * @param taskId The id of the task to load.
+     * @param userId The id of the user the task belonged to.
+     * @return The loaded {@link TaskSnapshot} or {@code null} if it couldn't be loaded.
+     */
+    TaskSnapshot loadTask(int taskId, int userId) {
+        final File protoFile = mPersister.getProtoFile(taskId, userId);
+        final File bitmapFile = mPersister.getBitmapFile(taskId, userId);
+        if (!protoFile.exists() || !bitmapFile.exists()) {
+            return null;
+        }
+        try {
+            final byte[] bytes = Files.readAllBytes(protoFile.toPath());
+            final TaskSnapshotProto proto = TaskSnapshotProto.parseFrom(bytes);
+            final Options options = new Options();
+            options.inPreferredConfig = Config.HARDWARE;
+            final Bitmap bitmap = BitmapFactory.decodeFile(bitmapFile.getPath(), options);
+            if (bitmap == null) {
+                Slog.w(TAG, "Failed to load bitmap: " + bitmapFile.getPath());
+                return null;
+            }
+            final GraphicBuffer buffer = bitmap.createGraphicBufferHandle();
+            if (buffer == null) {
+                Slog.w(TAG, "Failed to retrieve gralloc buffer for bitmap: "
+                        + bitmapFile.getPath());
+                return null;
+            }
+            return new TaskSnapshot(buffer, proto.orientation,
+                    new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom));
+        } catch (IOException e) {
+            Slog.w(TAG, "Unable to load task snapshot data for taskId=" + taskId);
+            return null;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
new file mode 100644
index 0000000..3a06c38
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.annotation.TestApi;
+import android.app.ActivityManager.TaskSnapshot;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.os.Process;
+import android.os.SystemClock;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.AtomicFile;
+import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayDeque;
+
+/**
+ * Persists {@link TaskSnapshot}s to disk.
+ * <p>
+ * Test class: {@link TaskSnapshotPersisterLoaderTest}
+ */
+class TaskSnapshotPersister {
+
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskSnapshotPersister" : TAG_WM;
+    private static final String SNAPSHOTS_DIRNAME = "snapshots";
+    private static final long DELAY_MS = 100;
+    private static final String PROTO_EXTENSION = ".proto";
+    private static final String BITMAP_EXTENSION = ".png";
+
+    @GuardedBy("mLock")
+    private final ArrayDeque<WriteQueueItem> mWriteQueue = new ArrayDeque<>();
+    @GuardedBy("mLock")
+    private boolean mQueueIdling;
+    private boolean mStarted;
+    private final Object mLock = new Object();
+    private final DirectoryResolver mDirectoryResolver;
+
+    /**
+     * The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was
+     * called.
+     */
+    @GuardedBy("mLock")
+    private final ArraySet<Integer> mPersistedTaskIdsSinceLastRemoveObsolete = new ArraySet<>();
+
+    TaskSnapshotPersister(DirectoryResolver resolver) {
+        mDirectoryResolver = resolver;
+    }
+
+    /**
+     * Starts persisting.
+     */
+    void start() {
+        if (!mStarted) {
+            mStarted = true;
+            mPersister.start();
+        }
+    }
+
+    /**
+     * Persists a snapshot of a task to disk.
+     *
+     * @param taskId The id of the task that needs to be persisted.
+     * @param userId The id of the user this tasks belongs to.
+     * @param snapshot The snapshot to persist.
+     */
+    void persistSnapshot(int taskId, int userId, TaskSnapshot snapshot) {
+        synchronized (mLock) {
+            mPersistedTaskIdsSinceLastRemoveObsolete.add(taskId);
+            sendToQueueLocked(new StoreWriteQueueItem(taskId, userId, snapshot));
+        }
+    }
+
+    /**
+     * Callend when a task has been removed.
+     *
+     * @param taskId The id of task that has been removed.
+     * @param userId The id of the user the task belonged to.
+     */
+    void onTaskRemovedFromRecents(int taskId, int userId) {
+        synchronized (mLock) {
+            mPersistedTaskIdsSinceLastRemoveObsolete.remove(taskId);
+            sendToQueueLocked(new DeleteWriteQueueItem(taskId, userId));
+        }
+    }
+
+    /**
+     * In case a write/delete operation was lost because the system crashed, this makes sure to
+     * clean up the directory to remove obsolete files.
+     *
+     * @param persistentTaskIds A set of task ids that exist in our in-memory model.
+     * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory
+     *                       model.
+     */
+    void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) {
+        synchronized (mLock) {
+            mPersistedTaskIdsSinceLastRemoveObsolete.clear();
+            sendToQueueLocked(new RemoveObsoleteFilesQueueItem(persistentTaskIds, runningUserIds));
+        }
+    }
+
+    @TestApi
+    void waitForQueueEmpty() {
+        while (true) {
+            synchronized (mLock) {
+                if (mWriteQueue.isEmpty() && mQueueIdling) {
+                    return;
+                }
+            }
+            SystemClock.sleep(100);
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void sendToQueueLocked(WriteQueueItem item) {
+        mWriteQueue.offer(item);
+        mLock.notifyAll();
+    }
+
+    private File getDirectory(int userId) {
+        return new File(mDirectoryResolver.getSystemDirectoryForUser(userId), SNAPSHOTS_DIRNAME);
+    }
+
+    File getProtoFile(int taskId, int userId) {
+        return new File(getDirectory(userId), taskId + PROTO_EXTENSION);
+    }
+
+    File getBitmapFile(int taskId, int userId) {
+        return new File(getDirectory(userId), taskId + BITMAP_EXTENSION);
+    }
+
+    private boolean createDirectory(int userId) {
+        final File dir = getDirectory(userId);
+        return dir.exists() || dir.mkdirs();
+    }
+
+    private void deleteSnapshot(int taskId, int userId) {
+        final File protoFile = getProtoFile(taskId, userId);
+        final File bitmapFile = getBitmapFile(taskId, userId);
+        protoFile.delete();
+        bitmapFile.delete();
+    }
+
+    interface DirectoryResolver {
+        File getSystemDirectoryForUser(int userId);
+    }
+
+    private Thread mPersister = new Thread("TaskSnapshotPersister") {
+        public void run() {
+            android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+            while (true) {
+                WriteQueueItem next;
+                synchronized (mLock) {
+                    next = mWriteQueue.poll();
+                }
+                if (next != null) {
+                    next.write();
+                    SystemClock.sleep(DELAY_MS);
+                }
+                synchronized (mLock) {
+                    if (!mWriteQueue.isEmpty()) {
+                        continue;
+                    }
+                    try {
+                        mQueueIdling = true;
+                        mLock.wait();
+                        mQueueIdling = false;
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+        }
+    };
+
+    private abstract class WriteQueueItem {
+        abstract void write();
+    }
+
+    private class StoreWriteQueueItem extends WriteQueueItem {
+        private final int mTaskId;
+        private final int mUserId;
+        private final TaskSnapshot mSnapshot;
+
+        StoreWriteQueueItem(int taskId, int userId, TaskSnapshot snapshot) {
+            mTaskId = taskId;
+            mUserId = userId;
+            mSnapshot = snapshot;
+        }
+
+        @Override
+        void write() {
+            if (!createDirectory(mUserId)) {
+                Slog.e(TAG, "Unable to create snapshot directory for user dir="
+                        + getDirectory(mUserId));
+            }
+            boolean failed = false;
+            if (!writeProto()) {
+                failed = true;
+            }
+            if (!writeBuffer()) {
+                writeBuffer();
+                failed = true;
+            }
+            if (failed) {
+                deleteSnapshot(mTaskId, mUserId);
+            }
+        }
+
+        boolean writeProto() {
+            final TaskSnapshotProto proto = new TaskSnapshotProto();
+            proto.orientation = mSnapshot.getOrientation();
+            proto.insetLeft = mSnapshot.getContentInsets().left;
+            proto.insetTop = mSnapshot.getContentInsets().top;
+            proto.insetRight = mSnapshot.getContentInsets().right;
+            proto.insetBottom = mSnapshot.getContentInsets().bottom;
+            final byte[] bytes = TaskSnapshotProto.toByteArray(proto);
+            final File file = getProtoFile(mTaskId, mUserId);
+            final AtomicFile atomicFile = new AtomicFile(file);
+            FileOutputStream fos = null;
+            try {
+                fos = atomicFile.startWrite();
+                fos.write(bytes);
+                atomicFile.finishWrite(fos);
+            } catch (IOException e) {
+                atomicFile.failWrite(fos);
+                Slog.e(TAG, "Unable to open " + file + " for persisting. " + e);
+                return false;
+            }
+            return true;
+        }
+
+        boolean writeBuffer() {
+            final File file = getBitmapFile(mTaskId, mUserId);
+            final Bitmap bitmap = Bitmap.createHardwareBitmap(mSnapshot.getSnapshot());
+            try {
+                FileOutputStream fos = new FileOutputStream(file);
+                bitmap.compress(CompressFormat.PNG, 0 /* quality */, fos);
+                fos.close();
+            } catch (IOException e) {
+                Slog.e(TAG, "Unable to open " + file + " for persisting. " + e);
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private class DeleteWriteQueueItem extends WriteQueueItem {
+        private final int mTaskId;
+        private final int mUserId;
+
+        DeleteWriteQueueItem(int taskId, int userId) {
+            mTaskId = taskId;
+            mUserId = userId;
+        }
+
+        @Override
+        void write() {
+            deleteSnapshot(mTaskId, mUserId);
+        }
+    }
+
+    @VisibleForTesting
+    class RemoveObsoleteFilesQueueItem extends WriteQueueItem {
+        private final ArraySet<Integer> mPersistentTaskIds;
+        private final int[] mRunningUserIds;
+
+        @VisibleForTesting
+        RemoveObsoleteFilesQueueItem(ArraySet<Integer> persistentTaskIds,
+                int[] runningUserIds) {
+            mPersistentTaskIds = persistentTaskIds;
+            mRunningUserIds = runningUserIds;
+        }
+
+        @Override
+        void write() {
+            final ArraySet<Integer> newPersistedTaskIds;
+            synchronized (mLock) {
+                newPersistedTaskIds = new ArraySet<>(mPersistedTaskIdsSinceLastRemoveObsolete);
+            }
+            for (int userId : mRunningUserIds) {
+                final File dir = getDirectory(userId);
+                final String[] files = dir.list();
+                if (files == null) {
+                    continue;
+                }
+                for (String file : files) {
+                    final int taskId = getTaskId(file);
+                    if (!mPersistentTaskIds.contains(taskId)
+                            && !newPersistedTaskIds.contains(taskId)) {
+                        new File(dir, file).delete();
+                    }
+                }
+            }
+        }
+
+        @VisibleForTesting
+        int getTaskId(String fileName) {
+            if (!fileName.endsWith(PROTO_EXTENSION) && !fileName.endsWith(BITMAP_EXTENSION)) {
+                return -1;
+            }
+            final int end = fileName.lastIndexOf('.');
+            if (end == -1) {
+                return -1;
+            }
+            try {
+                return Integer.parseInt(fileName.substring(0, end));
+            } catch (NumberFormatException e) {
+                return -1;
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index eeea532..53292bb 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -413,7 +413,7 @@
         switch (mStackId) {
             case PINNED_STACK_ID:
                 mTmpRect2 = mDisplayContent.getPinnedStackController().onDisplayChanged(mBounds,
-                        getDisplayInfo());
+                        mDisplayContent);
                 break;
             case DOCKED_STACK_ID:
                 repositionDockedStackAfterRotation(mTmpRect2);
@@ -684,7 +684,7 @@
         // Update the pinned stack controller after the display info is updated
         if (mStackId == PINNED_STACK_ID) {
             mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds,
-                    getDisplayInfo());
+                    mDisplayContent);
         }
 
         super.onDisplayChanged(dc);
@@ -1209,6 +1209,11 @@
     }
 
     @Override
+    public boolean isAttachedToDisplay() {
+        return mDisplayContent != null;
+    }
+
+    @Override
     public String toString() {
         return "{stackId=" + mStackId + " tasks=" + mChildren + "}";
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index dcc0c6f..b0d22b5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3902,6 +3902,20 @@
     }
 
     /**
+     * In case a task write/delete operation was lost because the system crashed, this makes sure to
+     * clean up the directory to remove obsolete files.
+     *
+     * @param persistentTaskIds A set of task ids that exist in our in-memory model.
+     * @param runningUserIds The ids of the list of users that have tasks loaded in our in-memory
+     *                       model.
+     */
+    public void removeObsoleteTaskFiles(ArraySet<Integer> persistentTaskIds, int[] runningUserIds) {
+        synchronized (mWindowMap) {
+            mTaskSnapshotController.removeObsoleteTaskFiles(persistentTaskIds, runningUserIds);
+        }
+    }
+
+    /**
      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
      * In portrait mode, it grabs the full screenshot.
      *
@@ -5346,6 +5360,7 @@
 
     public void systemReady() {
         mPolicy.systemReady();
+        mTaskSnapshotController.systemReady();
     }
 
     // -------------------------------------------------------------
@@ -6985,6 +7000,18 @@
         }
     }
 
+    /**
+     * Called when a task has been removed from the recent tasks list.
+     * <p>
+     * Note: This doesn't go through {@link TaskWindowContainerController} yet as the window
+     * container may not exist when this happens.
+     */
+    public void notifyTaskRemovedFromRecents(int taskId, int userId) {
+        synchronized (mWindowMap) {
+            mTaskSnapshotController.notifyTaskRemovedFromRecents(taskId, userId);
+        }
+    }
+
     @Override
     public int getDockedDividerInsetsLw() {
         return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
diff --git a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index 17a6c297..545b3d7 100644
--- a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -19,6 +19,7 @@
 #include "JNIHelp.h"
 #include "jni.h"
 
+#include <math.h>
 #include <stdlib.h>
 
 #include <android/hardware/thermal/1.0/IThermal.h>
@@ -56,10 +57,16 @@
     jmethodID initMethod;
 } gCpuUsageInfoClassInfo;
 
+jfloat gUndefinedTemperature;
+
 static sp<IThermal> gThermalModule;
 
 // ----------------------------------------------------------------------------
 
+float finalizeTemperature(float temperature) {
+    return isnan(temperature) ? gUndefinedTemperature : temperature;
+}
+
 static void nativeInit(JNIEnv* env, jobject obj) {
     // TODO(b/31632518)
     if (gThermalModule == nullptr) {
@@ -128,16 +135,16 @@
         if (static_cast<int>(list[i].type) == type) {
             switch (source) {
                 case TEMPERATURE_CURRENT:
-                    values[length++] = list[i].currentValue;
+                    values[length++] = finalizeTemperature(list[i].currentValue);
                     break;
                 case TEMPERATURE_THROTTLING:
-                    values[length++] = list[i].throttlingThreshold;
+                    values[length++] = finalizeTemperature(list[i].throttlingThreshold);
                     break;
                 case TEMPERATURE_SHUTDOWN:
-                    values[length++] = list[i].shutdownThreshold;
+                    values[length++] = finalizeTemperature(list[i].shutdownThreshold);
                     break;
                 case TEMPERATURE_THROTTLING_BELOW_VR_MIN:
-                    values[length++] = list[i].vrThrottlingThreshold;
+                    values[length++] = finalizeTemperature(list[i].vrThrottlingThreshold);
                     break;
             }
         }
@@ -204,6 +211,12 @@
     gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
     gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz,
                                                          "<init>", "(JJ)V");
+
+    clazz = env->FindClass("android/os/HardwarePropertiesManager");
+    jfieldID undefined_temperature_field = GetStaticFieldIDOrDie(env, clazz,
+                                                                 "UNDEFINED_TEMPERATURE", "F");
+    gUndefinedTemperature = env->GetStaticFloatField(clazz, undefined_temperature_field);
+
     return res;
 }
 
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 179fba0..9f528b1 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -327,7 +327,7 @@
 
 JTvInputHal* JTvInputHal::createInstance(JNIEnv* env, jobject thiz, const sp<Looper>& looper) {
     // TODO(b/31632518)
-    sp<ITvInput> tvInput = ITvInput::getService("tv.input");
+    sp<ITvInput> tvInput = ITvInput::getService();
     if (tvInput == nullptr) {
         ALOGE("Couldn't get tv.input service.");
         return nullptr;
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 8dd05b1..2624f0b 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -30,6 +30,7 @@
 import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
 import android.net.NetworkUtils;
+import android.net.TrafficStats;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.DhcpClientEvent;
 import android.net.metrics.DhcpErrorEvent;
@@ -303,6 +304,7 @@
     }
 
     private boolean initUdpSocket() {
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_DHCP);
         try {
             mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
             Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_REUSEADDR, 1);
@@ -314,6 +316,8 @@
         } catch(SocketException|ErrnoException e) {
             Log.e(TAG, "Error creating UDP socket", e);
             return false;
+        } finally {
+            TrafficStats.setThreadStatsTag(oldTag);
         }
         return true;
     }
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index 6802cff..ba1621d 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -22,6 +22,7 @@
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkUtils;
+import android.net.TrafficStats;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.StructGroupReq;
@@ -563,6 +564,7 @@
     private boolean createSocket() {
         final int SEND_TIMEOUT_MS = 300;
 
+        final int oldTag = TrafficStats.getAndSetThreadStatsTag(TrafficStats.TAG_SYSTEM_NEIGHBOR);
         try {
             mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
             // Setting SNDTIMEO is purely for defensive purposes.
@@ -574,6 +576,8 @@
         } catch (ErrnoException | IOException e) {
             Log.e(TAG, "Failed to create RA daemon socket: " + e);
             return false;
+        } finally {
+            TrafficStats.setThreadStatsTag(oldTag);
         }
 
         return true;
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index f8061f6..59ac427 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.notification;
 
+import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.fail;
 
 import org.junit.Before;
@@ -34,6 +35,7 @@
 import android.app.NotificationManager;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
@@ -49,6 +51,9 @@
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -166,7 +171,7 @@
         serializer.flush();
 
         for (String channelId : channelIds) {
-            mHelper.deleteNotificationChannel(pkg, uid, channelId);
+            mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId);
         }
         return baos;
     }
@@ -246,26 +251,23 @@
         channel2.enableVibration(true);
         channel2.setVibrationPattern(new long[] {100, 67, 145, 156});
 
-        mHelper.createNotificationChannel(pkg, uid, channel1, false);
+        mHelper.createNotificationChannel(pkg, uid, channel1, true);
         mHelper.createNotificationChannel(pkg, uid, channel2, false);
 
         ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(), channel2.getId(),
                 NotificationChannel.DEFAULT_CHANNEL_ID);
 
-        mHelper.deleteNotificationChannel(pkg, uid, channel1.getId());
-        mHelper.deleteNotificationChannel(pkg, uid, channel2.getId());
-        mHelper.deleteNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
-
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
                 null);
         parser.nextTag();
         mHelper.readXml(parser, false);
 
-        assertEquals(channel1, mHelper.getNotificationChannel(pkg, uid, channel1.getId()));
-        compareChannels(channel2, mHelper.getNotificationChannel(pkg, uid, channel2.getId()));
-        assertNotNull(
-                mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID));
+        assertEquals(channel1, mHelper.getNotificationChannel(pkg, uid, channel1.getId(), false));
+        compareChannels(channel2,
+                mHelper.getNotificationChannel(pkg, uid, channel2.getId(), false));
+        assertNotNull(mHelper.getNotificationChannel(
+                pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false));
     }
 
     @Test
@@ -284,8 +286,8 @@
         parser.nextTag();
         mHelper.readXml(parser, false);
 
-        final NotificationChannel updated =
-                mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+        final NotificationChannel updated = mHelper.getNotificationChannel(
+                pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false);
         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance());
         assertFalse(updated.canBypassDnd());
         assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,updated.getLockscreenVisibility());
@@ -298,8 +300,8 @@
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN);
         mHelper.createNotificationChannel(pkg, uid, channel1, true);
 
-        final NotificationChannel defaultChannel =
-                mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+        final NotificationChannel defaultChannel = mHelper.getNotificationChannel(
+                pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false);
         defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
         mHelper.updateNotificationChannel(pkg, uid, defaultChannel);
 
@@ -313,7 +315,7 @@
         mHelper.readXml(parser, false);
 
         assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
-                pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID).getImportance());
+                pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance());
     }
 
     @Test
@@ -331,8 +333,8 @@
         parser.nextTag();
         mHelper.readXml(parser, false);
 
-        final NotificationChannel updated1 =
-            mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+        final NotificationChannel updated1 = mHelper.getNotificationChannel(
+                pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false);
         assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance());
         assertTrue(updated1.canBypassDnd());
         assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility());
@@ -340,8 +342,8 @@
             | NotificationChannel.USER_LOCKED_PRIORITY
             | NotificationChannel.USER_LOCKED_VISIBILITY, updated1.getUserLockedFields());
 
-        final NotificationChannel updated2 =
-            mHelper.getNotificationChannel(pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID);
+        final NotificationChannel updated2 = mHelper.getNotificationChannel(
+                pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID, false);
         // clamped
         assertEquals(NotificationManager.IMPORTANCE_LOW, updated2.getImportance());
         assertFalse(updated2.canBypassDnd());
@@ -378,7 +380,7 @@
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
         // no fields should be changed
-        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false));
     }
 
     @Test
@@ -399,7 +401,7 @@
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
         // no fields should be changed
-        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false));
     }
 
     @Test
@@ -421,7 +423,7 @@
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
         // no fields should be changed
-        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false));
     }
 
     @Test
@@ -442,7 +444,7 @@
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
         // no fields should be changed
-        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false));
     }
 
     @Test
@@ -463,7 +465,7 @@
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
         // no fields should be changed
-        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false));
     }
 
     @Test
@@ -484,7 +486,7 @@
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
         // no fields should be changed
-        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false));
     }
 
     @Test
@@ -503,7 +505,7 @@
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
         // no fields should be changed
-        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false));
     }
 
     @Test
@@ -529,13 +531,13 @@
         mHelper.updateNotificationChannel(pkg, uid, channel2);
 
         // all fields should be changed
-        assertEquals(channel2, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+        assertEquals(channel2, mHelper.getNotificationChannel(pkg, uid, channel.getId(), false));
     }
 
     @Test
     public void testGetChannelWithFallback() throws Exception {
         NotificationChannel channel =
-                mHelper.getNotificationChannelWithFallback(pkg, uid, "garbage");
+                mHelper.getNotificationChannelWithFallback(pkg, uid, "garbage", false);
         assertEquals(NotificationChannel.DEFAULT_CHANNEL_ID, channel.getId());
     }
 
@@ -557,7 +559,7 @@
         mHelper.createNotificationChannel(pkg, uid, channel, true);
 
         NotificationChannel savedChannel =
-                mHelper.getNotificationChannel(pkg, uid, channel.getId());
+                mHelper.getNotificationChannel(pkg, uid, channel.getId(), false);
 
         assertEquals(channel.getName(), savedChannel.getName());
         assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
@@ -584,7 +586,7 @@
         mHelper.createNotificationChannel(pkg, uid, channel, true);
 
         NotificationChannel savedChannel =
-                mHelper.getNotificationChannel(pkg, uid, channel.getId());
+                mHelper.getNotificationChannel(pkg, uid, channel.getId(), false);
 
         assertEquals(channel.getName(), savedChannel.getName());
         assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
@@ -592,4 +594,168 @@
         assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
         assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
     }
+
+    @Test
+    public void testGetDeletedChannel() throws Exception {
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        channel.enableVibration(true);
+        channel.setVibrationPattern(new long[] {100, 67, 145, 156});
+
+        mHelper.createNotificationChannel(pkg, uid, channel, true);
+        mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
+
+        // Does not return deleted channel
+        NotificationChannel response =
+                mHelper.getNotificationChannel(pkg, uid, channel.getId(), false);
+        assertNull(response);
+
+        // Returns deleted channel
+        response = mHelper.getNotificationChannel(pkg, uid, channel.getId(), true);
+        compareChannels(channel, response);
+        assertTrue(response.isDeleted());
+    }
+
+    @Test
+    public void testGetDeletedChannels() throws Exception {
+        Map<String, NotificationChannel> channelMap = new HashMap<>();
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
+        channel.enableVibration(true);
+        channel.setVibrationPattern(new long[] {100, 67, 145, 156});
+        channelMap.put(channel.getId(), channel);
+        NotificationChannel channel2 =
+                new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
+        channelMap.put(channel2.getId(), channel2);
+        mHelper.createNotificationChannel(pkg, uid, channel, true);
+        mHelper.createNotificationChannel(pkg, uid, channel2, true);
+
+        mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
+
+        // Returns only non-deleted channels
+        List<NotificationChannel> channels =
+                mHelper.getNotificationChannels(pkg, uid, false).getList();
+        assertEquals(2, channels.size());   // Default channel + non-deleted channel
+        for (NotificationChannel nc : channels) {
+            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
+                compareChannels(channel2, nc);
+            }
+        }
+
+        // Returns deleted channels too
+        channels =  mHelper.getNotificationChannels(pkg, uid, true).getList();
+        assertEquals(3, channels.size());               // Includes default channel
+        for (NotificationChannel nc : channels) {
+            if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
+                compareChannels(channelMap.get(nc.getId()), nc);
+            }
+        }
+    }
+
+    @Test
+    public void testUpdateDeletedChannels() throws Exception {
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        mHelper.createNotificationChannel(pkg, uid, channel, true);
+
+        mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
+
+        channel.setSound(new Uri.Builder().scheme("test").build());
+        try {
+            mHelper.updateNotificationChannel(pkg, uid, channel);
+            fail("Updated deleted channel");
+        } catch (IllegalArgumentException e) {
+            // :)
+        }
+
+        try {
+            mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel);
+            fail("Updated deleted channel");
+        } catch (IllegalArgumentException e) {
+            // :)
+        }
+    }
+
+    @Test
+    public void testCreateDeletedChannel() throws Exception {
+        long[] vibration = new long[] {100, 67, 145, 156};
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setVibrationPattern(vibration);
+
+        mHelper.createNotificationChannel(pkg, uid, channel, true);
+        mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
+
+        NotificationChannel newChannel = new NotificationChannel(
+                channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
+        newChannel.setVibrationPattern(new long[] {100});
+
+        mHelper.createNotificationChannel(pkg, uid, newChannel, true);
+
+        // No long deleted, using old settings
+        compareChannels(channel,
+                mHelper.getNotificationChannel(pkg, uid, newChannel.getId(), false));
+    }
+
+    @Test
+    public void testCreateChannel_alreadyExists() throws Exception {
+        long[] vibration = new long[] {100, 67, 145, 156};
+        NotificationChannel channel =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setVibrationPattern(vibration);
+
+        mHelper.createNotificationChannel(pkg, uid, channel, true);
+
+        NotificationChannel newChannel = new NotificationChannel(
+                channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
+        newChannel.setVibrationPattern(new long[] {100});
+
+        mHelper.createNotificationChannel(pkg, uid, newChannel, true);
+
+        // Old settings not overridden
+        compareChannels(channel,
+                mHelper.getNotificationChannel(pkg, uid, newChannel.getId(), false));
+    }
+
+    @Test
+    public void testPermanentlyDeleteChannels() throws Exception {
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+
+        mHelper.createNotificationChannel(pkg, uid, channel1, true);
+        mHelper.createNotificationChannel(pkg, uid, channel2, false);
+
+        mHelper.permanentlyDeleteNotificationChannels(pkg, uid);
+
+        // Only default channel remains
+        assertEquals(1, mHelper.getNotificationChannels(pkg, uid, true).getList().size());
+    }
+
+    @Test
+    public void testOnPackageChanged_packageRemoval() throws Exception {
+        // Deleted
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        mHelper.createNotificationChannel(pkg, uid, channel1, true);
+
+        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid});
+
+        assertEquals(0, mHelper.getNotificationChannels(pkg, uid, true).getList().size());
+
+        // Not deleted
+        mHelper.createNotificationChannel(pkg, uid, channel1, true);
+
+        mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid});
+        assertEquals(2, mHelper.getNotificationChannels(pkg, uid, false).getList().size());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index df275d2..96e8948 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -22,6 +22,9 @@
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Matchers.notNull;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -238,7 +241,7 @@
      * - Launcher supports the feature.
      * - Shortcut doesn't pre-exist.
      */
-    private void checkRequestPinShortcut(@Nullable PendingIntent resultIntent) {
+    private void checkRequestPinShortcut(@Nullable IntentSender resultIntent) {
         setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
         setDefaultLauncher(USER_10, mMainActivityFetcher.apply(LAUNCHER_2, USER_10));
 
@@ -254,8 +257,7 @@
 
             assertNull(s.getActivity());
 
-            assertTrue(mManager.requestPinShortcut(s,
-                    resultIntent == null ? null : resultIntent.getIntentSender()));
+            assertTrue(mManager.requestPinShortcut(s, resultIntent));
 
             verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
 
@@ -294,9 +296,9 @@
 
         // This method is always called, even with PI == null.
         if (resultIntent == null) {
-            verify(mServiceContext, times(1)).sendIntentSender(eq(null));
+            verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class));
         } else {
-            verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class));
+            verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class));
         }
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -314,11 +316,12 @@
         checkRequestPinShortcut(/* resultIntent=*/ null);
     }
 
-    public void testRequestPinShortcut_withCallback() {
-        final PendingIntent resultIntent =
-                PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0);
+    private IntentSender makeResultIntent() {
+        return PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0).getIntentSender();
+    }
 
-        checkRequestPinShortcut(resultIntent);
+    public void testRequestPinShortcut_withCallback() {
+        checkRequestPinShortcut(makeResultIntent());
     }
 
     public void testRequestPinShortcut_explicitTargetActivity() {
@@ -578,8 +581,15 @@
     public void testRequestPinShortcut_dynamicExists_alreadyPinned() {
         setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0));
 
+        final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
+
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))));
+            final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext, "s1")
+                    .setShortLabel("Title-" + "s1")
+                    .setIcon(res32x32)
+                    .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class));
+            final ShortcutInfo s = b.build();
+            assertTrue(mManager.setDynamicShortcuts(list(s)));
         });
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
@@ -590,14 +600,66 @@
             assertWith(getCallerShortcuts())
                     .haveIds("s1")
                     .areAllDynamic()
-                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main"))
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity"))
                     .areAllPinned();
 
             assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("s1"),
-                    /* resultIntent=*/ null));
+                    makeResultIntent()));
 
             // The intent should be sent right away.
-            verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class));
+            verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class));
+        });
+
+        // Already pinned.
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("s1")
+                    .areAllDynamic()
+                    .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity"))
+                    .areAllPinned();
+        });
+
+        // ... But the launcher will still receive the request.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            // Check the intent passed to startActivityAsUser().
+            final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
+
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+
+            assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
+
+            // Check the request object.
+            final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue());
+
+            assertPinItemRequest(request);
+
+            assertWith(request.getShortcutInfo())
+                    .haveIds("s1")
+                    .areAllDynamic()
+                    .areAllPinned() // Note it's pinned already.
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity"))
+                    .areAllWithNoIntent();
+
+            assertAllHaveIcon(list(request.getShortcutInfo()));
+
+            reset(mServiceContext);
+
+            // Accept the request.
+            assertTrue(request.accept());
+
+            // The intent is only sent once, so times(1).
+            verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class));
+        });
+
+        // Still pinned.
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("s1")
+                    .areAllDynamic()
+                    .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity"))
+                    .areAllPinned();
         });
     }
 
@@ -621,10 +683,65 @@
                     .areAllPinned();
 
             assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("ms1"),
-                    /* resultIntent=*/ null));
+                    makeResultIntent()));
 
             // The intent should be sent right away.
-            verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class));
+            verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class));
+        });
+
+        // Already pinned.
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1")
+                    .areAllManifest()
+                    .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
+                    .areAllPinned();
+        });
+
+        // ... But the launcher will still receive the request.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            // Check the intent passed to startActivityAsUser().
+            final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
+
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+
+            assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
+
+            // Check the request object.
+            final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue());
+
+            assertPinItemRequest(request);
+
+            assertWith(request.getShortcutInfo())
+                    .haveIds("ms1")
+                    .areAllManifest()
+                    .areAllPinned() // Note it's pinned already.
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
+                    .areAllWithNoIntent();
+
+            assertAllHaveIcon(list(request.getShortcutInfo()));
+
+            reset(mServiceContext);
+
+            // Accept the request.
+            assertTrue(request.accept());
+
+            // The intent is only sent once, so times(1).
+            verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class));
+        });
+
+        // Still pinned.
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertWith(getCallerShortcuts())
+                    .haveIds("ms1")
+                    .areAllManifest()
+                    .areAllEnabled()
+                    .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1,
+                            ShortcutActivity.class.getName()))
+                    .areAllPinned();
         });
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index 84a7c19..cfa35c2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -83,7 +83,8 @@
     private void assertPinItemRequest(PinItemRequest actualRequest, String className) {
         assertNotNull(actualRequest);
         assertEquals(PinItemRequest.REQUEST_TYPE_APPWIDGET, actualRequest.getRequestType());
-        assertEquals(className, actualRequest.getAppWidgetProviderInfo().provider.getClassName());
+        assertEquals(className, actualRequest.getAppWidgetProviderInfo(getTestContext())
+                .provider.getClassName());
     }
 
     public void testNotForeground() {
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
new file mode 100644
index 0000000..8d6d2da
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static android.graphics.GraphicBuffer.USAGE_HW_TEXTURE;
+import static android.graphics.GraphicBuffer.USAGE_SW_READ_RARELY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.ActivityManager.TaskSnapshot;
+import android.content.pm.UserInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.ArraySet;
+
+import com.android.internal.util.Predicate;
+import com.android.server.wm.TaskSnapshotPersister.RemoveObsoleteFilesQueueItem;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+/**
+ * Test class for {@link TaskSnapshotPersister} and {@link TaskSnapshotLoader}
+ *
+ * runtest frameworks-services -c com.android.server.wm.TaskSnapshotPersisterLoaderTest
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class TaskSnapshotPersisterLoaderTest {
+
+    private static final String TEST_USER_NAME = "TaskSnapshotPersisterTest User";
+    private static final Rect TEST_INSETS = new Rect(10, 20, 30, 40);
+
+    private TaskSnapshotPersister mPersister;
+    private TaskSnapshotLoader mLoader;
+    private static int sTestUserId;
+    private static File sFilesDir;
+    private static UserManager sUserManager;
+
+    @BeforeClass
+    public static void setUpUser() {
+        sUserManager = UserManager.get(InstrumentationRegistry.getContext());
+        sTestUserId = createUser(TEST_USER_NAME, 0);
+        sFilesDir = InstrumentationRegistry.getContext().getFilesDir();
+    }
+
+    @AfterClass
+    public static void tearDownUser() {
+        removeUser(sTestUserId);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        mPersister = new TaskSnapshotPersister(
+                userId -> sFilesDir);
+        mLoader = new TaskSnapshotLoader(mPersister);
+        mPersister.start();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        cleanDirectory();
+    }
+
+    @Test
+    public void testPersistAndLoadSnapshot() {
+        mPersister.persistSnapshot(1 , sTestUserId, createSnapshot());
+        mPersister.waitForQueueEmpty();
+        final File[] files = new File[] { new File(sFilesDir.getPath() + "/snapshots/1.proto"),
+                new File(sFilesDir.getPath() + "/snapshots/1.png") };
+        assertTrueForFiles(files, File::exists, " must exist");
+        final TaskSnapshot snapshot = mLoader.loadTask(1, sTestUserId);
+        assertNotNull(snapshot);
+        assertEquals(TEST_INSETS, snapshot.getContentInsets());
+        assertNotNull(snapshot.getSnapshot());
+        assertEquals(Configuration.ORIENTATION_PORTRAIT, snapshot.getOrientation());
+    }
+
+    private void assertTrueForFiles(File[] files, Predicate<File> predicate, String message) {
+        for (File file : files) {
+            assertTrue(file.getName() + message, predicate.apply(file));
+        }
+    }
+
+    @Test
+    public void testTaskRemovedFromRecents() {
+        mPersister.persistSnapshot(1, sTestUserId, createSnapshot());
+        mPersister.onTaskRemovedFromRecents(1, sTestUserId);
+        mPersister.waitForQueueEmpty();
+        assertFalse(new File(sFilesDir.getPath() + "/snapshots/1.proto").exists());
+        assertFalse(new File(sFilesDir.getPath() + "/snapshots/1.png").exists());
+    }
+
+    /**
+     * Tests that persisting a couple of snapshots is being throttled.
+     */
+    @Test
+    public void testThrottling() {
+        long ms = SystemClock.elapsedRealtime();
+        mPersister.persistSnapshot(1, sTestUserId, createSnapshot());
+        mPersister.persistSnapshot(2, sTestUserId, createSnapshot());
+        mPersister.persistSnapshot(3, sTestUserId, createSnapshot());
+        mPersister.persistSnapshot(4, sTestUserId, createSnapshot());
+        mPersister.persistSnapshot(5, sTestUserId, createSnapshot());
+        mPersister.persistSnapshot(6, sTestUserId, createSnapshot());
+        mPersister.waitForQueueEmpty();
+        assertTrue(SystemClock.elapsedRealtime() - ms > 500);
+    }
+
+    @Test
+    public void testGetTaskId() {
+        RemoveObsoleteFilesQueueItem removeObsoleteFilesQueueItem =
+                mPersister.new RemoveObsoleteFilesQueueItem(new ArraySet<>(), new int[] {});
+        assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("blablablulp"));
+        assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("nothing.err"));
+        assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("/invalid/"));
+        assertEquals(12, removeObsoleteFilesQueueItem.getTaskId("12.png"));
+        assertEquals(12, removeObsoleteFilesQueueItem.getTaskId("12.proto"));
+        assertEquals(1, removeObsoleteFilesQueueItem.getTaskId("1.png"));
+    }
+
+    @Test
+    public void testRemoveObsoleteFiles() {
+        mPersister.persistSnapshot(1, sTestUserId, createSnapshot());
+        mPersister.persistSnapshot(2, sTestUserId, createSnapshot());
+        final ArraySet<Integer> taskIds = new ArraySet<>();
+        taskIds.add(1);
+        mPersister.removeObsoleteFiles(taskIds, new int[] { sTestUserId });
+        mPersister.waitForQueueEmpty();
+        final File[] existsFiles = new File[] {
+                new File(sFilesDir.getPath() + "/snapshots/1.proto"),
+                new File(sFilesDir.getPath() + "/snapshots/1.png") };
+        final File[] nonExistsFiles = new File[] {
+                new File(sFilesDir.getPath() + "/snapshots/2.proto"),
+                new File(sFilesDir.getPath() + "/snapshots/2.png") };
+        assertTrueForFiles(existsFiles, File::exists, " must exist");
+        assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
+    }
+
+    @Test
+    public void testRemoveObsoleteFiles_addedOneInTheMeantime() {
+        mPersister.persistSnapshot(1, sTestUserId, createSnapshot());
+        final ArraySet<Integer> taskIds = new ArraySet<>();
+        taskIds.add(1);
+        mPersister.removeObsoleteFiles(taskIds, new int[] { sTestUserId });
+        mPersister.persistSnapshot(2, sTestUserId, createSnapshot());
+        mPersister.waitForQueueEmpty();
+        final File[] existsFiles = new File[] {
+                new File(sFilesDir.getPath() + "/snapshots/1.proto"),
+                new File(sFilesDir.getPath() + "/snapshots/1.png"),
+                new File(sFilesDir.getPath() + "/snapshots/2.proto"),
+                new File(sFilesDir.getPath() + "/snapshots/2.png") };
+        assertTrueForFiles(existsFiles, File::exists, " must exist");
+    }
+
+    private TaskSnapshot createSnapshot() {
+        GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
+                USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
+        Canvas c = buffer.lockCanvas();
+        c.drawColor(Color.RED);
+        buffer.unlockCanvasAndPost(c);
+        return new TaskSnapshot(buffer, Configuration.ORIENTATION_PORTRAIT, TEST_INSETS);
+    }
+
+    private static int createUser(String name, int flags) {
+        UserInfo user = sUserManager.createUser(name, flags);
+        if (user == null) {
+            Assert.fail("Error while creating the test user: " + TEST_USER_NAME);
+        }
+        return user.id;
+    }
+
+    private static void removeUser(int userId) {
+        if (!sUserManager.removeUser(userId)) {
+            Assert.fail("Error while removing the test user: " + TEST_USER_NAME);
+        }
+    }
+
+    private void cleanDirectory() {
+        for (File file : new File(sFilesDir, "snapshots").listFiles()) {
+            if (!file.isDirectory()) {
+                file.delete();
+            }
+        }
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index d243bf2..6dfb48b 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -106,6 +106,7 @@
     private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
     private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
 
+    private static final boolean ENABLE_KERNEL_UPDATES = false;
     private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set");
 
     long mAppIdleScreenThresholdMillis;
@@ -241,7 +242,7 @@
                 postOneTimeCheckIdleStates();
             }
 
-            if (KERNEL_COUNTER_FILE.exists()) {
+            if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) {
                 try {
                     ActivityManager.getService().registerUidObserver(mUidObserver,
                             ActivityManager.UID_OBSERVER_PROCSTATE
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index 7f182a4..4aff3d54 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -556,7 +556,9 @@
 
     private void sendPortChangedBroadcastLocked(PortInfo portInfo) {
         final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED);
-        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        intent.addFlags(
+                Intent.FLAG_RECEIVER_FOREGROUND |
+                Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         intent.putExtra(UsbManager.EXTRA_PORT, portInfo.mUsbPort);
         intent.putExtra(UsbManager.EXTRA_PORT_STATUS, portInfo.mUsbPortStatus);
 
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index e03a14f..2e99b6e 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -971,7 +971,9 @@
     public void accessoryAttached(UsbAccessory accessory) {
         Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
         intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK |
+                Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
 
         ArrayList<ResolveInfo> matches;
         String defaultPackage = null;
@@ -1364,7 +1366,9 @@
     private static Intent createDeviceAttachedIntent(UsbDevice device) {
         Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
         intent.putExtra(UsbManager.EXTRA_DEVICE, device);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.addFlags(
+                Intent.FLAG_ACTIVITY_NEW_TASK |
+                Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         return intent;
     }
 }
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 24d5f09..7a55be4 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -182,6 +182,7 @@
         }
 
         Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
+        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         intent.putExtra(UsbManager.EXTRA_DEVICE, device);
 
         if (DEBUG) {
@@ -204,6 +205,7 @@
         }
 
         Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
+        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
         intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 7d258a0..b7391b4 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -377,8 +377,16 @@
      */
     public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 1<<6;
 
+    /**
+     * Set by the framework to indicate that the {@link Connection} originated from a self-managed
+     * {@link ConnectionService}.
+     * <p>
+     * See {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.
+     */
+    public static final int PROPERTY_SELF_MANAGED = 1<<7;
+
     //**********************************************************************************************
-    // Next PROPERTY value: 1<<7
+    // Next PROPERTY value: 1<<8
     //**********************************************************************************************
 
     /**
@@ -681,6 +689,10 @@
             builder.append("Properties:");
         }
 
+        if (can(properties, PROPERTY_SELF_MANAGED)) {
+            builder.append(isLong ? " PROPERTY_SELF_MANAGED" : " self_mng");
+        }
+
         if (can(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
             builder.append(isLong ? " PROPERTY_EMERGENCY_CALLBACK_MODE" : " ecbm");
         }
@@ -741,6 +753,7 @@
         public void onConnectionEvent(Connection c, String event, Bundle extras) {}
         /** @hide */
         public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
+        public void onAudioRouteChanged(Connection c, int audioRoute) {}
     }
 
     /**
@@ -2325,6 +2338,25 @@
     }
 
     /**
+     * Sets the audio route (speaker, bluetooth, etc...).  When this request is honored, there will
+     * be change to the {@link #getCallAudioState()}.
+     * <p>
+     * Used by self-managed {@link ConnectionService}s which wish to change the audio route for a
+     * self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.)
+     * <p>
+     * See also {@link InCallService#setAudioRoute(int)}.
+     *
+     * @param route The audio route to use (one of {@link CallAudioState#ROUTE_BLUETOOTH},
+     *              {@link CallAudioState#ROUTE_EARPIECE}, {@link CallAudioState#ROUTE_SPEAKER}, or
+     *              {@link CallAudioState#ROUTE_WIRED_HEADSET}).
+     */
+    public final void setAudioRoute(int route) {
+        for (Listener l : mListeners) {
+            l.onAudioRouteChanged(this, route);
+        }
+    }
+
+    /**
      * Notifies this Connection that the {@link #getAudioState()} property has a new value.
      *
      * @param state The new connection audio state.
@@ -2479,6 +2511,21 @@
      */
     public void onExtrasChanged(Bundle extras) {}
 
+    /**
+     * Notifies this {@link Connection} that its {@link ConnectionService} is responsible for
+     * displaying its incoming call user interface for the {@link Connection}.
+     * <p>
+     * Will only be called for incoming calls added via a self-managed {@link ConnectionService}
+     * (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}), where the {@link ConnectionService}
+     * should show its own incoming call user interface.
+     * <p>
+     * Where there are ongoing calls in other self-managed {@link ConnectionService}s, or in a
+     * regular {@link ConnectionService}, the Telecom framework will display its own incoming call
+     * user interface to allow the user to choose whether to answer the new incoming call and
+     * disconnect other ongoing calls, or to reject the new incoming call.
+     */
+    public void onShowIncomingCallUi() {}
+
     static String toLogSafePhoneNumber(String number) {
         // For unknown number, log empty string.
         if (number == null) {
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index aba38fe..2343462 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -33,6 +33,7 @@
     private final Bundle mExtras;
     private final int mVideoState;
     private final String mTelecomCallId;
+    private final boolean mShouldShowIncomingCallUi;
 
     /**
      * @param accountHandle The accountHandle which should be used to place the call.
@@ -43,7 +44,7 @@
             PhoneAccountHandle accountHandle,
             Uri handle,
             Bundle extras) {
-        this(accountHandle, handle, extras, VideoProfile.STATE_AUDIO_ONLY, null);
+        this(accountHandle, handle, extras, VideoProfile.STATE_AUDIO_ONLY, null, false);
     }
 
     /**
@@ -57,7 +58,7 @@
             Uri handle,
             Bundle extras,
             int videoState) {
-        this(accountHandle, handle, extras, videoState, null);
+        this(accountHandle, handle, extras, videoState, null, false);
     }
 
     /**
@@ -66,6 +67,10 @@
      * @param extras Application-specific extra data.
      * @param videoState Determines the video state for the connection.
      * @param telecomCallId The telecom call ID.
+     * @param shouldShowIncomingCallUi For a self-managed {@link ConnectionService}, will be
+     *                                 {@code true} if the {@link ConnectionService} should show its
+     *                                 own incoming call UI for an incoming call.  When
+     *                                 {@code false}, Telecom shows the incoming call UI.
      * @hide
      */
     public ConnectionRequest(
@@ -73,12 +78,14 @@
             Uri handle,
             Bundle extras,
             int videoState,
-            String telecomCallId) {
+            String telecomCallId,
+            boolean shouldShowIncomingCallUi) {
         mAccountHandle = accountHandle;
         mAddress = handle;
         mExtras = extras;
         mVideoState = videoState;
         mTelecomCallId = telecomCallId;
+        mShouldShowIncomingCallUi = shouldShowIncomingCallUi;
     }
 
     private ConnectionRequest(Parcel in) {
@@ -87,6 +94,7 @@
         mExtras = in.readParcelable(getClass().getClassLoader());
         mVideoState = in.readInt();
         mTelecomCallId = in.readString();
+        mShouldShowIncomingCallUi = in.readInt() == 1;
     }
 
     /**
@@ -129,6 +137,18 @@
         return mTelecomCallId;
     }
 
+    /**
+     * For a self-managed {@link ConnectionService}, indicates for an incoming call whether the
+     * {@link ConnectionService} should show its own incoming call UI for an incoming call.
+     *
+     * @return {@code true} if the {@link ConnectionService} should show its own incoming call UI.
+     * When {@code false}, Telecom shows the incoming call UI for the call.
+     * @hide
+     */
+    public boolean shouldShowIncomingCallUi() {
+        return mShouldShowIncomingCallUi;
+    }
+
     @Override
     public String toString() {
         return String.format("ConnectionRequest %s %s",
@@ -165,5 +185,6 @@
         destination.writeParcelable(mExtras, 0);
         destination.writeInt(mVideoState);
         destination.writeString(mTelecomCallId);
+        destination.writeInt(mShouldShowIncomingCallUi ? 1 : 0);
     }
 }
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index b119e16..d0ccd55 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -42,10 +42,15 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
- * An abstract service that should be implemented by any apps which can make phone calls (VoIP or
- * otherwise) and want those calls to be integrated into the built-in phone app.
- * Once implemented, the {@code ConnectionService} needs two additional steps before it will be
- * integrated into the phone app:
+ * An abstract service that should be implemented by any apps which either:
+ * <ol>
+ *     <li>Can make phone calls (VoIP or otherwise) and want those calls to be integrated into the
+ *     built-in phone app.  Referred to as a <b>system managed</b> {@link ConnectionService}.</li>
+ *     <li>Are a standalone calling app and don't want their calls to be integrated into the
+ *     built-in phone app.  Referred to as a <b>self managed</b> {@link ConnectionService}.</li>
+ * </ol>
+ * Once implemented, the {@link ConnectionService} needs to take the following steps so that Telecom
+ * will bind to it:
  * <p>
  * 1. <i>Registration in AndroidManifest.xml</i>
  * <br/>
@@ -63,16 +68,20 @@
  * <br/>
  * See {@link PhoneAccount} and {@link TelecomManager#registerPhoneAccount} for more information.
  * <p>
- * Once registered and enabled by the user in the phone app settings, telecom will bind to a
- * {@code ConnectionService} implementation when it wants that {@code ConnectionService} to place
- * a call or the service has indicated that is has an incoming call through
- * {@link TelecomManager#addNewIncomingCall}. The {@code ConnectionService} can then expect a call
- * to {@link #onCreateIncomingConnection} or {@link #onCreateOutgoingConnection} wherein it
- * should provide a new instance of a {@link Connection} object.  It is through this
- * {@link Connection} object that telecom receives state updates and the {@code ConnectionService}
+ * System managed {@link ConnectionService}s must be enabled by the user in the phone app settings
+ * before Telecom will bind to them.  Self-manged {@link ConnectionService}s must be granted the
+ * appropriate permission before Telecom will bind to them.
+ * <p>
+ * Once registered and enabled by the user in the phone app settings or granted permission, telecom
+ * will bind to a {@link ConnectionService} implementation when it wants that
+ * {@link ConnectionService} to place a call or the service has indicated that is has an incoming
+ * call through {@link TelecomManager#addNewIncomingCall}. The {@link ConnectionService} can then
+ * expect a call to {@link #onCreateIncomingConnection} or {@link #onCreateOutgoingConnection}
+ * wherein it should provide a new instance of a {@link Connection} object.  It is through this
+ * {@link Connection} object that telecom receives state updates and the {@link ConnectionService}
  * receives call-commands such as answer, reject, hold and disconnect.
  * <p>
- * When there are no more live calls, telecom will unbind from the {@code ConnectionService}.
+ * When there are no more live calls, telecom will unbind from the {@link ConnectionService}.
  */
 public abstract class ConnectionService extends Service {
     /**
@@ -1054,6 +1063,7 @@
             }
         }
 
+        @Override
         public void onExtrasRemoved(Connection c, List<String> keys) {
             String id = mIdByConnection.get(c);
             if (id != null) {
@@ -1061,7 +1071,6 @@
             }
         }
 
-
         @Override
         public void onConnectionEvent(Connection connection, String event, Bundle extras) {
             String id = mIdByConnection.get(connection);
@@ -1069,6 +1078,14 @@
                 mAdapter.onConnectionEvent(id, event, extras);
             }
         }
+
+        @Override
+        public void onAudioRouteChanged(Connection c, int audioRoute) {
+            String id = mIdByConnection.get(c);
+            if (id != null) {
+                mAdapter.setAudioRoute(id, audioRoute);
+            }
+        }
     };
 
     /** {@inheritDoc} */
@@ -1146,6 +1163,13 @@
                         connection.getDisconnectCause(),
                         createIdList(connection.getConferenceables()),
                         connection.getExtras()));
+
+        if (isIncoming && request.shouldShowIncomingCallUi() &&
+                (connection.getConnectionProperties() & Connection.PROPERTY_SELF_MANAGED) ==
+                        Connection.PROPERTY_SELF_MANAGED) {
+            // Tell ConnectionService to show its incoming call UX.
+            connection.onShowIncomingCallUi();
+        }
         if (isUnknown) {
             triggerConferenceRecalculate();
         }
@@ -1587,6 +1611,38 @@
     }
 
     /**
+     * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
+     * incoming {@link Connection} was denied.
+     * <p>
+     * Used when a self-managed {@link ConnectionService} attempts to create a new incoming
+     * {@link Connection}, but Telecom has determined that the call cannot be allowed at this time.
+     * The {@link ConnectionService} is responsible for silently rejecting the new incoming
+     * {@link Connection}.
+     * <p>
+     * See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information.
+     *
+     * @param request The incoming connection request.
+     */
+    public void onCreateIncomingConnectionFailed(ConnectionRequest request) {
+    }
+
+    /**
+     * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
+     * outgoing {@link Connection} was denied.
+     * <p>
+     * Used when a self-managed {@link ConnectionService} attempts to create a new outgoing
+     * {@link Connection}, but Telecom has determined that the call cannot be placed at this time.
+     * The {@link ConnectionService} is responisible for informing the user that the
+     * {@link Connection} cannot be made at this time.
+     * <p>
+     * See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information.
+     *
+     * @param request The outgoing connection request.
+     */
+    public void onCreateOutgoingConnectionFailed(ConnectionRequest request) {
+    }
+
+    /**
      * Trigger recalculate functinality for conference calls. This is used when a Telephony
      * Connection is part of a conference controller but is not yet added to Connection
      * Service and hence cannot be added to the conference call.
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index f3fada9..9542b73 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -515,6 +515,23 @@
     }
 
     /**
+     * Sets the audio route associated with a {@link Connection}.
+     *
+     * @param callId The unique ID of the call.
+     * @param audioRoute The new audio route (see {@code CallAudioState#ROUTE_*}).
+     */
+    void setAudioRoute(String callId, int audioRoute) {
+        Log.v(this, "setAudioRoute: %s %s", callId, CallAudioState.audioRouteToString(audioRoute));
+        for (IConnectionServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setAudioRoute(callId, audioRoute, Log.getExternalSession());
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+
+    /**
      * Informs Telecom of a connection level event.
      *
      * @param callId The unique ID of the call.
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index afe5e33..cc437f9 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -67,6 +67,7 @@
     private static final int MSG_ON_CONNECTION_EVENT = 26;
     private static final int MSG_SET_CONNECTION_PROPERTIES = 27;
     private static final int MSG_SET_PULLING = 28;
+    private static final int MSG_SET_AUDIO_ROUTE = 29;
 
     private final IConnectionServiceAdapter mDelegate;
 
@@ -289,6 +290,16 @@
                     }
                     break;
                 }
+                case MSG_SET_AUDIO_ROUTE: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        mDelegate.setAudioRoute((String) args.arg1, args.argi1,
+                                (Session.Info) args.arg2);
+                    } finally {
+                        args.recycle();
+                    }
+                    break;
+                }
             }
         }
     };
@@ -507,6 +518,17 @@
         }
 
         @Override
+        public final void setAudioRoute(String connectionId, int audioRoute,
+                Session.Info sessionInfo) {
+
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = connectionId;
+            args.argi1 = audioRoute;
+            args.arg2 = sessionInfo;
+            mHandler.obtainMessage(MSG_SET_AUDIO_ROUTE, args).sendToTarget();
+        }
+
+        @Override
         public final void onConnectionEvent(String connectionId, String event, Bundle extras,
                 Session.Info sessionInfo) {
             SomeArgs args = SomeArgs.obtain();
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index ca54486..845a103 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -189,6 +189,21 @@
     public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 0x400;
 
     /**
+     * Flag indicating that this {@link PhoneAccount} is responsible for managing its own
+     * {@link Connection}s.  This type of {@link PhoneAccount} is ideal for use with standalone
+     * calling apps which do not wish to use the default phone app for {@link Connection} UX,
+     * but which want to leverage the call and audio routing capabilities of the Telecom framework.
+     * <p>
+     * When set, {@link Connection}s created by the self-managed {@link ConnectionService} will not
+     * be surfaced to implementations of the {@link InCallService} API.  Thus it is the
+     * responsibility of a self-managed {@link ConnectionService} to provide a user interface for
+     * its {@link Connection}s.
+     * <p>
+     * Self-managed {@link Connection}s will, however, be displayed on connected Bluetooth devices.
+     */
+    public static final int CAPABILITY_SELF_MANAGED = 0x800;
+
+    /**
      * URI scheme for telephone number URIs.
      */
     public static final String SCHEME_TEL = "tel";
@@ -692,6 +707,14 @@
         mIsEnabled = isEnabled;
     }
 
+    /**
+     * @return {@code true} if the {@link PhoneAccount} is self-managed, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isSelfManaged() {
+        return (mCapabilities & CAPABILITY_SELF_MANAGED) == CAPABILITY_SELF_MANAGED;
+    }
+
     //
     // Parcelable implementation
     //
@@ -815,6 +838,9 @@
      */
     private String capabilitiesToString() {
         StringBuilder sb = new StringBuilder();
+        if (hasCapabilities(CAPABILITY_SELF_MANAGED)) {
+            sb.append("SelfManaged ");
+        }
         if (hasCapabilities(CAPABILITY_SUPPORTS_VIDEO_CALLING)) {
             sb.append("SuppVideo ");
         }
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index d8a226a..0c7404a 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -389,6 +389,15 @@
         }
 
         @Override
+        public void setAudioRoute(String callId, int audioRoute, Session.Info sessionInfo) {
+            if (hasConnection(callId)) {
+                // TODO(3pcalls): handle this for remote connections.
+                // Likely we don't want to do anything since it doesn't make sense for self-managed
+                // connections to go through a connection mgr.
+            }
+        }
+
+        @Override
         public void onConnectionEvent(String callId, String event, Bundle extras,
                 Session.Info sessionInfo) {
             if (mConnectionById.containsKey(callId)) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index f12886a..00e8f9f 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1202,17 +1202,25 @@
 
     /**
      * Registers a new incoming call. A {@link ConnectionService} should invoke this method when it
-     * has an incoming call. The specified {@link PhoneAccountHandle} must have been registered
-     * with {@link #registerPhoneAccount} and the user must have enabled the corresponding
-     * {@link PhoneAccount}. This can be checked using {@link #getPhoneAccount}. Once invoked, this
-     * method will cause the system to bind to the {@link ConnectionService} associated with the
-     * {@link PhoneAccountHandle} and request additional information about the call
-     * (See {@link ConnectionService#onCreateIncomingConnection}) before starting the incoming
+     * has an incoming call. For managed {@link ConnectionService}s, the specified
+     * {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
+     * the user must have enabled the corresponding {@link PhoneAccount}.  This can be checked using
+     * {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
+     * {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
+     * <p>
+     * Once invoked, this method will cause the system to bind to the {@link ConnectionService}
+     * associated with the {@link PhoneAccountHandle} and request additional information about the
+     * call (See {@link ConnectionService#onCreateIncomingConnection}) before starting the incoming
      * call UI.
      * <p>
-     * A {@link SecurityException} will be thrown if either the {@link PhoneAccountHandle} does not
-     * correspond to a registered {@link PhoneAccount} or the associated {@link PhoneAccount} is not
-     * currently enabled by the user.
+     * For a managed {@link ConnectionService}, a {@link SecurityException} will be thrown if either
+     * the {@link PhoneAccountHandle} does not correspond to a registered {@link PhoneAccount} or
+     * the associated {@link PhoneAccount} is not currently enabled by the user.
+     * <p>
+     * For a self-managed {@link ConnectionService}, a {@link SecurityException} will be thrown if
+     * the {@link PhoneAccount} has {@link PhoneAccount#CAPABILITY_SELF_MANAGED} and the calling app
+     * does not have {@link android.Manifest.permission#MANAGE_OWN_CALLS}.
+     *
      * @param phoneAccount A {@link PhoneAccountHandle} registered with
      *            {@link #registerPhoneAccount}.
      * @param extras A bundle that will be passed through to
@@ -1379,7 +1387,8 @@
      * method-caller is either the user selected default dialer app or preloaded system dialer
      * app, then emergency calls will also be allowed.
      *
-     * Requires permission: {@link android.Manifest.permission#CALL_PHONE}
+     * Placing a call via a managed {@link ConnectionService} requires permission:
+     * {@link android.Manifest.permission#CALL_PHONE}
      *
      * Usage example:
      * <pre>
@@ -1396,11 +1405,20 @@
      *   <li>{@link #EXTRA_START_CALL_WITH_SPEAKERPHONE}</li>
      *   <li>{@link #EXTRA_START_CALL_WITH_VIDEO_STATE}</li>
      * </ul>
+     * <p>
+     * An app which implements the self-managed {@link ConnectionService} API uses
+     * {@link #placeCall(Uri, Bundle)} to inform Telecom of a new outgoing call.  A self-managed
+     * {@link ConnectionService} must include {@link #EXTRA_PHONE_ACCOUNT_HANDLE} to specify its
+     * associated {@link android.telecom.PhoneAccountHandle}.
+     *
+     * Self-managed {@link ConnectionService}s require permission
+     * {@link android.Manifest.permission#MANAGE_OWN_CALLS}.
      *
      * @param address The address to make the call to.
      * @param extras Bundle of extras to use with the call.
      */
-    @RequiresPermission(android.Manifest.permission.CALL_PHONE)
+    @RequiresPermission(anyOf = {android.Manifest.permission.CALL_PHONE,
+            android.Manifest.permission.MANAGE_OWN_CALLS})
     public void placeCall(Uri address, Bundle extras) {
         ITelecomService service = getTelecomService();
         if (service != null) {
@@ -1476,6 +1494,71 @@
         return result;
     }
 
+    /**
+     * Determines whether Telecom would permit an incoming call to be added via the
+     * {@link #addNewIncomingCall(PhoneAccountHandle, Bundle)} API for the specified
+     * {@link PhoneAccountHandle}.
+     * <p>
+     * A {@link ConnectionService} may not add a call for the specified {@link PhoneAccountHandle}
+     * in the following situations:
+     * <ul>
+     *     <li>{@link PhoneAccount} does not have property
+     *     {@link PhoneAccount#CAPABILITY_SELF_MANAGED} set (i.e. it is a managed
+     *     {@link ConnectionService}), and the active or held call limit has
+     *     been reached.</li>
+     *     <li>There is an ongoing emergency call.</li>
+     * </ul>
+     *
+     * @param phoneAccountHandle The {@link PhoneAccountHandle} the call will be added for.
+     * @return {@code true} if telecom will permit an incoming call to be added, {@code false}
+     *      otherwise.
+     */
+    public boolean isIncomingCallPermitted(PhoneAccountHandle phoneAccountHandle) {
+        ITelecomService service = getTelecomService();
+        if (service != null) {
+            try {
+                return service.isIncomingCallPermitted(phoneAccountHandle);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error isIncomingCallPermitted", e);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Determines whether Telecom would permit an outgoing call to be placed via the
+     * {@link #placeCall(Uri, Bundle)} API for the specified {@link PhoneAccountHandle}.
+     * <p>
+     * A {@link ConnectionService} may not place a call for the specified {@link PhoneAccountHandle}
+     * in the following situations:
+     * <ul>
+     *     <li>{@link PhoneAccount} does not have property
+     *     {@link PhoneAccount#CAPABILITY_SELF_MANAGED} set (i.e. it is a managed
+     *     {@link ConnectionService}), and the active, held or ringing call limit has
+     *     been reached.</li>
+     *     <li>{@link PhoneAccount} has property {@link PhoneAccount#CAPABILITY_SELF_MANAGED} set
+     *     (i.e. it is a self-managed {@link ConnectionService} and there is an ongoing call in
+     *     another {@link ConnectionService}.</li>
+     *     <li>There is an ongoing emergency call.</li>
+     * </ul>
+     *
+     * @param phoneAccountHandle The {@link PhoneAccountHandle} the call will be added for.
+     * @return {@code true} if telecom will permit an outgoing call to be placed, {@code false}
+     *      otherwise.
+     */
+    public boolean isOutgoingCallPermitted(PhoneAccountHandle phoneAccountHandle) {
+        ITelecomService service = getTelecomService();
+        if (service != null) {
+            try {
+                return service.isOutgoingCallPermitted(phoneAccountHandle);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error isOutgoingCallPermitted", e);
+            }
+        }
+        return false;
+    }
+
+
     private ITelecomService getTelecomService() {
         if (mTelecomServiceOverride != null) {
             return mTelecomServiceOverride;
diff --git a/telecomm/java/android/telecom/package-info.java b/telecomm/java/android/telecom/package-info.java
new file mode 100644
index 0000000..a4140e5
--- /dev/null
+++ b/telecomm/java/android/telecom/package-info.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+/**
+ * The Android Telecom framework is responsible for managing calls on an Android device.  This can
+ * include SIM-based calls using the {@code Telephony} framework, VOIP calls using SIP (e.g. the
+ * {@code SipConnectionService}), or via a third-party VOIP
+ * {@link android.telecom.ConnectionService}.  Telecom acts as a switchboard, routing calls and
+ * audio focus between {@link android.telecom.Connection}s provided by
+ * {@link android.telecom.ConnectionService} implementations, and
+ * {@link android.telecom.InCallService} implementations which provide a user interface for calls.
+ * <p>
+ * Android supports the following calling use cases (with increasing level of complexity):
+ * <ul>
+ *     <li>Implement the self-managed {@link android.telecom.ConnectionService} API - this is ideal
+ *     for developers of standalone calling apps which do not wish to show their calls within the
+ *     default phone app, and do not wish to have other calls shown in their user interface.  Using
+ *     a self-managed {@link android.telecom.ConnectionService} implementation within your
+ *     standalone calling app helps you ensure that your app will interoperate not only with native
+ *     telephony calling on the device, but also other standalone calling apps implementing this
+ *     API.  It also manages audio routing and focus for you.</li>
+ *     <li>Implement the managed {@link android.telecom.ConnectionService} API - facilitates
+ *     development of a calling solution that relies on the existing device phone application (see
+ *     {@link android.telecom.TelecomManager#getDefaultDialerPackage()}) to provide the user
+ *     interface for calls.  An example might be a third party implementation of SIP calling, or a
+ *     VOIP calling service.  A {@link android.telecom.ConnectionService} alone provides only the
+ *     means of connecting calls, but has no associated user interface.</li>
+ *     <li>Implement the {@link android.telecom.InCallService} API - facilitates development of a
+ *     replacement for the device's default Phone/Dialer app.  The
+ *     {@link android.telecom.InCallService} alone does not have any calling capability and consists
+ *     of the user-interface side of calling only.  An {@link android.telecom.InCallService} must
+ *     handle all Calls the Telecom framework is aware of.  It must not make assumptions about the
+ *     nature of the calls (e.g. assuming calls are SIM-based telephony calls), and should not
+ *     implement calling restrictions based on any one {@link android.telecom.ConnectionService}
+ *     (e.g. it should not enforce Telephony restrictions for video calls).</li>
+ *     <li>Implement both the {@link android.telecom.InCallService} and
+ *     {@link android.telecom.ConnectionService} API - ideal if you wish to create your own
+ *     {@link android.telecom.ConnectionService} based calling solution, complete with its own
+ *     full user interface, while showing all other Android calls in the same user interface.  Using
+ *     this approach, you must still ensure that your {@link android.telecom.InCallService} makes
+ *     no assumption about the source of the calls it displays.  You must also ensure that your
+ *     {@link android.telecom.ConnectionService} implementation can still function without the
+ *     default phone app being set to your custom {@link android.telecom.InCallService}.</li>
+ * </ul>
+ */
+package android.telecom;
\ No newline at end of file
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 002c3bb..b58f8bc 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -102,6 +102,8 @@
 
     void removeExtras(String callId, in List<String> keys, in Session.Info sessionInfo);
 
+    void setAudioRoute(String callId, int audioRoute, in Session.Info sessionInfo);
+
     void onConnectionEvent(String callId, String event, in Bundle extras,
     in Session.Info sessionInfo);
 }
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 5c412e7..6ca0bc5 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -249,4 +249,14 @@
     * @see TelecomServiceImpl#createManageBlockedNumbersIntent
     **/
     Intent createManageBlockedNumbersIntent();
+
+    /**
+     * @see TelecomServiceImpl#isIncomingCallPermitted
+     */
+    boolean isIncomingCallPermitted(in PhoneAccountHandle phoneAccountHandle);
+
+    /**
+     * @see TelecomServiceImpl#isOutgoingCallPermitted
+     */
+    boolean isOutgoingCallPermitted(in PhoneAccountHandle phoneAccountHandle);
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 288c9ab..c0a86d6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -878,39 +878,6 @@
      public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
 
     /**
-     * A list of component name of carrier signalling receivers which are interested in intent
-     * android.intent.action.CARRIER_SIGNAL_REDIRECTED.
-     * Example:
-     * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameA</item>
-     * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameB</item>
-     * @hide
-     */
-    public static final String KEY_SIGNAL_REDIRECTION_RECEIVER_STRING_ARRAY =
-            "signal_redirection_receiver_string_array";
-
-    /**
-     * A list of component name of carrier signalling receivers which are interested in intent
-     * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED.
-     * Example:
-     * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameA</item>
-     * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameB</item>
-     * @hide
-     */
-    public static final String KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY =
-            "signal_dcfailure_receiver_string_array";
-
-    /**
-     * A list of component name of carrier signalling receivers which are interested in intent
-     * android.intent.action.CARRIER_SIGNAL_PCO_VALUE.
-     * Example:
-     * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameA</item>
-     * <item>com.google.android.carrierPackageName/.CarrierSignalReceiverNameB</item>
-     * @hide
-     */
-    public static final String KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY =
-            "signal_pco_receiver_string_array";
-
-    /**
      * Defines carrier-specific actions which act upon
      * android.intent.action.CARRIER_SIGNAL_REDIRECTED, used for customization of the
      * default carrier app
@@ -963,6 +930,42 @@
             "carrier_default_redirection_url_string_array";
 
     /**
+     * Each config includes the componentName of the carrier app, followed by a list of interesting
+     * signals(declared in the manifest) which could wake up the app.
+     * @see com.android.internal.telephony.TelephonyIntents
+     * Example:
+     * <item>com.google.android.carrierAPK/.CarrierSignalReceiverA:
+     * android.intent.action.CARRIER_SIGNAL_REDIRECTED,
+     * android.intent.action.CARRIER_SIGNAL_PCO_VALUE
+     * </item>
+     * <item>com.google.android.carrierAPK/.CarrierSignalReceiverB:
+     * android.intent.action.CARRIER_SIGNAL_PCO_VALUE
+     * </item>
+     * @hide
+     */
+    public static final String KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY =
+            "carrier_app_wake_signal_config";
+
+    /**
+     * Each config includes the componentName of the carrier app, followed by a list of interesting
+     * signals for the app during run-time. The list of signals(intents) are targeting on run-time
+     * broadcast receivers only, aiming to avoid unnecessary wake-ups and should not be declared in
+     * the app's manifest.
+     * @see com.android.internal.telephony.TelephonyIntents
+     * Example:
+     * <item>com.google.android.carrierAPK/.CarrierSignalReceiverA:
+     * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
+     * android.intent.action.CARRIER_SIGNAL_PCO_VALUE
+     * </item>
+     * <item>com.google.android.carrierAPK/.CarrierSignalReceiverB:
+     * android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
+     * </item>
+     * @hide
+     */
+    public static final String KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY =
+            "carrier_app_no_wake_signal_config";
+
+    /**
      * Determines whether the carrier supports making non-emergency phone calls while the phone is
      * in emergency callback mode.  Default value is {@code true}, meaning that non-emergency calls
      * are allowed in emergency callback mode.
@@ -1413,10 +1416,14 @@
         sDefaults.putString(KEY_RCS_CONFIG_SERVER_URL_STRING, "");
 
         // Carrier Signalling Receivers
-        sDefaults.putStringArray(KEY_SIGNAL_REDIRECTION_RECEIVER_STRING_ARRAY, null);
-        sDefaults.putStringArray(KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY, null);
-        sDefaults.putStringArray(KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY, null);
         sDefaults.putString(KEY_CARRIER_SETUP_APP_STRING, "");
+        sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
+                new String[]{
+                        "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" +
+                                "android.intent.action.CARRIER_SIGNAL_REDIRECTED"
+                });
+        sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
+
 
         // Default carrier app configurations
         sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY,
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index eb838fa..a3f7c18 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5809,10 +5809,17 @@
      * Set the allowed carrier list for slotId
      * Require system privileges. In the future we may add this to carrier APIs.
      *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+     *
+     * <p>This method works only on devices with {@link
+     * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
+     *
      * @return The number of carriers set successfully. Should be length of
      * carrierList on success; -1 on error.
      * @hide
      */
+    @SystemApi
     public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) {
         try {
             ITelephony service = getITelephony();
@@ -5821,6 +5828,8 @@
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
+        } catch (NullPointerException e) {
+            Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
         }
         return -1;
     }
@@ -5829,10 +5838,17 @@
      * Get the allowed carrier list for slotId.
      * Require system privileges. In the future we may add this to carrier APIs.
      *
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
+     *
+     * <p>This method returns valid data on devices with {@link
+     * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
+     *
      * @return List of {@link android.telephony.CarrierIdentifier}; empty list
      * means all carriers are allowed.
      * @hide
      */
+    @SystemApi
     public List<CarrierIdentifier> getAllowedCarriers(int slotId) {
         try {
             ITelephony service = getITelephony();
@@ -5841,6 +5857,8 @@
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
+        } catch (NullPointerException e) {
+            Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
         }
         return new ArrayList<CarrierIdentifier>(0);
     }
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index bcc68b3..b6e701e 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -19,6 +19,7 @@
 import android.annotation.SystemApi;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
+import android.app.Notification;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -513,6 +514,12 @@
     }
 
     @Override
+    public ComponentName startServiceInForeground(Intent service,
+            int id, Notification notification) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean stopService(Intent service) {
         throw new UnsupportedOperationException();
     }
@@ -525,6 +532,13 @@
 
     /** @hide */
     @Override
+    public ComponentName startServiceInForegroundAsUser(Intent service,
+            int id, Notification notification, UserHandle user) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** @hide */
+    @Override
     public boolean stopServiceAsUser(Intent service, UserHandle user) {
         throw new UnsupportedOperationException();
     }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index d62c30d..46b6403 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -1103,6 +1103,29 @@
         UNAVAILABLE
     }
 
+    private static class CallbackInfo {
+        public final CallbackState state;
+        public final Network network;
+        public final Object arg;
+        public CallbackInfo(CallbackState s, Network n, Object o) {
+            state = s; network = n; arg = o;
+        }
+        public String toString() {
+            return String.format("%s (%s)", state, network);
+        }
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof CallbackInfo)) return false;
+            // Ignore timeMs, since it's unpredictable.
+            CallbackInfo other = (CallbackInfo) o;
+            return (state == other.state) && Objects.equals(network, other.network);
+        }
+        @Override
+        public int hashCode() {
+            return Objects.hash(state, network);
+        }
+    }
+
     /**
      * Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
      * this class receives, by calling expectCallback() exactly once each time a callback is
@@ -1114,21 +1137,6 @@
         // the linger timeout.
         private final static int TIMEOUT_MS = 50;
 
-        private class CallbackInfo {
-            public final CallbackState state;
-            public final Network network;
-            public Object arg;
-            public CallbackInfo(CallbackState s, Network n, Object o) {
-                state = s; network = n; arg = o;
-            }
-            public String toString() { return String.format("%s (%s)", state, network); }
-            public boolean equals(Object o) {
-                if (!(o instanceof CallbackInfo)) return false;
-                // Ignore timeMs, since it's unpredictable.
-                CallbackInfo other = (CallbackInfo) o;
-                return state == other.state && Objects.equals(network, other.network);
-            }
-        }
         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
 
         protected void setLastCallback(CallbackState state, Network network, Object o) {
@@ -1155,17 +1163,24 @@
             setLastCallback(CallbackState.LOST, network, null);
         }
 
+        CallbackInfo nextCallback(int timeoutMs) {
+            CallbackInfo cb = null;
+            try {
+                cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+            }
+            if (cb == null) {
+                // LinkedBlockingQueue.poll() returns null if it timeouts.
+                fail("Did not receive callback after " + timeoutMs + "ms");
+            }
+            return cb;
+        }
+
         void expectCallback(CallbackState state, MockNetworkAgent mockAgent, int timeoutMs) {
             CallbackInfo expected = new CallbackInfo(
                     state, (mockAgent != null) ? mockAgent.getNetwork() : null, 0);
-            CallbackInfo actual;
-            try {
-                actual = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
-                assertEquals("Unexpected callback:", expected, actual);
-            } catch (InterruptedException e) {
-                fail("Did not receive expected " + expected + " after " + TIMEOUT_MS + "ms");
-                actual = null;  // Or the compiler can't tell it's never used uninitialized.
-            }
+            CallbackInfo actual = nextCallback(timeoutMs);
+            assertEquals("Unexpected callback:", expected, actual);
             if (state == CallbackState.LOSING) {
                 String msg = String.format(
                         "Invalid linger time value %d, must be between %d and %d",
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index 00420e9..b4d4871 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -73,8 +73,8 @@
         assertFalse(unm.mobileNetworkRequested());
         // Given a null Context, and therefore a null ConnectivityManager,
         // these would cause an exception, if they actually attempted anything.
-        unm.mobileUpstreamRequiresDun(true);
-        unm.mobileUpstreamRequiresDun(false);
+        unm.updateMobileRequiresDun(true);
+        unm.updateMobileRequiresDun(false);
     }
 
     @Test
@@ -109,7 +109,7 @@
         assertFalse(mUNM.mobileNetworkRequested());
         assertEquals(0, mCM.requested.size());
 
-        mUNM.mobileUpstreamRequiresDun(false);
+        mUNM.updateMobileRequiresDun(false);
         assertFalse(mUNM.mobileNetworkRequested());
         assertEquals(0, mCM.requested.size());
 
@@ -135,7 +135,7 @@
         assertFalse(mUNM.mobileNetworkRequested());
         assertEquals(0, mCM.requested.size());
 
-        mUNM.mobileUpstreamRequiresDun(true);
+        mUNM.updateMobileRequiresDun(true);
         assertFalse(mUNM.mobileNetworkRequested());
         assertEquals(0, mCM.requested.size());
 
diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp
index 565d2f0..d0026a2 100644
--- a/tools/aapt/AaptConfig.cpp
+++ b/tools/aapt/AaptConfig.cpp
@@ -131,6 +131,22 @@
         part = parts[index].string();
     }
 
+    if (parseWideColorGamut(part, &config)) {
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index].string();
+    }
+
+    if (parseHdr(part, &config)) {
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index].string();
+    }
+
     if (parseOrientation(part, &config)) {
         index++;
         if (index == N) {
@@ -250,7 +266,9 @@
 
     uint16_t minSdk = 0;
     if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
-                == ResTable_config::UI_MODE_TYPE_VR_HEADSET) {
+                == ResTable_config::UI_MODE_TYPE_VR_HEADSET
+            || config->colorimetry & ResTable_config::MASK_WIDE_COLOR_GAMUT
+            || config->colorimetry & ResTable_config::MASK_HDR) {
         minSdk = SDK_O;
     } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
         minSdk = SDK_MNC;
@@ -431,6 +449,46 @@
     return false;
 }
 
+bool parseWideColorGamut(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT)
+                | ResTable_config::WIDE_COLOR_GAMUT_ANY;
+        return true;
+    } else if (strcmp(name, "widecg") == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT)
+                | ResTable_config::WIDE_COLOR_GAMUT_YES;
+        return true;
+    } else if (strcmp(name, "nowidecg") == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_WIDE_COLOR_GAMUT)
+                | ResTable_config::WIDE_COLOR_GAMUT_NO;
+        return true;
+    }
+    return false;
+}
+
+bool parseHdr(const char* name, ResTable_config* out) {
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_HDR)
+                | ResTable_config::HDR_ANY;
+        return true;
+    } else if (strcmp(name, "highdr") == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_HDR)
+                | ResTable_config::HDR_YES;
+        return true;
+    } else if (strcmp(name, "lowdr") == 0) {
+        if (out) out->colorimetry =
+                (out->colorimetry&~ResTable_config::MASK_HDR)
+                | ResTable_config::HDR_NO;
+        return true;
+    }
+    return false;
+}
+
 bool parseOrientation(const char* name, ResTable_config* out) {
     if (strcmp(name, kWildcardName) == 0) {
         if (out) out->orientation = out->ORIENTATION_ANY;
diff --git a/tools/aapt/AaptConfig.h b/tools/aapt/AaptConfig.h
index 04c763f..a6dd252 100644
--- a/tools/aapt/AaptConfig.h
+++ b/tools/aapt/AaptConfig.h
@@ -61,6 +61,8 @@
 bool parseScreenLayoutSize(const char* str, android::ResTable_config* out = NULL);
 bool parseScreenLayoutLong(const char* str, android::ResTable_config* out = NULL);
 bool parseScreenRound(const char* name, android::ResTable_config* out = NULL);
+bool parseWideColorGamut(const char* name, android::ResTable_config* out = NULL);
+bool parseHdr(const char* name, android::ResTable_config* out = NULL);
 bool parseOrientation(const char* str, android::ResTable_config* out = NULL);
 bool parseUiModeType(const char* str, android::ResTable_config* out = NULL);
 bool parseUiModeNight(const char* str, android::ResTable_config* out = NULL);
diff --git a/tools/aapt/tests/AaptConfig_test.cpp b/tools/aapt/tests/AaptConfig_test.cpp
index 8bb38ba..23f61e9 100644
--- a/tools/aapt/tests/AaptConfig_test.cpp
+++ b/tools/aapt/tests/AaptConfig_test.cpp
@@ -98,3 +98,33 @@
     EXPECT_EQ(SDK_MNC, config.sdkVersion);
     EXPECT_EQ(String8("notround-v23"), config.toString());
 }
+
+TEST(AaptConfigTest, WideColorGamutQualifier) {
+    ConfigDescription config;
+    EXPECT_TRUE(TestParse("widecg", &config));
+    EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES,
+              config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT);
+    EXPECT_EQ(SDK_O, config.sdkVersion);
+    EXPECT_EQ(String8("widecg-v26"), config.toString());
+
+    EXPECT_TRUE(TestParse("nowidecg", &config));
+    EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO,
+              config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT);
+    EXPECT_EQ(SDK_O, config.sdkVersion);
+    EXPECT_EQ(String8("nowidecg-v26"), config.toString());
+}
+
+TEST(AaptConfigTest, HdrQualifier) {
+    ConfigDescription config;
+    EXPECT_TRUE(TestParse("highdr", &config));
+    EXPECT_EQ(android::ResTable_config::HDR_YES,
+              config.colorimetry & android::ResTable_config::MASK_HDR);
+    EXPECT_EQ(SDK_O, config.sdkVersion);
+    EXPECT_EQ(String8("highdr-v26"), config.toString());
+
+    EXPECT_TRUE(TestParse("lowdr", &config));
+    EXPECT_EQ(android::ResTable_config::HDR_NO,
+              config.colorimetry & android::ResTable_config::MASK_HDR);
+    EXPECT_EQ(SDK_O, config.sdkVersion);
+    EXPECT_EQ(String8("lowdr-v26"), config.toString());
+}
\ No newline at end of file
diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp
index b1bd401..5bea3ad 100644
--- a/tools/aapt2/ConfigDescription.cpp
+++ b/tools/aapt2/ConfigDescription.cpp
@@ -20,15 +20,16 @@
 #include <vector>
 
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
 
 #include "Locale.h"
 #include "SdkConstants.h"
-#include "util/StringPiece.h"
 #include "util/Util.h"
 
-namespace aapt {
-
 using android::ResTable_config;
+using android::StringPiece;
+
+namespace aapt {
 
 static const char* kWildcardName = "any";
 
@@ -205,6 +206,52 @@
   return false;
 }
 
+static bool parseWideColorGamut(const char* name, ResTable_config* out) {
+  if (strcmp(name, kWildcardName) == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
+          ResTable_config::WIDE_COLOR_GAMUT_ANY;
+    return true;
+  } else if (strcmp(name, "widecg") == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
+          ResTable_config::WIDE_COLOR_GAMUT_YES;
+    return true;
+  } else if (strcmp(name, "nowidecg") == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_WIDE_COLOR_GAMUT) |
+          ResTable_config::WIDE_COLOR_GAMUT_NO;
+    return true;
+  }
+  return false;
+}
+
+static bool parseHdr(const char* name, ResTable_config* out) {
+  if (strcmp(name, kWildcardName) == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_HDR) |
+          ResTable_config::HDR_ANY;
+    return true;
+  } else if (strcmp(name, "highdr") == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_HDR) |
+          ResTable_config::HDR_YES;
+    return true;
+  } else if (strcmp(name, "lowdr") == 0) {
+    if (out)
+      out->colorimetry =
+          (out->colorimetry & ~ResTable_config::MASK_HDR) |
+          ResTable_config::HDR_NO;
+    return true;
+  }
+  return false;
+}
+
 static bool parseOrientation(const char* name, ResTable_config* out) {
   if (strcmp(name, kWildcardName) == 0) {
     if (out) out->orientation = out->ORIENTATION_ANY;
@@ -686,6 +733,20 @@
     }
   }
 
+  if (parseWideColorGamut(part_iter->c_str(), &config)) {
+    ++part_iter;
+    if (part_iter == parts_end) {
+      goto success;
+    }
+  }
+
+  if (parseHdr(part_iter->c_str(), &config)) {
+    ++part_iter;
+    if (part_iter == parts_end) {
+      goto success;
+    }
+  }
+
   if (parseOrientation(part_iter->c_str(), &config)) {
     ++part_iter;
     if (part_iter == parts_end) {
@@ -778,7 +839,9 @@
     ConfigDescription* config) {
   uint16_t min_sdk = 0;
   if ((config->uiMode & ResTable_config::MASK_UI_MODE_TYPE)
-                == ResTable_config::UI_MODE_TYPE_VR_HEADSET) {
+                == ResTable_config::UI_MODE_TYPE_VR_HEADSET ||
+            config->colorimetry & ResTable_config::MASK_WIDE_COLOR_GAMUT ||
+            config->colorimetry & ResTable_config::MASK_HDR) {
         min_sdk = SDK_O;
   } else if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
     min_sdk = SDK_MARSHMALLOW;
@@ -849,6 +912,12 @@
   if ((screenLayout2 | o.screenLayout2) & MASK_SCREENROUND) {
     return !(o.screenLayout2 & MASK_SCREENROUND);
   }
+  if ((colorimetry | o.colorimetry) & MASK_HDR) {
+    return !(o.colorimetry & MASK_HDR);
+  }
+  if ((colorimetry | o.colorimetry) & MASK_WIDE_COLOR_GAMUT) {
+    return !(o.colorimetry & MASK_WIDE_COLOR_GAMUT);
+  }
   if (orientation || o.orientation) return (!o.orientation);
   if ((uiMode | o.uiMode) & MASK_UI_MODE_TYPE) {
     return !(o.uiMode & MASK_UI_MODE_TYPE);
@@ -895,6 +964,9 @@
          !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) ||
          !pred(screenLayout2 & MASK_SCREENROUND,
                o.screenLayout2 & MASK_SCREENROUND) ||
+         !pred(colorimetry & MASK_HDR, o.colorimetry & MASK_HDR) ||
+         !pred(colorimetry & MASK_WIDE_COLOR_GAMUT,
+               o.colorimetry & MASK_WIDE_COLOR_GAMUT) ||
          !pred(orientation, o.orientation) ||
          !pred(touchscreen, o.touchscreen) ||
          !pred(inputFlags & MASK_KEYSHIDDEN, o.inputFlags & MASK_KEYSHIDDEN) ||
diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h
index 97d0f38..65c9617 100644
--- a/tools/aapt2/ConfigDescription.h
+++ b/tools/aapt2/ConfigDescription.h
@@ -20,8 +20,7 @@
 #include <ostream>
 
 #include "androidfw/ResourceTypes.h"
-
-#include "util/StringPiece.h"
+#include "androidfw/StringPiece.h"
 
 namespace aapt {
 
@@ -42,7 +41,7 @@
    * The resulting configuration has the appropriate sdkVersion defined
    * for backwards compatibility.
    */
-  static bool Parse(const StringPiece& str, ConfigDescription* out = nullptr);
+  static bool Parse(const android::StringPiece& str, ConfigDescription* out = nullptr);
 
   /**
    * If the configuration uses an axis that was added after
diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp
index 1d22ce0..b88838a 100644
--- a/tools/aapt2/ConfigDescription_test.cpp
+++ b/tools/aapt2/ConfigDescription_test.cpp
@@ -18,9 +18,12 @@
 
 #include <string>
 
+#include "androidfw/StringPiece.h"
+
 #include "SdkConstants.h"
 #include "test/Test.h"
-#include "util/StringPiece.h"
+
+using android::StringPiece;
 
 namespace aapt {
 
@@ -99,6 +102,36 @@
   EXPECT_EQ(std::string("notround-v23"), config.toString().string());
 }
 
+TEST(ConfigDescriptionTest, TestWideColorGamutQualifier) {
+  ConfigDescription config;
+  EXPECT_TRUE(TestParse("widecg", &config));
+  EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_YES,
+            config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT);
+  EXPECT_EQ(SDK_O, config.sdkVersion);
+  EXPECT_EQ(std::string("widecg-v26"), config.toString().string());
+
+  EXPECT_TRUE(TestParse("nowidecg", &config));
+  EXPECT_EQ(android::ResTable_config::WIDE_COLOR_GAMUT_NO,
+            config.colorimetry & android::ResTable_config::MASK_WIDE_COLOR_GAMUT);
+  EXPECT_EQ(SDK_O, config.sdkVersion);
+  EXPECT_EQ(std::string("nowidecg-v26"), config.toString().string());
+}
+
+TEST(ConfigDescriptionTest, TestHdrQualifier) {
+  ConfigDescription config;
+  EXPECT_TRUE(TestParse("highdr", &config));
+  EXPECT_EQ(android::ResTable_config::HDR_YES,
+            config.colorimetry & android::ResTable_config::MASK_HDR);
+  EXPECT_EQ(SDK_O, config.sdkVersion);
+  EXPECT_EQ(std::string("highdr-v26"), config.toString().string());
+
+  EXPECT_TRUE(TestParse("lowdr", &config));
+  EXPECT_EQ(android::ResTable_config::HDR_NO,
+            config.colorimetry & android::ResTable_config::MASK_HDR);
+  EXPECT_EQ(SDK_O, config.sdkVersion);
+  EXPECT_EQ(std::string("lowdr-v26"), config.toString().string());
+}
+
 TEST(ConfigDescriptionTest, ParseVrAttribute) {
   ConfigDescription config;
   EXPECT_TRUE(TestParse("vrheadset", &config));
diff --git a/tools/aapt2/Diagnostics.h b/tools/aapt2/Diagnostics.h
index 5bc86a9..50e8b33 100644
--- a/tools/aapt2/Diagnostics.h
+++ b/tools/aapt2/Diagnostics.h
@@ -22,9 +22,9 @@
 #include <string>
 
 #include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
 
 #include "Source.h"
-#include "util/StringPiece.h"
 #include "util/Util.h"
 
 namespace aapt {
@@ -38,7 +38,7 @@
  public:
   DiagMessage() = default;
 
-  explicit DiagMessage(const StringPiece& src) : source_(src) {}
+  explicit DiagMessage(const android::StringPiece& src) : source_(src) {}
 
   explicit DiagMessage(const Source& src) : source_(src) {}
 
@@ -59,6 +59,12 @@
   std::stringstream message_;
 };
 
+template <>
+inline DiagMessage& DiagMessage::operator<<(const ::std::u16string& value) {
+  message_ << android::StringPiece16(value);
+  return *this;
+}
+
 struct IDiagnostics {
   virtual ~IDiagnostics() = default;
 
diff --git a/tools/aapt2/Flags.cpp b/tools/aapt2/Flags.cpp
index c98cd37..84977ab 100644
--- a/tools/aapt2/Flags.cpp
+++ b/tools/aapt2/Flags.cpp
@@ -21,20 +21,22 @@
 #include <string>
 #include <vector>
 
-#include "util/StringPiece.h"
+#include "androidfw/StringPiece.h"
+
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 Flags& Flags::RequiredFlag(const StringPiece& name,
                            const StringPiece& description, std::string* value) {
   auto func = [value](const StringPiece& arg) -> bool {
-    *value = arg.ToString();
+    *value = arg.to_string();
     return true;
   };
 
-  flags_.push_back(
-      Flag{name.ToString(), description.ToString(), func, true, 1, false});
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
   return *this;
 }
 
@@ -42,12 +44,11 @@
                                const StringPiece& description,
                                std::vector<std::string>* value) {
   auto func = [value](const StringPiece& arg) -> bool {
-    value->push_back(arg.ToString());
+    value->push_back(arg.to_string());
     return true;
   };
 
-  flags_.push_back(
-      Flag{name.ToString(), description.ToString(), func, true, 1, false});
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, true, 1, false});
   return *this;
 }
 
@@ -55,12 +56,11 @@
                            const StringPiece& description,
                            Maybe<std::string>* value) {
   auto func = [value](const StringPiece& arg) -> bool {
-    *value = arg.ToString();
+    *value = arg.to_string();
     return true;
   };
 
-  flags_.push_back(
-      Flag{name.ToString(), description.ToString(), func, false, 1, false});
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
   return *this;
 }
 
@@ -68,12 +68,11 @@
                                const StringPiece& description,
                                std::vector<std::string>* value) {
   auto func = [value](const StringPiece& arg) -> bool {
-    value->push_back(arg.ToString());
+    value->push_back(arg.to_string());
     return true;
   };
 
-  flags_.push_back(
-      Flag{name.ToString(), description.ToString(), func, false, 1, false});
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
   return *this;
 }
 
@@ -81,12 +80,11 @@
                                const StringPiece& description,
                                std::unordered_set<std::string>* value) {
   auto func = [value](const StringPiece& arg) -> bool {
-    value->insert(arg.ToString());
+    value->insert(arg.to_string());
     return true;
   };
 
-  flags_.push_back(
-      Flag{name.ToString(), description.ToString(), func, false, 1, false});
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 1, false});
   return *this;
 }
 
@@ -97,8 +95,7 @@
     return true;
   };
 
-  flags_.push_back(
-      Flag{name.ToString(), description.ToString(), func, false, 0, false});
+  flags_.push_back(Flag{name.to_string(), description.to_string(), func, false, 0, false});
   return *this;
 }
 
@@ -141,7 +138,7 @@
   for (size_t i = 0; i < args.size(); i++) {
     StringPiece arg = args[i];
     if (*(arg.data()) != '-') {
-      args_.push_back(arg.ToString());
+      args_.push_back(arg.to_string());
       continue;
     }
 
diff --git a/tools/aapt2/Flags.h b/tools/aapt2/Flags.h
index 9feff6b..3b3ae71 100644
--- a/tools/aapt2/Flags.h
+++ b/tools/aapt2/Flags.h
@@ -23,32 +23,30 @@
 #include <unordered_set>
 #include <vector>
 
+#include "androidfw/StringPiece.h"
+
 #include "util/Maybe.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 
 class Flags {
  public:
-  Flags& RequiredFlag(const StringPiece& name, const StringPiece& description,
+  Flags& RequiredFlag(const android::StringPiece& name, const android::StringPiece& description,
                       std::string* value);
-  Flags& RequiredFlagList(const StringPiece& name,
-                          const StringPiece& description,
+  Flags& RequiredFlagList(const android::StringPiece& name, const android::StringPiece& description,
                           std::vector<std::string>* value);
-  Flags& OptionalFlag(const StringPiece& name, const StringPiece& description,
+  Flags& OptionalFlag(const android::StringPiece& name, const android::StringPiece& description,
                       Maybe<std::string>* value);
-  Flags& OptionalFlagList(const StringPiece& name,
-                          const StringPiece& description,
+  Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description,
                           std::vector<std::string>* value);
-  Flags& OptionalFlagList(const StringPiece& name,
-                          const StringPiece& description,
+  Flags& OptionalFlagList(const android::StringPiece& name, const android::StringPiece& description,
                           std::unordered_set<std::string>* value);
-  Flags& OptionalSwitch(const StringPiece& name, const StringPiece& description,
+  Flags& OptionalSwitch(const android::StringPiece& name, const android::StringPiece& description,
                         bool* value);
 
-  void Usage(const StringPiece& command, std::ostream* out);
+  void Usage(const android::StringPiece& command, std::ostream* out);
 
-  bool Parse(const StringPiece& command, const std::vector<StringPiece>& args,
+  bool Parse(const android::StringPiece& command, const std::vector<android::StringPiece>& args,
              std::ostream* outError);
 
   const std::vector<std::string>& GetArgs();
@@ -57,7 +55,7 @@
   struct Flag {
     std::string name;
     std::string description;
-    std::function<bool(const StringPiece& value)> action;
+    std::function<bool(const android::StringPiece& value)> action;
     bool required;
     size_t num_args;
 
diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp
index 78f56c7a..7664fac 100644
--- a/tools/aapt2/Locale.cpp
+++ b/tools/aapt2/Locale.cpp
@@ -72,7 +72,7 @@
   return std::all_of(std::begin(str), std::end(str), ::isdigit);
 }
 
-bool LocaleValue::InitFromFilterString(const StringPiece& str) {
+bool LocaleValue::InitFromFilterString(const android::StringPiece& str) {
   // A locale (as specified in the filter) is an underscore separated name such
   // as "en_US", "en_Latn_US", or "en_US_POSIX".
   std::vector<std::string> parts = util::SplitAndLowercase(str, '_');
diff --git a/tools/aapt2/Locale.h b/tools/aapt2/Locale.h
index fc6c448..3d73b2e 100644
--- a/tools/aapt2/Locale.h
+++ b/tools/aapt2/Locale.h
@@ -21,8 +21,7 @@
 #include <vector>
 
 #include "androidfw/ResourceTypes.h"
-
-#include "util/StringPiece.h"
+#include "androidfw/StringPiece.h"
 
 namespace aapt {
 
@@ -40,7 +39,7 @@
   /**
    * Initialize this LocaleValue from a config string.
    */
-  bool InitFromFilterString(const StringPiece& config);
+  bool InitFromFilterString(const android::StringPiece& config);
 
   /**
    * Initialize this LocaleValue from parts of a vector.
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index a2b216d..74d4019 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -17,7 +17,7 @@
 #include <iostream>
 #include <vector>
 
-#include "util/StringPiece.h"
+#include "androidfw/StringPiece.h"
 
 namespace aapt {
 
@@ -33,10 +33,10 @@
   return 0;
 }
 
-extern int Compile(const std::vector<StringPiece>& args);
-extern int Link(const std::vector<StringPiece>& args);
-extern int Dump(const std::vector<StringPiece>& args);
-extern int Diff(const std::vector<StringPiece>& args);
+extern int Compile(const std::vector<android::StringPiece>& args);
+extern int Link(const std::vector<android::StringPiece>& args);
+extern int Dump(const std::vector<android::StringPiece>& args);
+extern int Diff(const std::vector<android::StringPiece>& args);
 
 }  // namespace aapt
 
@@ -45,12 +45,12 @@
     argv += 1;
     argc -= 1;
 
-    std::vector<aapt::StringPiece> args;
+    std::vector<android::StringPiece> args;
     for (int i = 1; i < argc; i++) {
       args.push_back(argv[i]);
     }
 
-    aapt::StringPiece command(argv[0]);
+    android::StringPiece command(argv[0]);
     if (command == "compile" || command == "c") {
       return aapt::Compile(args);
     } else if (command == "link" || command == "l") {
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
index 3eef7aa7..fdabce1 100644
--- a/tools/aapt2/Resource.cpp
+++ b/tools/aapt2/Resource.cpp
@@ -19,6 +19,8 @@
 #include <map>
 #include <string>
 
+using android::StringPiece;
+
 namespace aapt {
 
 StringPiece ToString(ResourceType type) {
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 13330b5..1950ea3 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -24,11 +24,11 @@
 #include <tuple>
 #include <vector>
 
+#include "androidfw/StringPiece.h"
 #include "utils/JenkinsHash.h"
 
 #include "ConfigDescription.h"
 #include "Source.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 
@@ -63,13 +63,13 @@
   kXml,
 };
 
-StringPiece ToString(ResourceType type);
+android::StringPiece ToString(ResourceType type);
 
 /**
  * Returns a pointer to a valid ResourceType, or nullptr if
  * the string was invalid.
  */
-const ResourceType* ParseResourceType(const StringPiece& str);
+const ResourceType* ParseResourceType(const android::StringPiece& str);
 
 /**
  * A resource's name. This can uniquely identify
@@ -81,7 +81,7 @@
   std::string entry;
 
   ResourceName() = default;
-  ResourceName(const StringPiece& p, ResourceType t, const StringPiece& e);
+  ResourceName(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
 
   int compare(const ResourceName& other) const;
 
@@ -96,15 +96,15 @@
  * of the original string.
  */
 struct ResourceNameRef {
-  StringPiece package;
+  android::StringPiece package;
   ResourceType type = ResourceType::kRaw;
-  StringPiece entry;
+  android::StringPiece entry;
 
   ResourceNameRef() = default;
   ResourceNameRef(const ResourceNameRef&) = default;
   ResourceNameRef(ResourceNameRef&&) = default;
   ResourceNameRef(const ResourceName& rhs);  // NOLINT(implicit)
-  ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e);
+  ResourceNameRef(const android::StringPiece& p, ResourceType t, const android::StringPiece& e);
   ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
   ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
   ResourceNameRef& operator=(const ResourceName& rhs);
@@ -258,9 +258,9 @@
 // ResourceName implementation.
 //
 
-inline ResourceName::ResourceName(const StringPiece& p, ResourceType t,
-                                  const StringPiece& e)
-    : package(p.ToString()), type(t), entry(e.ToString()) {}
+inline ResourceName::ResourceName(const android::StringPiece& p, ResourceType t,
+                                  const android::StringPiece& e)
+    : package(p.to_string()), type(t), entry(e.to_string()) {}
 
 inline int ResourceName::compare(const ResourceName& other) const {
   int cmp = package.compare(other.package);
@@ -311,8 +311,8 @@
 inline ResourceNameRef::ResourceNameRef(const ResourceName& rhs)
     : package(rhs.package), type(rhs.type), entry(rhs.entry) {}
 
-inline ResourceNameRef::ResourceNameRef(const StringPiece& p, ResourceType t,
-                                        const StringPiece& e)
+inline ResourceNameRef::ResourceNameRef(const android::StringPiece& p, ResourceType t,
+                                        const android::StringPiece& e)
     : package(p), type(t), entry(e) {}
 
 inline ResourceNameRef& ResourceNameRef::operator=(const ResourceName& rhs) {
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index b16def4..79379fe 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -29,6 +29,8 @@
 #include "util/Util.h"
 #include "xml/XmlPullParser.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 constexpr const char* sXliffNamespaceUri =
@@ -101,7 +103,7 @@
   StringPiece trimmed_comment = util::TrimWhitespace(res->comment);
   if (trimmed_comment.size() != res->comment.size()) {
     // Only if there was a change do we re-assign.
-    res->comment = trimmed_comment.ToString();
+    res->comment = trimmed_comment.to_string();
   }
 
   if (res->symbol_state) {
@@ -297,7 +299,7 @@
     // Extract the product name if it exists.
     if (Maybe<StringPiece> maybe_product =
             xml::FindNonEmptyAttribute(parser, "product")) {
-      parsed_resource.product = maybe_product.value().ToString();
+      parsed_resource.product = maybe_product.value().to_string();
     }
 
     // Parse the resource regardless of product.
@@ -383,7 +385,7 @@
     // Items have their type encoded in the type attribute.
     if (Maybe<StringPiece> maybe_type =
             xml::FindNonEmptyAttribute(parser, "type")) {
-      resource_type = maybe_type.value().ToString();
+      resource_type = maybe_type.value().to_string();
     } else {
       diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
                    << "<item> must have a 'type' attribute");
@@ -419,7 +421,7 @@
     }
 
     out_resource->name.type = ResourceType::kId;
-    out_resource->name.entry = maybe_name.value().ToString();
+    out_resource->name.entry = maybe_name.value().to_string();
     out_resource->value = util::make_unique<Id>();
     return true;
   }
@@ -436,7 +438,7 @@
     }
 
     out_resource->name.type = item_iter->second.type;
-    out_resource->name.entry = maybe_name.value().ToString();
+    out_resource->name.entry = maybe_name.value().to_string();
 
     // Only use the implicit format for this type if it wasn't overridden.
     if (!resource_format) {
@@ -461,7 +463,7 @@
         return false;
       }
 
-      out_resource->name.entry = maybe_name.value().ToString();
+      out_resource->name.entry = maybe_name.value().to_string();
     }
 
     // Call the associated parse method. The type will be filled in by the
@@ -484,7 +486,7 @@
     }
 
     out_resource->name.type = *parsed_type;
-    out_resource->name.entry = maybe_name.value().ToString();
+    out_resource->name.entry = maybe_name.value().to_string();
     out_resource->value =
         ParseXml(parser, android::ResTable_map::TYPE_REFERENCE, kNoRawString);
     if (!out_resource->value) {
@@ -718,7 +720,7 @@
   const size_t depth = parser->depth();
   while (xml::XmlPullParser::NextChildNode(parser, depth)) {
     if (parser->event() == xml::XmlPullParser::Event::kComment) {
-      comment = util::TrimWhitespace(parser->comment()).ToString();
+      comment = util::TrimWhitespace(parser->comment()).to_string();
       continue;
     } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) {
       // Skip text.
@@ -754,7 +756,7 @@
 
       ParsedResource child_resource;
       child_resource.name.type = *parsed_type;
-      child_resource.name.entry = maybe_name.value().ToString();
+      child_resource.name.entry = maybe_name.value().to_string();
       child_resource.id = next_id;
       child_resource.comment = std::move(comment);
       child_resource.source = item_source;
@@ -899,7 +901,7 @@
   const size_t depth = parser->depth();
   while (xml::XmlPullParser::NextChildNode(parser, depth)) {
     if (parser->event() == xml::XmlPullParser::Event::kComment) {
-      comment = util::TrimWhitespace(parser->comment()).ToString();
+      comment = util::TrimWhitespace(parser->comment()).to_string();
       continue;
     } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) {
       // Skip text.
@@ -1288,7 +1290,7 @@
   const size_t depth = parser->depth();
   while (xml::XmlPullParser::NextChildNode(parser, depth)) {
     if (parser->event() == xml::XmlPullParser::Event::kComment) {
-      comment = util::TrimWhitespace(parser->comment()).ToString();
+      comment = util::TrimWhitespace(parser->comment()).to_string();
       continue;
     } else if (parser->event() != xml::XmlPullParser::Event::kStartElement) {
       // Ignore text.
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index 11b1e5b..c12dacf 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -20,6 +20,7 @@
 #include <memory>
 
 #include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
 
 #include "ConfigDescription.h"
 #include "Diagnostics.h"
@@ -27,7 +28,6 @@
 #include "ResourceValues.h"
 #include "StringPool.h"
 #include "util/Maybe.h"
-#include "util/StringPiece.h"
 #include "xml/XmlPullParser.h"
 
 namespace aapt {
@@ -101,7 +101,7 @@
   bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource,
                      bool weak);
   Maybe<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser,
-                                               const StringPiece& tag);
+                                               const android::StringPiece& tag);
   bool ParseStyle(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseStyleItem(xml::XmlPullParser* parser, Style* style);
   bool ParseDeclareStyleable(xml::XmlPullParser* parser,
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 2463911..5762fb0 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -25,6 +25,8 @@
 #include "test/Test.h"
 #include "xml/XmlPullParser.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 constexpr const char* kXmlPreamble =
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 4e6a50a..dd78750 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -28,6 +28,8 @@
 #include <string>
 #include <tuple>
 
+using android::StringPiece;
+
 namespace aapt {
 
 static bool less_than_type(const std::unique_ptr<ResourceTableType>& lhs,
@@ -87,7 +89,7 @@
 
   std::unique_ptr<ResourceTablePackage> new_package =
       util::make_unique<ResourceTablePackage>();
-  new_package->name = name.ToString();
+  new_package->name = name.to_string();
   return packages.emplace(iter, std::move(new_package))->get();
 }
 
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index a0c3217..0fe966c 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -25,7 +25,9 @@
 #include "StringPool.h"
 #include "io/File.h"
 
-#include <android-base/macros.h>
+#include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
+
 #include <functional>
 #include <map>
 #include <memory>
@@ -68,9 +70,8 @@
    */
   std::unique_ptr<Value> value;
 
-  ResourceConfigValue(const ConfigDescription& config,
-                      const StringPiece& product)
-      : config(config), product(product.ToString()) {}
+  ResourceConfigValue(const ConfigDescription& config, const android::StringPiece& product)
+      : config(config), product(product.to_string()) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
@@ -105,13 +106,13 @@
    */
   std::vector<std::unique_ptr<ResourceConfigValue>> values;
 
-  explicit ResourceEntry(const StringPiece& name) : name(name.ToString()) {}
+  explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
 
   ResourceConfigValue* FindValue(const ConfigDescription& config);
   ResourceConfigValue* FindValue(const ConfigDescription& config,
-                                 const StringPiece& product);
+                                 const android::StringPiece& product);
   ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config,
-                                         const StringPiece& product);
+                                         const android::StringPiece& product);
   std::vector<ResourceConfigValue*> findAllValues(
       const ConfigDescription& config);
   std::vector<ResourceConfigValue*> FindValuesIf(
@@ -150,8 +151,8 @@
 
   explicit ResourceTableType(const ResourceType type) : type(type) {}
 
-  ResourceEntry* FindEntry(const StringPiece& name);
-  ResourceEntry* FindOrCreateEntry(const StringPiece& name);
+  ResourceEntry* FindEntry(const android::StringPiece& name);
+  ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
@@ -195,22 +196,19 @@
                                                Value* incoming);
 
   bool AddResource(const ResourceNameRef& name, const ConfigDescription& config,
-                   const StringPiece& product, std::unique_ptr<Value> value,
+                   const android::StringPiece& product, std::unique_ptr<Value> value,
                    IDiagnostics* diag);
 
   bool AddResource(const ResourceNameRef& name, const ResourceId& res_id,
-                   const ConfigDescription& config, const StringPiece& product,
+                   const ConfigDescription& config, const android::StringPiece& product,
                    std::unique_ptr<Value> value, IDiagnostics* diag);
 
-  bool AddFileReference(const ResourceNameRef& name,
-                        const ConfigDescription& config, const Source& source,
-                        const StringPiece& path, IDiagnostics* diag);
+  bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config,
+                        const Source& source, const android::StringPiece& path, IDiagnostics* diag);
 
-  bool AddFileReferenceAllowMangled(const ResourceNameRef& name,
-                                    const ConfigDescription& config,
-                                    const Source& source,
-                                    const StringPiece& path, io::IFile* file,
-                                    IDiagnostics* diag);
+  bool AddFileReferenceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
+                                    const Source& source, const android::StringPiece& path,
+                                    io::IFile* file, IDiagnostics* diag);
 
   /**
    * Same as AddResource, but doesn't verify the validity of the name. This is
@@ -219,18 +217,13 @@
    * mangled
    * names.
    */
-  bool AddResourceAllowMangled(const ResourceNameRef& name,
-                               const ConfigDescription& config,
-                               const StringPiece& product,
-                               std::unique_ptr<Value> value,
+  bool AddResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
+                               const android::StringPiece& product, std::unique_ptr<Value> value,
                                IDiagnostics* diag);
 
-  bool AddResourceAllowMangled(const ResourceNameRef& name,
-                               const ResourceId& id,
-                               const ConfigDescription& config,
-                               const StringPiece& product,
-                               std::unique_ptr<Value> value,
-                               IDiagnostics* diag);
+  bool AddResourceAllowMangled(const ResourceNameRef& name, const ResourceId& id,
+                               const ConfigDescription& config, const android::StringPiece& product,
+                               std::unique_ptr<Value> value, IDiagnostics* diag);
 
   bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id,
                       const Symbol& symbol, IDiagnostics* diag);
@@ -273,28 +266,23 @@
    * represent the
    * 'current' package before it is known to the ResourceTable.
    */
-  ResourceTablePackage* FindPackage(const StringPiece& name);
+  ResourceTablePackage* FindPackage(const android::StringPiece& name);
 
   ResourceTablePackage* FindPackageById(uint8_t id);
 
-  ResourceTablePackage* CreatePackage(const StringPiece& name,
-                                      Maybe<uint8_t> id = {});
+  ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
 
  private:
-  ResourceTablePackage* FindOrCreatePackage(const StringPiece& name);
+  ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
 
   bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
-                       const ConfigDescription& config,
-                       const StringPiece& product, std::unique_ptr<Value> value,
-                       const char* valid_chars,
-                       const CollisionResolverFunc& conflict_resolver,
-                       IDiagnostics* diag);
+                       const ConfigDescription& config, const android::StringPiece& product,
+                       std::unique_ptr<Value> value, const char* valid_chars,
+                       const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag);
 
-  bool AddFileReferenceImpl(const ResourceNameRef& name,
-                            const ConfigDescription& config,
-                            const Source& source, const StringPiece& path,
-                            io::IFile* file, const char* valid_chars,
-                            IDiagnostics* diag);
+  bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config,
+                            const Source& source, const android::StringPiece& path, io::IFile* file,
+                            const char* valid_chars, IDiagnostics* diag);
 
   bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id,
                           const Symbol& symbol, const char* valid_chars,
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index fce9b33..1123967 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -26,6 +26,9 @@
 #include "util/Files.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+using android::StringPiece16;
+
 namespace aapt {
 namespace ResourceUtils {
 
@@ -59,7 +62,7 @@
     name_out.entry =
         util::Utf16ToUtf8(StringPiece16(name_in.name, name_in.nameLen));
   } else if (name_in.name8) {
-    name_out.entry = StringPiece(name_in.name8, name_in.nameLen).ToString();
+    name_out.entry.assign(name_in.name8, name_in.nameLen);
   } else {
     return {};
   }
@@ -303,9 +306,7 @@
     p++;
   }
 
-  ref.name =
-      ResourceName(package.ToString(), ResourceType::kAttr,
-                   name.empty() ? trimmed_str.ToString() : name.ToString());
+  ref.name = ResourceName(package, ResourceType::kAttr, name.empty() ? trimmed_str : name);
   return Maybe<Reference>(std::move(ref));
 }
 
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 9766f6a..bd3a8e3 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -20,10 +20,11 @@
 #include <functional>
 #include <memory>
 
+#include "androidfw/StringPiece.h"
+
 #include "NameMangler.h"
 #include "Resource.h"
 #include "ResourceValues.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 namespace ResourceUtils {
@@ -37,8 +38,8 @@
  * individual extracted piece to verify that the pieces are valid.
  * Returns false if there was no package but a ':' was present.
  */
-bool ExtractResourceName(const StringPiece& str, StringPiece* out_package,
-                         StringPiece* out_type, StringPiece* out_entry);
+bool ExtractResourceName(const android::StringPiece& str, android::StringPiece* out_package,
+                         android::StringPiece* out_type, android::StringPiece* out_entry);
 
 /**
  * Returns true if the string was parsed as a resource name
@@ -46,7 +47,7 @@
  * `out_resource` set to the parsed resource name and `out_private` set to true
  * if a '*' prefix was present.
  */
-bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_resource,
+bool ParseResourceName(const android::StringPiece& str, ResourceNameRef* out_resource,
                        bool* out_private = nullptr);
 
 /*
@@ -57,28 +58,27 @@
  * If '+' was present in the reference, `out_create` is set to true.
  * If '*' was present in the reference, `out_private` is set to true.
  */
-bool ParseReference(const StringPiece& str, ResourceNameRef* out_reference,
+bool ParseReference(const android::StringPiece& str, ResourceNameRef* out_reference,
                     bool* out_create = nullptr, bool* out_private = nullptr);
 
 /*
  * Returns true if the string is in the form of a resource reference
  * (@[+][package:]type/name).
  */
-bool IsReference(const StringPiece& str);
+bool IsReference(const android::StringPiece& str);
 
 /*
  * Returns true if the string was parsed as an attribute reference
  * (?[package:][type/]name),
  * with `out_reference` set to the parsed reference.
  */
-bool ParseAttributeReference(const StringPiece& str,
-                             ResourceNameRef* out_reference);
+bool ParseAttributeReference(const android::StringPiece& str, ResourceNameRef* out_reference);
 
 /**
  * Returns true if the string is in the form of an attribute
  * reference(?[package:][type/]name).
  */
-bool IsAttributeReference(const StringPiece& str);
+bool IsAttributeReference(const android::StringPiece& str);
 
 /**
  * Convert an android::ResTable::resource_name to an aapt::ResourceName struct.
@@ -90,22 +90,22 @@
  * Returns a boolean value if the string is equal to TRUE, true, True, FALSE,
  * false, or False.
  */
-Maybe<bool> ParseBool(const StringPiece& str);
+Maybe<bool> ParseBool(const android::StringPiece& str);
 
 /**
  * Returns a uint32_t if the string is an integer.
  */
-Maybe<uint32_t> ParseInt(const StringPiece& str);
+Maybe<uint32_t> ParseInt(const android::StringPiece& str);
 
 /**
  * Returns an ID if it the string represented a valid ID.
  */
-Maybe<ResourceId> ParseResourceId(const StringPiece& str);
+Maybe<ResourceId> ParseResourceId(const android::StringPiece& str);
 
 /**
  * Parses an SDK version, which can be an integer, or a letter from A-Z.
  */
-Maybe<int> ParseSdkVersion(const StringPiece& str);
+Maybe<int> ParseSdkVersion(const android::StringPiece& str);
 
 /*
  * Returns a Reference, or None Maybe instance if the string `str` was parsed as
@@ -118,8 +118,7 @@
  * ?[package:]style/<entry> or
  * <package>:[style/]<entry>
  */
-Maybe<Reference> ParseStyleParentReference(const StringPiece& str,
-                                           std::string* out_error);
+Maybe<Reference> ParseStyleParentReference(const android::StringPiece& str, std::string* out_error);
 
 /*
  * Returns a Reference if the string `str` was parsed as a valid XML attribute
@@ -128,7 +127,7 @@
  *
  * package:entry
  */
-Maybe<Reference> ParseXmlAttributeName(const StringPiece& str);
+Maybe<Reference> ParseXmlAttributeName(const android::StringPiece& str);
 
 /*
  * Returns a Reference object if the string was parsed as a resource or
@@ -137,52 +136,52 @@
  * if
  * the '+' was present in the string.
  */
-std::unique_ptr<Reference> TryParseReference(const StringPiece& str,
+std::unique_ptr<Reference> TryParseReference(const android::StringPiece& str,
                                              bool* out_create = nullptr);
 
 /*
  * Returns a BinaryPrimitve object representing @null or @empty if the string
  * was parsed as one.
  */
-std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const StringPiece& str);
+std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const android::StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing a color if the string was parsed
  * as one.
  */
-std::unique_ptr<BinaryPrimitive> TryParseColor(const StringPiece& str);
+std::unique_ptr<BinaryPrimitive> TryParseColor(const android::StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing a boolean if the string was
  * parsed as one.
  */
-std::unique_ptr<BinaryPrimitive> TryParseBool(const StringPiece& str);
+std::unique_ptr<BinaryPrimitive> TryParseBool(const android::StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing an integer if the string was
  * parsed as one.
  */
-std::unique_ptr<BinaryPrimitive> TryParseInt(const StringPiece& str);
+std::unique_ptr<BinaryPrimitive> TryParseInt(const android::StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing a floating point number
  * (float, dimension, etc) if the string was parsed as one.
  */
-std::unique_ptr<BinaryPrimitive> TryParseFloat(const StringPiece& str);
+std::unique_ptr<BinaryPrimitive> TryParseFloat(const android::StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing an enum symbol if the string was
  * parsed as one.
  */
 std::unique_ptr<BinaryPrimitive> TryParseEnumSymbol(const Attribute* enum_attr,
-                                                    const StringPiece& str);
+                                                    const android::StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing a flag symbol if the string was
  * parsed as one.
  */
 std::unique_ptr<BinaryPrimitive> TryParseFlagSymbol(const Attribute* enum_attr,
-                                                    const StringPiece& str);
+                                                    const android::StringPiece& str);
 /*
  * Try to convert a string to an Item for the given attribute. The attribute
  * will
@@ -191,11 +190,11 @@
  * reference to an ID that must be created (@+id/foo).
  */
 std::unique_ptr<Item> TryParseItemForAttribute(
-    const StringPiece& value, const Attribute* attr,
+    const android::StringPiece& value, const Attribute* attr,
     const std::function<void(const ResourceName&)>& on_create_reference = {});
 
 std::unique_ptr<Item> TryParseItemForAttribute(
-    const StringPiece& value, uint32_t type_mask,
+    const android::StringPiece& value, uint32_t type_mask,
     const std::function<void(const ResourceName&)>& on_create_reference = {});
 
 uint32_t AndroidTypeToAttributeTypeMask(uint16_t type);
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index f9c500b..048c692 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -48,8 +48,7 @@
   EXPECT_EQ(ResourceNameRef("android", ResourceType::kColor, "foo"), actual);
   EXPECT_TRUE(actual_priv);
 
-  EXPECT_FALSE(
-      ResourceUtils::ParseResourceName(StringPiece(), &actual, &actual_priv));
+  EXPECT_FALSE(ResourceUtils::ParseResourceName(android::StringPiece(), &actual, &actual_priv));
 }
 
 TEST(ResourceUtilsTest, ParseReferenceWithNoPackage) {
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index ea73615..d380f8d 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -22,6 +22,7 @@
 #include <vector>
 
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
 
 #include "Diagnostics.h"
 #include "Resource.h"
@@ -73,7 +74,7 @@
    */
   const std::string& GetComment() const { return comment_; }
 
-  void SetComment(const StringPiece& str) { comment_ = str.ToString(); }
+  void SetComment(const android::StringPiece& str) { comment_ = str.to_string(); }
 
   void SetComment(std::string&& str) { comment_ = std::move(str); }
 
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index c7f920a..e806714 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -21,6 +21,8 @@
 #include <unordered_map>
 #include <vector>
 
+using android::StringPiece;
+
 namespace aapt {
 
 static const char* sDevelopmentSdkCodeName = "O";
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index 5352b53..98ba94b 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -19,6 +19,8 @@
 
 #include <utility>
 
+#include "androidfw/StringPiece.h"
+
 #include "Resource.h"
 
 namespace aapt {
@@ -52,7 +54,7 @@
 
 size_t FindAttributeSdkLevel(const ResourceId& id);
 size_t FindAttributeSdkLevel(const ResourceName& name);
-std::pair<StringPiece, int> GetDevelopmentSdkCodeNameAndVersion();
+std::pair<android::StringPiece, int> GetDevelopmentSdkCodeNameAndVersion();
 
 }  // namespace aapt
 
diff --git a/tools/aapt2/Source.h b/tools/aapt2/Source.h
index 459a8e6..d7f2a66 100644
--- a/tools/aapt2/Source.h
+++ b/tools/aapt2/Source.h
@@ -20,8 +20,9 @@
 #include <ostream>
 #include <string>
 
+#include "androidfw/StringPiece.h"
+
 #include "util/Maybe.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 
@@ -35,12 +36,11 @@
 
   Source() = default;
 
-  inline Source(const StringPiece& path)
-      : path(path.ToString()) {  // NOLINT(implicit)
+  inline Source(const android::StringPiece& path) : path(path.to_string()) {  // NOLINT(implicit)
   }
 
-  inline Source(const StringPiece& path, size_t line)
-      : path(path.ToString()), line(line) {}
+  inline Source(const android::StringPiece& path, size_t line)
+      : path(path.to_string()), line(line) {}
 
   inline Source WithLine(size_t line) const { return Source(path, line); }
 };
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index 3032829..d968d73 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -22,11 +22,13 @@
 
 #include "android-base/logging.h"
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
 
 #include "util/BigBuffer.h"
-#include "util/StringPiece.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 StringPool::Ref::Ref() : entry_(nullptr) {}
@@ -140,7 +142,7 @@
   }
 
   Entry* entry = new Entry();
-  entry->value = str.ToString();
+  entry->value = str.to_string();
   entry->context = context;
   entry->index = strings_.size();
   entry->ref_ = 0;
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index a4f556c..d0ce489 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -23,9 +23,10 @@
 #include <unordered_map>
 #include <vector>
 
+#include "androidfw/StringPiece.h"
+
 #include "ConfigDescription.h"
 #include "util/BigBuffer.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 
@@ -149,14 +150,14 @@
    * Adds a string to the pool, unless it already exists. Returns
    * a reference to the string in the pool.
    */
-  Ref MakeRef(const StringPiece& str);
+  Ref MakeRef(const android::StringPiece& str);
 
   /**
    * Adds a string to the pool, unless it already exists, with a context
    * object that can be used when sorting the string pool. Returns
    * a reference to the string in the pool.
    */
-  Ref MakeRef(const StringPiece& str, const Context& context);
+  Ref MakeRef(const android::StringPiece& str, const Context& context);
 
   /**
    * Adds a style to the string pool and returns a reference to it.
@@ -208,11 +209,11 @@
 
   static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8);
 
-  Ref MakeRefImpl(const StringPiece& str, const Context& context, bool unique);
+  Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique);
 
   std::vector<std::unique_ptr<Entry>> strings_;
   std::vector<std::unique_ptr<StyleEntry>> styles_;
-  std::unordered_multimap<StringPiece, Entry*> indexed_strings_;
+  std::unordered_multimap<android::StringPiece, Entry*> indexed_strings_;
 };
 
 //
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index e1394fc..f64a8cf 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -18,9 +18,14 @@
 
 #include <string>
 
+#include "androidfw/StringPiece.h"
+
 #include "test/Test.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+using android::StringPiece16;
+
 namespace aapt {
 
 TEST(StringPoolTest, InsertOneString) {
@@ -236,8 +241,7 @@
     EXPECT_EQ(StringPiece16(u"goodbye"), util::GetString16(test, 1));
 
     EXPECT_EQ(StringPiece(sLongString), util::GetString(test, 2));
-    EXPECT_EQ(util::Utf8ToUtf16(sLongString),
-              util::GetString16(test, 2).ToString());
+    EXPECT_EQ(util::Utf8ToUtf16(sLongString), util::GetString16(test, 2).to_string());
 
     size_t len;
     EXPECT_TRUE(test.stringAt(3, &len) != nullptr ||
diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp
index f0b18e6..8027f42 100644
--- a/tools/aapt2/compile/Compile.cpp
+++ b/tools/aapt2/compile/Compile.cpp
@@ -19,6 +19,12 @@
 #include <fstream>
 #include <string>
 
+#include "android-base/errors.h"
+#include "android-base/file.h"
+#include "androidfw/StringPiece.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+
 #include "ConfigDescription.h"
 #include "Diagnostics.h"
 #include "Flags.h"
@@ -38,11 +44,7 @@
 #include "xml/XmlDom.h"
 #include "xml/XmlPullParser.h"
 
-#include "android-base/errors.h"
-#include "android-base/file.h"
-#include "google/protobuf/io/coded_stream.h"
-#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
-
+using android::StringPiece;
 using google::protobuf::io::CopyingOutputStreamAdaptor;
 using google::protobuf::io::ZeroCopyOutputStream;
 
@@ -103,9 +105,8 @@
     name = name.substr(0, dot_pos);
   }
 
-  return ResourcePathData{Source(path),          dir_str.ToString(),
-                          name.ToString(),       extension.ToString(),
-                          config_str.ToString(), config};
+  return ResourcePathData{Source(path),          dir_str.to_string(),    name.to_string(),
+                          extension.to_string(), config_str.to_string(), config};
 }
 
 struct CompileOptions {
diff --git a/tools/aapt2/compile/IdAssigner.h b/tools/aapt2/compile/IdAssigner.h
index 371ec01..9640eb8 100644
--- a/tools/aapt2/compile/IdAssigner.h
+++ b/tools/aapt2/compile/IdAssigner.h
@@ -19,11 +19,11 @@
 
 #include <unordered_map>
 
+#include "android-base/macros.h"
+
 #include "Resource.h"
 #include "process/IResourceTableConsumer.h"
 
-#include "android-base/macros.h"
-
 namespace aapt {
 
 /**
@@ -40,8 +40,7 @@
   bool Consume(IAaptContext* context, ResourceTable* table) override;
 
  private:
-  const std::unordered_map<ResourceName, ResourceId>* assigned_id_map_ =
-      nullptr;
+  const std::unordered_map<ResourceName, ResourceId>* assigned_id_map_ = nullptr;
 };
 
 }  // namespace aapt
diff --git a/tools/aapt2/compile/NinePatch.cpp b/tools/aapt2/compile/NinePatch.cpp
index eab5c97..c931da4 100644
--- a/tools/aapt2/compile/NinePatch.cpp
+++ b/tools/aapt2/compile/NinePatch.cpp
@@ -21,10 +21,12 @@
 #include <vector>
 
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
 
-#include "util/StringPiece.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 // Colors in the format 0xAARRGGBB (the way 9-patch expects it).
diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp
index 7ab05b5..5e15c88 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/tools/aapt2/compile/Png.cpp
@@ -15,18 +15,21 @@
  */
 
 #include "Png.h"
-#include "Source.h"
-#include "util/BigBuffer.h"
-#include "util/Util.h"
 
-#include <androidfw/ResourceTypes.h>
 #include <png.h>
 #include <zlib.h>
+
 #include <iostream>
 #include <sstream>
 #include <string>
 #include <vector>
 
+#include "androidfw/ResourceTypes.h"
+
+#include "Source.h"
+#include "util/BigBuffer.h"
+#include "util/Util.h"
+
 namespace aapt {
 
 constexpr bool kDebug = false;
diff --git a/tools/aapt2/compile/Png.h b/tools/aapt2/compile/Png.h
index aff1da3..a820051 100644
--- a/tools/aapt2/compile/Png.h
+++ b/tools/aapt2/compile/Png.h
@@ -56,7 +56,7 @@
  */
 class PngChunkFilter : public io::InputStream {
  public:
-  explicit PngChunkFilter(const StringPiece& data);
+  explicit PngChunkFilter(const android::StringPiece& data);
 
   bool Next(const void** buffer, int* len) override;
   void BackUp(int count) override;
@@ -71,7 +71,7 @@
  private:
   bool ConsumeWindow(const void** buffer, int* len);
 
-  StringPiece data_;
+  android::StringPiece data_;
   size_t window_start_ = 0;
   size_t window_end_ = 0;
   bool error_ = false;
diff --git a/tools/aapt2/compile/PngChunkFilter.cpp b/tools/aapt2/compile/PngChunkFilter.cpp
index 4cbefb9..edec123 100644
--- a/tools/aapt2/compile/PngChunkFilter.cpp
+++ b/tools/aapt2/compile/PngChunkFilter.cpp
@@ -16,8 +16,11 @@
 
 #include "compile/Png.h"
 
+#include "androidfw/StringPiece.h"
+
 #include "io/Io.h"
-#include "util/StringPiece.h"
+
+using android::StringPiece;
 
 namespace aapt {
 
diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp
index 055a725..5035f81 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp
@@ -23,6 +23,8 @@
 #include "ValueVisitor.h"
 #include "compile/Pseudolocalizer.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 std::unique_ptr<StyledString> PseudolocalizeStyledString(
diff --git a/tools/aapt2/compile/Pseudolocalizer.cpp b/tools/aapt2/compile/Pseudolocalizer.cpp
index f89288f..15a3d8c 100644
--- a/tools/aapt2/compile/Pseudolocalizer.cpp
+++ b/tools/aapt2/compile/Pseudolocalizer.cpp
@@ -18,6 +18,8 @@
 
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 // String basis to generate expansion
@@ -40,10 +42,8 @@
 
 class PseudoMethodNone : public PseudoMethodImpl {
  public:
-  std::string Text(const StringPiece& text) override { return text.ToString(); }
-  std::string Placeholder(const StringPiece& text) override {
-    return text.ToString();
-  }
+  std::string Text(const StringPiece& text) override { return text.to_string(); }
+  std::string Placeholder(const StringPiece& text) override { return text.to_string(); }
 };
 
 class PseudoMethodBidi : public PseudoMethodImpl {
@@ -116,7 +116,7 @@
       }
       size_t size = nextpos - lastpos;
       if (size) {
-        std::string chunk = text.substr(lastpos, size).ToString();
+        std::string chunk = text.substr(lastpos, size).to_string();
         if (pseudo) {
           chunk = impl_->Text(chunk);
         } else if (str[lastpos] == kArgStart && str[nextpos - 1] == kArgEnd) {
@@ -437,7 +437,7 @@
 
 std::string PseudoMethodAccent::Placeholder(const StringPiece& source) {
   // Surround a placeholder with brackets
-  return kPlaceholderOpen + source.ToString() + kPlaceholderClose;
+  return kPlaceholderOpen + source.to_string() + kPlaceholderClose;
 }
 
 std::string PseudoMethodBidi::Text(const StringPiece& source) {
@@ -467,7 +467,7 @@
 
 std::string PseudoMethodBidi::Placeholder(const StringPiece& source) {
   // Surround a placeholder with directionality change sequence
-  return kRlm + kRlo + source.ToString() + kPdf + kRlm;
+  return kRlm + kRlo + source.to_string() + kPdf + kRlm;
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/compile/Pseudolocalizer.h b/tools/aapt2/compile/Pseudolocalizer.h
index a6d2ad0..6cf003b 100644
--- a/tools/aapt2/compile/Pseudolocalizer.h
+++ b/tools/aapt2/compile/Pseudolocalizer.h
@@ -20,10 +20,10 @@
 #include <memory>
 
 #include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
 
 #include "ResourceValues.h"
 #include "StringPool.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 
@@ -32,8 +32,8 @@
   virtual ~PseudoMethodImpl() {}
   virtual std::string Start() { return {}; }
   virtual std::string End() { return {}; }
-  virtual std::string Text(const StringPiece& text) = 0;
-  virtual std::string Placeholder(const StringPiece& text) = 0;
+  virtual std::string Text(const android::StringPiece& text) = 0;
+  virtual std::string Placeholder(const android::StringPiece& text) = 0;
 };
 
 class Pseudolocalizer {
@@ -48,7 +48,7 @@
   void SetMethod(Method method);
   std::string Start() { return impl_->Start(); }
   std::string End() { return impl_->End(); }
-  std::string Text(const StringPiece& text);
+  std::string Text(const android::StringPiece& text);
 
  private:
   std::unique_ptr<PseudoMethodImpl> impl_;
diff --git a/tools/aapt2/compile/Pseudolocalizer_test.cpp b/tools/aapt2/compile/Pseudolocalizer_test.cpp
index 92eb3b5..d3b7b02 100644
--- a/tools/aapt2/compile/Pseudolocalizer_test.cpp
+++ b/tools/aapt2/compile/Pseudolocalizer_test.cpp
@@ -19,6 +19,8 @@
 #include "test/Test.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 // In this context, 'Axis' represents a particular field in the configuration,
diff --git a/tools/aapt2/diff/Diff.cpp b/tools/aapt2/diff/Diff.cpp
index 593e7ab..de0fe40 100644
--- a/tools/aapt2/diff/Diff.cpp
+++ b/tools/aapt2/diff/Diff.cpp
@@ -24,6 +24,8 @@
 #include "process/SymbolTable.h"
 #include "unflatten/BinaryResourceParser.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 class DiffContext : public IAaptContext {
diff --git a/tools/aapt2/dump/Dump.cpp b/tools/aapt2/dump/Dump.cpp
index 2920c2a..bcede72 100644
--- a/tools/aapt2/dump/Dump.cpp
+++ b/tools/aapt2/dump/Dump.cpp
@@ -16,6 +16,8 @@
 
 #include <vector>
 
+#include "androidfw/StringPiece.h"
+
 #include "Debug.h"
 #include "Diagnostics.h"
 #include "Flags.h"
@@ -24,7 +26,8 @@
 #include "proto/ProtoSerialize.h"
 #include "unflatten/BinaryResourceParser.h"
 #include "util/Files.h"
-#include "util/StringPiece.h"
+
+using android::StringPiece;
 
 namespace aapt {
 
diff --git a/tools/aapt2/flatten/Archive.cpp b/tools/aapt2/flatten/Archive.cpp
index 47de0a3..5c96a4d 100644
--- a/tools/aapt2/flatten/Archive.cpp
+++ b/tools/aapt2/flatten/Archive.cpp
@@ -22,10 +22,12 @@
 #include <vector>
 
 #include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
 #include "ziparchive/zip_writer.h"
 
 #include "util/Files.h"
-#include "util/StringPiece.h"
+
+using android::StringPiece;
 
 namespace aapt {
 
@@ -36,7 +38,7 @@
   DirectoryWriter() = default;
 
   bool Open(IDiagnostics* diag, const StringPiece& out_dir) {
-    dir_ = out_dir.ToString();
+    dir_ = out_dir.to_string();
     file::FileType type = file::GetFileType(dir_);
     if (type == file::FileType::kNonexistant) {
       diag->Error(DiagMessage() << "directory " << dir_ << " does not exist");
diff --git a/tools/aapt2/flatten/Archive.h b/tools/aapt2/flatten/Archive.h
index 4fcb3ff..f0681bd 100644
--- a/tools/aapt2/flatten/Archive.h
+++ b/tools/aapt2/flatten/Archive.h
@@ -22,12 +22,12 @@
 #include <string>
 #include <vector>
 
+#include "androidfw/StringPiece.h"
 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 
 #include "Diagnostics.h"
 #include "util/BigBuffer.h"
 #include "util/Files.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 
@@ -46,7 +46,7 @@
  public:
   virtual ~IArchiveWriter() = default;
 
-  virtual bool StartEntry(const StringPiece& path, uint32_t flags) = 0;
+  virtual bool StartEntry(const android::StringPiece& path, uint32_t flags) = 0;
   virtual bool WriteEntry(const BigBuffer& buffer) = 0;
   virtual bool WriteEntry(const void* data, size_t len) = 0;
   virtual bool FinishEntry() = 0;
@@ -57,11 +57,11 @@
   }
 };
 
-std::unique_ptr<IArchiveWriter> CreateDirectoryArchiveWriter(
-    IDiagnostics* diag, const StringPiece& path);
+std::unique_ptr<IArchiveWriter> CreateDirectoryArchiveWriter(IDiagnostics* diag,
+                                                             const android::StringPiece& path);
 
-std::unique_ptr<IArchiveWriter> CreateZipFileArchiveWriter(
-    IDiagnostics* diag, const StringPiece& path);
+std::unique_ptr<IArchiveWriter> CreateZipFileArchiveWriter(IDiagnostics* diag,
+                                                           const android::StringPiece& path);
 
 }  // namespace aapt
 
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index 2c83bb3..ffc2de1 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -23,6 +23,8 @@
 #include "util/BigBuffer.h"
 #include "util/Util.h"
 
+using android::StringPiece16;
+
 namespace aapt {
 
 class XmlFlattenerTest : public ::testing::Test {
diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h
index 644f59f..3d5b5b1 100644
--- a/tools/aapt2/io/File.h
+++ b/tools/aapt2/io/File.h
@@ -110,7 +110,7 @@
  public:
   virtual ~IFileCollection() = default;
 
-  virtual IFile* FindFile(const StringPiece& path) = 0;
+  virtual IFile* FindFile(const android::StringPiece& path) = 0;
   virtual std::unique_ptr<IFileCollectionIterator> Iterator() = 0;
 };
 
diff --git a/tools/aapt2/io/FileSystem.cpp b/tools/aapt2/io/FileSystem.cpp
index 828f34e..027cbd0 100644
--- a/tools/aapt2/io/FileSystem.cpp
+++ b/tools/aapt2/io/FileSystem.cpp
@@ -16,14 +16,16 @@
 
 #include "io/FileSystem.h"
 
+#include "androidfw/StringPiece.h"
 #include "utils/FileMap.h"
 
 #include "Source.h"
 #include "util/Files.h"
 #include "util/Maybe.h"
-#include "util/StringPiece.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 namespace io {
 
@@ -54,13 +56,11 @@
 }
 
 IFile* FileCollection::InsertFile(const StringPiece& path) {
-  return (files_[path.ToString()] =
-              util::make_unique<RegularFile>(Source(path)))
-      .get();
+  return (files_[path.to_string()] = util::make_unique<RegularFile>(Source(path))).get();
 }
 
 IFile* FileCollection::FindFile(const StringPiece& path) {
-  auto iter = files_.find(path.ToString());
+  auto iter = files_.find(path.to_string());
   if (iter != files_.end()) {
     return iter->second.get();
   }
diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h
index 84f851f..dfd3717 100644
--- a/tools/aapt2/io/FileSystem.h
+++ b/tools/aapt2/io/FileSystem.h
@@ -59,8 +59,8 @@
   /**
    * Adds a file located at path. Returns the IFile representation of that file.
    */
-  IFile* InsertFile(const StringPiece& path);
-  IFile* FindFile(const StringPiece& path) override;
+  IFile* InsertFile(const android::StringPiece& path);
+  IFile* FindFile(const android::StringPiece& path) override;
   std::unique_ptr<IFileCollectionIterator> Iterator() override;
 
  private:
diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp
index f4a128e..62b436f 100644
--- a/tools/aapt2/io/ZipArchive.cpp
+++ b/tools/aapt2/io/ZipArchive.cpp
@@ -22,6 +22,8 @@
 #include "Source.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 namespace io {
 
@@ -107,7 +109,7 @@
     std::string zip_entry_path =
         std::string(reinterpret_cast<const char*>(zip_entry_name.name),
                     zip_entry_name.name_length);
-    std::string nested_path = path.ToString() + "@" + zip_entry_path;
+    std::string nested_path = path.to_string() + "@" + zip_entry_path;
     collection->files_[zip_entry_path] = util::make_unique<ZipFile>(
         collection->handle_, zip_data, Source(nested_path));
   }
@@ -120,7 +122,7 @@
 }
 
 IFile* ZipFileCollection::FindFile(const StringPiece& path) {
-  auto iter = files_.find(path.ToString());
+  auto iter = files_.find(path.to_string());
   if (iter != files_.end()) {
     return iter->second.get();
   }
diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h
index 85ca1ae..634adad 100644
--- a/tools/aapt2/io/ZipArchive.h
+++ b/tools/aapt2/io/ZipArchive.h
@@ -21,8 +21,9 @@
 
 #include <map>
 
+#include "androidfw/StringPiece.h"
+
 #include "io/File.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 namespace io {
@@ -64,10 +65,10 @@
  */
 class ZipFileCollection : public IFileCollection {
  public:
-  static std::unique_ptr<ZipFileCollection> Create(const StringPiece& path,
+  static std::unique_ptr<ZipFileCollection> Create(const android::StringPiece& path,
                                                    std::string* outError);
 
-  io::IFile* FindFile(const StringPiece& path) override;
+  io::IFile* FindFile(const android::StringPiece& path) override;
   std::unique_ptr<IFileCollectionIterator> Iterator() override;
 
   ~ZipFileCollection() override;
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index 2951e5c..a0ef00b 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -20,6 +20,8 @@
 
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 void AnnotationProcessor::AppendCommentLine(std::string& comment) {
@@ -54,7 +56,7 @@
   for (StringPiece line : util::Tokenize(comment, '\n')) {
     line = util::TrimWhitespace(line);
     if (!line.empty()) {
-      std::string lineCopy = line.ToString();
+      std::string lineCopy = line.to_string();
       AppendCommentLine(lineCopy);
     }
   }
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index 666a7f3..99cd44f 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -20,7 +20,7 @@
 #include <sstream>
 #include <string>
 
-#include "util/StringPiece.h"
+#include "androidfw/StringPiece.h"
 
 namespace aapt {
 
@@ -58,7 +58,7 @@
    * configurations,
    * we need to collect all the comments.
    */
-  void AppendComment(const StringPiece& comment);
+  void AppendComment(const android::StringPiece& comment);
 
   void AppendNewLine();
 
@@ -66,7 +66,7 @@
    * Writes the comments and annotations to the stream, with the given prefix
    * before each line.
    */
-  void WriteToStream(std::ostream* out, const StringPiece& prefix) const;
+  void WriteToStream(std::ostream* out, const android::StringPiece& prefix) const;
 
  private:
   enum : uint32_t {
diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp
index f1f1f92..53d6ea1 100644
--- a/tools/aapt2/java/ClassDefinition.cpp
+++ b/tools/aapt2/java/ClassDefinition.cpp
@@ -16,7 +16,9 @@
 
 #include "java/ClassDefinition.h"
 
-#include "util/StringPiece.h"
+#include "androidfw/StringPiece.h"
+
+using android::StringPiece;
 
 namespace aapt {
 
@@ -43,7 +45,7 @@
   }
   *out << "final class " << name_ << " {\n";
 
-  std::string new_prefix = prefix.ToString();
+  std::string new_prefix = prefix.to_string();
   new_prefix.append(kIndent);
 
   for (const std::unique_ptr<ClassMember>& member : members_) {
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index d8b61d9..64e4b29 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -21,10 +21,10 @@
 #include <string>
 
 #include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
 
 #include "Resource.h"
 #include "java/AnnotationProcessor.h"
-#include "util/StringPiece.h"
 #include "util/Util.h"
 
 namespace aapt {
@@ -41,7 +41,7 @@
 
   virtual bool empty() const = 0;
 
-  virtual void WriteToStream(const StringPiece& prefix, bool final,
+  virtual void WriteToStream(const android::StringPiece& prefix, bool final,
                              std::ostream* out) const {
     processor_.WriteToStream(out, prefix);
   }
@@ -53,12 +53,12 @@
 template <typename T>
 class PrimitiveMember : public ClassMember {
  public:
-  PrimitiveMember(const StringPiece& name, const T& val)
-      : name_(name.ToString()), val_(val) {}
+  PrimitiveMember(const android::StringPiece& name, const T& val)
+      : name_(name.to_string()), val_(val) {}
 
   bool empty() const override { return false; }
 
-  void WriteToStream(const StringPiece& prefix, bool final,
+  void WriteToStream(const android::StringPiece& prefix, bool final,
                      std::ostream* out) const override {
     ClassMember::WriteToStream(prefix, final, out);
 
@@ -79,12 +79,12 @@
 template <>
 class PrimitiveMember<std::string> : public ClassMember {
  public:
-  PrimitiveMember(const StringPiece& name, const std::string& val)
-      : name_(name.ToString()), val_(val) {}
+  PrimitiveMember(const android::StringPiece& name, const std::string& val)
+      : name_(name.to_string()), val_(val) {}
 
   bool empty() const override { return false; }
 
-  void WriteToStream(const StringPiece& prefix, bool final,
+  void WriteToStream(const android::StringPiece& prefix, bool final,
                      std::ostream* out) const override {
     ClassMember::WriteToStream(prefix, final, out);
 
@@ -106,14 +106,13 @@
 template <typename T>
 class PrimitiveArrayMember : public ClassMember {
  public:
-  explicit PrimitiveArrayMember(const StringPiece& name)
-      : name_(name.ToString()) {}
+  explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {}
 
   void AddElement(const T& val) { elements_.push_back(val); }
 
   bool empty() const override { return false; }
 
-  void WriteToStream(const StringPiece& prefix, bool final,
+  void WriteToStream(const android::StringPiece& prefix, bool final,
                      std::ostream* out) const override {
     ClassMember::WriteToStream(prefix, final, out);
 
@@ -147,22 +146,18 @@
 
 class ClassDefinition : public ClassMember {
  public:
-  static bool WriteJavaFile(const ClassDefinition* def,
-                            const StringPiece& package, bool final,
-                            std::ostream* out);
+  static bool WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package,
+                            bool final, std::ostream* out);
 
-  ClassDefinition(const StringPiece& name, ClassQualifier qualifier,
-                  bool createIfEmpty)
-      : name_(name.ToString()),
-        qualifier_(qualifier),
-        create_if_empty_(createIfEmpty) {}
+  ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty)
+      : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {}
 
   void AddMember(std::unique_ptr<ClassMember> member) {
     members_.push_back(std::move(member));
   }
 
   bool empty() const override;
-  void WriteToStream(const StringPiece& prefix, bool final,
+  void WriteToStream(const android::StringPiece& prefix, bool final,
                      std::ostream* out) const override;
 
  private:
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 6e7c7078..b71dc48 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -23,6 +23,7 @@
 #include <tuple>
 
 #include "android-base/logging.h"
+#include "androidfw/StringPiece.h"
 
 #include "NameMangler.h"
 #include "Resource.h"
@@ -32,7 +33,8 @@
 #include "java/AnnotationProcessor.h"
 #include "java/ClassDefinition.h"
 #include "process/SymbolTable.h"
-#include "util/StringPiece.h"
+
+using android::StringPiece;
 
 namespace aapt {
 
@@ -58,7 +60,7 @@
  * Replace those with '_'.
  */
 static std::string Transform(const StringPiece& symbol) {
-  std::string output = symbol.ToString();
+  std::string output = symbol.to_string();
   for (char& c : output) {
     if (c == '.' || c == '-') {
       c = '_';
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 190e73b..5cf556e 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -20,10 +20,11 @@
 #include <ostream>
 #include <string>
 
+#include "androidfw/StringPiece.h"
+
 #include "ResourceTable.h"
 #include "ResourceValues.h"
 #include "process/IResourceTableConsumer.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 
@@ -69,22 +70,20 @@
    * We need to generate these symbols in a separate file.
    * Returns true on success.
    */
-  bool Generate(const StringPiece& packageNameToGenerate, std::ostream* out);
+  bool Generate(const android::StringPiece& packageNameToGenerate, std::ostream* out);
 
-  bool Generate(const StringPiece& packageNameToGenerate,
-                const StringPiece& outputPackageName, std::ostream* out);
+  bool Generate(const android::StringPiece& packageNameToGenerate,
+                const android::StringPiece& outputPackageName, std::ostream* out);
 
   const std::string& getError() const;
 
  private:
-  bool AddMembersToTypeClass(const StringPiece& packageNameToGenerate,
-                             const ResourceTablePackage* package,
-                             const ResourceTableType* type,
+  bool AddMembersToTypeClass(const android::StringPiece& packageNameToGenerate,
+                             const ResourceTablePackage* package, const ResourceTableType* type,
                              ClassDefinition* outTypeClassDef);
 
-  void AddMembersToStyleableClass(const StringPiece& packageNameToGenerate,
-                                  const std::string& entryName,
-                                  const Styleable* styleable,
+  void AddMembersToStyleableClass(const android::StringPiece& packageNameToGenerate,
+                                  const std::string& entryName, const Styleable* styleable,
                                   ClassDefinition* outStyleableClassDef);
 
   bool SkipSymbol(SymbolState state);
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 3d3d24e..55c5cb2 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -22,6 +22,8 @@
 #include "test/Test.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
index db84f29..de8e59a 100644
--- a/tools/aapt2/java/ManifestClassGenerator.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -24,6 +24,8 @@
 #include "util/Maybe.h"
 #include "xml/XmlDom.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 static Maybe<StringPiece> ExtractJavaIdentifier(IDiagnostics* diag,
diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp
index 5518fe2..b029b20 100644
--- a/tools/aapt2/jni/aapt2_jni.cpp
+++ b/tools/aapt2/jni/aapt2_jni.cpp
@@ -26,6 +26,8 @@
 
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 extern int Compile(const std::vector<StringPiece> &args);
 extern int Link(const std::vector<StringPiece> &args);
@@ -65,9 +67,8 @@
  * The returned pieces can only be used while the original ones have not been
  * destroyed.
  */
-static std::vector<aapt::StringPiece> extract_pieces(
-    const std::vector<ScopedUtfChars> &strings) {
-  std::vector<aapt::StringPiece> pieces;
+static std::vector<StringPiece> extract_pieces(const std::vector<ScopedUtfChars> &strings) {
+  std::vector<StringPiece> pieces;
 
   std::for_each(
       strings.begin(), strings.end(),
@@ -80,8 +81,7 @@
     JNIEnv *env, jclass aapt_obj, jobject arguments_obj) {
   std::vector<ScopedUtfChars> compile_args_jni =
       list_to_utfchars(env, arguments_obj);
-  std::vector<aapt::StringPiece> compile_args =
-      extract_pieces(compile_args_jni);
+  std::vector<StringPiece> compile_args = extract_pieces(compile_args_jni);
   aapt::Compile(compile_args);
 }
 
@@ -89,7 +89,7 @@
     JNIEnv *env, jclass aapt_obj, jobject arguments_obj) {
   std::vector<ScopedUtfChars> link_args_jni =
       list_to_utfchars(env, arguments_obj);
-  std::vector<aapt::StringPiece> link_args = extract_pieces(link_args_jni);
+  std::vector<StringPiece> link_args = extract_pieces(link_args_jni);
   aapt::Link(link_args);
 }
 
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index b525758..c3ce076 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -23,6 +23,7 @@
 
 #include "android-base/errors.h"
 #include "android-base/file.h"
+#include "androidfw/StringPiece.h"
 #include "google/protobuf/io/coded_stream.h"
 
 #include "AppInfo.h"
@@ -51,9 +52,9 @@
 #include "split/TableSplitter.h"
 #include "unflatten/BinaryResourceParser.h"
 #include "util/Files.h"
-#include "util/StringPiece.h"
 #include "xml/XmlDom.h"
 
+using android::StringPiece;
 using ::google::protobuf::io::CopyingOutputStreamAdaptor;
 
 namespace aapt {
@@ -121,7 +122,7 @@
   }
 
   void SetCompilationPackage(const StringPiece& package_name) {
-    compilation_package_ = package_name.ToString();
+    compilation_package_ = package_name.to_string();
   }
 
   uint8_t GetPackageId() override { return package_id_; }
@@ -2011,14 +2012,14 @@
   for (std::string& extra_package : extra_java_packages) {
     // A given package can actually be a colon separated list of packages.
     for (StringPiece package : util::Split(extra_package, ':')) {
-      options.extra_java_packages.insert(package.ToString());
+      options.extra_java_packages.insert(package.to_string());
     }
   }
 
   if (product_list) {
     for (StringPiece product : util::Tokenize(product_list.value(), ',')) {
       if (product != "" && product != "default") {
-        options.products.insert(product.ToString());
+        options.products.insert(product.to_string());
       }
     }
   }
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 4185937..e5eaf2f 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -25,6 +25,8 @@
 #include "xml/XmlActionExecutor.h"
 #include "xml/XmlDom.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 /**
@@ -293,7 +295,7 @@
   CHECK(attr != nullptr);
 
   std::string original_package = std::move(attr->value);
-  attr->value = package_override.ToString();
+  attr->value = package_override.to_string();
 
   FullyQualifiedClassNameVisitor visitor(original_package);
   manifest_el->Accept(&visitor);
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index fc6970c..12a304a 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -18,6 +18,8 @@
 
 #include "test/Test.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 struct ManifestFixerTest : public ::testing::Test {
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index be787b2..ea68b61 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -30,6 +30,8 @@
 #include "util/Util.h"
 #include "xml/XmlUtil.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 namespace {
@@ -192,8 +194,7 @@
       const StringPiece& alias,
       const StringPiece& local_package) const override {
     if (alias.empty()) {
-      return xml::ExtractedPackage{local_package.ToString(),
-                                   true /* private */};
+      return xml::ExtractedPackage{local_package.to_string(), true /* private */};
     }
     return {};
   }
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index d808da3..7e7b9fb 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -24,6 +24,8 @@
 #include "ValueVisitor.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table,
@@ -351,9 +353,8 @@
     const std::string& package, const FileReference& file_ref) {
   StringPiece prefix, entry, suffix;
   if (util::ExtractResFilePathParts(*file_ref.path, &prefix, &entry, &suffix)) {
-    std::string mangled_entry =
-        NameMangler::MangleEntry(package, entry.ToString());
-    std::string newPath = prefix.ToString() + mangled_entry + suffix.ToString();
+    std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string());
+    std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string();
     std::unique_ptr<FileReference> new_file_ref =
         util::make_unique<FileReference>(
             master_table_->string_pool.MakeRef(newPath));
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index 4ab83c3..c96b1b0 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -96,8 +96,8 @@
    * An io::IFileCollection is needed in order to find the referenced Files and
    * process them.
    */
-  bool MergeAndMangle(const Source& src, const StringPiece& package,
-                      ResourceTable* table, io::IFileCollection* collection);
+  bool MergeAndMangle(const Source& src, const android::StringPiece& package, ResourceTable* table,
+                      io::IFileCollection* collection);
 
   /**
    * Merges a compiled file that belongs to this same or empty package. This is
diff --git a/tools/aapt2/link/VersionCollapser_test.cpp b/tools/aapt2/link/VersionCollapser_test.cpp
index 1b5592f..44babb2 100644
--- a/tools/aapt2/link/VersionCollapser_test.cpp
+++ b/tools/aapt2/link/VersionCollapser_test.cpp
@@ -18,6 +18,8 @@
 
 #include "test/Test.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 static std::unique_ptr<ResourceTable> BuildTableWithConfigs(
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 767384d..1a3da73 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -25,6 +25,8 @@
 #include "ValueVisitor.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 void SymbolTable::AppendSource(std::unique_ptr<ISymbolSource> source) {
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 25f7565..cf597bb 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -154,7 +154,7 @@
  public:
   AssetManagerSymbolSource() = default;
 
-  bool AddAssetPath(const StringPiece& path);
+  bool AddAssetPath(const android::StringPiece& path);
 
   std::unique_ptr<SymbolTable::Symbol> FindByName(
       const ResourceName& name) override;
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index 0d0e46d..7230b55 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -22,7 +22,7 @@
 #include "proto/ProtoSerialize.h"
 #include "util/BigBuffer.h"
 
-#include <android-base/logging.h>
+#include "android-base/logging.h"
 
 using google::protobuf::io::CodedOutputStream;
 using google::protobuf::io::CodedInputStream;
@@ -239,7 +239,7 @@
       if (type->id) {
         pb_type->set_id(type->id.value());
       }
-      pb_type->set_name(ToString(type->type).ToString());
+      pb_type->set_name(ToString(type->type).to_string());
 
       for (auto& entry : type->entries) {
         pb::Entry* pb_entry = pb_type->add_entries();
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 7aad86f..38cfd2e 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -21,6 +21,7 @@
 #include <set>
 #include <unordered_map>
 #include <vector>
+
 #include "android-base/logging.h"
 
 #include "ConfigDescription.h"
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 9377306..6888cf3 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -37,95 +37,86 @@
 
   StringPool* string_pool() { return &table_->string_pool; }
 
-  ResourceTableBuilder& SetPackageId(const StringPiece& package_name,
-                                     uint8_t id) {
+  ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id) {
     ResourceTablePackage* package = table_->CreatePackage(package_name, id);
     CHECK(package != nullptr);
     return *this;
   }
 
-  ResourceTableBuilder& AddSimple(const StringPiece& name,
-                                  const ResourceId& id = {}) {
+  ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {}) {
     return AddValue(name, id, util::make_unique<Id>());
   }
 
-  ResourceTableBuilder& AddSimple(const StringPiece& name,
-                                  const ConfigDescription& config,
+  ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ConfigDescription& config,
                                   const ResourceId& id = {}) {
     return AddValue(name, config, id, util::make_unique<Id>());
   }
 
-  ResourceTableBuilder& AddReference(const StringPiece& name,
-                                     const StringPiece& ref) {
+  ResourceTableBuilder& AddReference(const android::StringPiece& name,
+                                     const android::StringPiece& ref) {
     return AddReference(name, {}, ref);
   }
 
-  ResourceTableBuilder& AddReference(const StringPiece& name,
-                                     const ResourceId& id,
-                                     const StringPiece& ref) {
+  ResourceTableBuilder& AddReference(const android::StringPiece& name, const ResourceId& id,
+                                     const android::StringPiece& ref) {
     return AddValue(name, id,
                     util::make_unique<Reference>(ParseNameOrDie(ref)));
   }
 
-  ResourceTableBuilder& AddString(const StringPiece& name,
-                                  const StringPiece& str) {
+  ResourceTableBuilder& AddString(const android::StringPiece& name,
+                                  const android::StringPiece& str) {
     return AddString(name, {}, str);
   }
 
-  ResourceTableBuilder& AddString(const StringPiece& name, const ResourceId& id,
-                                  const StringPiece& str) {
+  ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id,
+                                  const android::StringPiece& str) {
     return AddValue(
         name, id, util::make_unique<String>(table_->string_pool.MakeRef(str)));
   }
 
-  ResourceTableBuilder& AddString(const StringPiece& name, const ResourceId& id,
+  ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id,
                                   const ConfigDescription& config,
-                                  const StringPiece& str) {
+                                  const android::StringPiece& str) {
     return AddValue(name, config, id, util::make_unique<String>(
                                           table_->string_pool.MakeRef(str)));
   }
 
-  ResourceTableBuilder& AddFileReference(const StringPiece& name,
-                                         const StringPiece& path) {
+  ResourceTableBuilder& AddFileReference(const android::StringPiece& name,
+                                         const android::StringPiece& path) {
     return AddFileReference(name, {}, path);
   }
 
-  ResourceTableBuilder& AddFileReference(const StringPiece& name,
-                                         const ResourceId& id,
-                                         const StringPiece& path) {
+  ResourceTableBuilder& AddFileReference(const android::StringPiece& name, const ResourceId& id,
+                                         const android::StringPiece& path) {
     return AddValue(name, id, util::make_unique<FileReference>(
                                   table_->string_pool.MakeRef(path)));
   }
 
-  ResourceTableBuilder& AddFileReference(const StringPiece& name,
-                                         const StringPiece& path,
+  ResourceTableBuilder& AddFileReference(const android::StringPiece& name,
+                                         const android::StringPiece& path,
                                          const ConfigDescription& config) {
     return AddValue(name, config, {}, util::make_unique<FileReference>(
                                           table_->string_pool.MakeRef(path)));
   }
 
-  ResourceTableBuilder& AddValue(const StringPiece& name,
-                                 std::unique_ptr<Value> value) {
+  ResourceTableBuilder& AddValue(const android::StringPiece& name, std::unique_ptr<Value> value) {
     return AddValue(name, {}, std::move(value));
   }
 
-  ResourceTableBuilder& AddValue(const StringPiece& name, const ResourceId& id,
+  ResourceTableBuilder& AddValue(const android::StringPiece& name, const ResourceId& id,
                                  std::unique_ptr<Value> value) {
     return AddValue(name, {}, id, std::move(value));
   }
 
-  ResourceTableBuilder& AddValue(const StringPiece& name,
-                                 const ConfigDescription& config,
-                                 const ResourceId& id,
-                                 std::unique_ptr<Value> value) {
+  ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config,
+                                 const ResourceId& id, std::unique_ptr<Value> value) {
     ResourceName res_name = ParseNameOrDie(name);
     CHECK(table_->AddResourceAllowMangled(res_name, id, config, {},
                                           std::move(value), &diagnostics_));
     return *this;
   }
 
-  ResourceTableBuilder& SetSymbolState(const StringPiece& name,
-                                       const ResourceId& id,
+  ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id,
                                        SymbolState state) {
     ResourceName res_name = ParseNameOrDie(name);
     Symbol symbol;
@@ -144,8 +135,8 @@
   std::unique_ptr<ResourceTable> table_ = util::make_unique<ResourceTable>();
 };
 
-inline std::unique_ptr<Reference> BuildReference(
-    const StringPiece& ref, const Maybe<ResourceId>& id = {}) {
+inline std::unique_ptr<Reference> BuildReference(const android::StringPiece& ref,
+                                                 const Maybe<ResourceId>& id = {}) {
   std::unique_ptr<Reference> reference =
       util::make_unique<Reference>(ParseNameOrDie(ref));
   reference->id = id;
@@ -174,7 +165,7 @@
     return *this;
   }
 
-  ValueBuilder& SetComment(const StringPiece& str) {
+  ValueBuilder& SetComment(const android::StringPiece& str) {
     value_->SetComment(str);
     return *this;
   }
@@ -199,7 +190,7 @@
     return *this;
   }
 
-  AttributeBuilder& AddItem(const StringPiece& name, uint32_t value) {
+  AttributeBuilder& AddItem(const android::StringPiece& name, uint32_t value) {
     attr_->symbols.push_back(Attribute::Symbol{
         Reference(ResourceName({}, ResourceType::kId, name)), value});
     return *this;
@@ -217,18 +208,18 @@
  public:
   StyleBuilder() = default;
 
-  StyleBuilder& SetParent(const StringPiece& str) {
+  StyleBuilder& SetParent(const android::StringPiece& str) {
     style_->parent = Reference(ParseNameOrDie(str));
     return *this;
   }
 
-  StyleBuilder& AddItem(const StringPiece& str, std::unique_ptr<Item> value) {
+  StyleBuilder& AddItem(const android::StringPiece& str, std::unique_ptr<Item> value) {
     style_->entries.push_back(
         Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)});
     return *this;
   }
 
-  StyleBuilder& AddItem(const StringPiece& str, const ResourceId& id,
+  StyleBuilder& AddItem(const android::StringPiece& str, const ResourceId& id,
                         std::unique_ptr<Item> value) {
     AddItem(str, std::move(value));
     style_->entries.back().key.id = id;
@@ -247,8 +238,7 @@
  public:
   StyleableBuilder() = default;
 
-  StyleableBuilder& AddItem(const StringPiece& str,
-                            const Maybe<ResourceId>& id = {}) {
+  StyleableBuilder& AddItem(const android::StringPiece& str, const Maybe<ResourceId>& id = {}) {
     styleable_->entries.push_back(Reference(ParseNameOrDie(str)));
     styleable_->entries.back().id = id;
     return *this;
@@ -262,7 +252,7 @@
   std::unique_ptr<Styleable> styleable_ = util::make_unique<Styleable>();
 };
 
-inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const StringPiece& str) {
+inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const android::StringPiece& str) {
   std::stringstream in;
   in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str;
   StdErrDiagnostics diag;
@@ -273,7 +263,7 @@
 }
 
 inline std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(
-    IAaptContext* context, const StringPiece& str) {
+    IAaptContext* context, const android::StringPiece& str) {
   std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str);
   doc->file.name.package = context->GetCompilationPackage();
   return doc;
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index 3689201..248921f 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -21,6 +21,7 @@
 
 #include "android-base/logging.h"
 #include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
 #include "gtest/gtest.h"
 
 #include "ConfigDescription.h"
@@ -30,7 +31,6 @@
 #include "ValueVisitor.h"
 #include "io/File.h"
 #include "process/IResourceTableConsumer.h"
-#include "util/StringPiece.h"
 
 //
 // GTEST 1.7 doesn't explicitly cast to bool, which causes explicit operators to
@@ -68,23 +68,22 @@
   return &diag;
 }
 
-inline ResourceName ParseNameOrDie(const StringPiece& str) {
+inline ResourceName ParseNameOrDie(const android::StringPiece& str) {
   ResourceNameRef ref;
   CHECK(ResourceUtils::ParseResourceName(str, &ref)) << "invalid resource name";
   return ref.ToResourceName();
 }
 
-inline ConfigDescription ParseConfigOrDie(const StringPiece& str) {
+inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) {
   ConfigDescription config;
   CHECK(ConfigDescription::Parse(str, &config)) << "invalid configuration";
   return config;
 }
 
 template <typename T>
-T* GetValueForConfigAndProduct(ResourceTable* table,
-                               const StringPiece& res_name,
+T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name,
                                const ConfigDescription& config,
-                               const StringPiece& product) {
+                               const android::StringPiece& product) {
   Maybe<ResourceTable::SearchResult> result =
       table->FindResource(ParseNameOrDie(res_name));
   if (result) {
@@ -98,19 +97,19 @@
 }
 
 template <typename T>
-T* GetValueForConfig(ResourceTable* table, const StringPiece& res_name,
+T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name,
                      const ConfigDescription& config) {
   return GetValueForConfigAndProduct<T>(table, res_name, config, {});
 }
 
 template <typename T>
-T* GetValue(ResourceTable* table, const StringPiece& res_name) {
+T* GetValue(ResourceTable* table, const android::StringPiece& res_name) {
   return GetValueForConfig<T>(table, res_name, {});
 }
 
 class TestFile : public io::IFile {
  public:
-  explicit TestFile(const StringPiece& path) : source_(path) {}
+  explicit TestFile(const android::StringPiece& path) : source_(path) {}
 
   std::unique_ptr<io::IData> OpenAsData() override { return {}; }
 
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index 7986329..63e5f16 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -70,8 +70,8 @@
 
 class ContextBuilder {
  public:
-  ContextBuilder& SetCompilationPackage(const StringPiece& package) {
-    context_->compilation_package_ = package.ToString();
+  ContextBuilder& SetCompilationPackage(const android::StringPiece& package) {
+    context_->compilation_package_ = package.to_string();
     return *this;
   }
 
@@ -103,9 +103,8 @@
 
 class StaticSymbolSourceBuilder {
  public:
-  StaticSymbolSourceBuilder& AddPublicSymbol(
-      const StringPiece& name, ResourceId id,
-      std::unique_ptr<Attribute> attr = {}) {
+  StaticSymbolSourceBuilder& AddPublicSymbol(const android::StringPiece& name, ResourceId id,
+                                             std::unique_ptr<Attribute> attr = {}) {
     std::unique_ptr<SymbolTable::Symbol> symbol =
         util::make_unique<SymbolTable::Symbol>(id, std::move(attr), true);
     symbol_source_->name_map_[ParseNameOrDie(name)] = symbol.get();
@@ -114,7 +113,7 @@
     return *this;
   }
 
-  StaticSymbolSourceBuilder& AddSymbol(const StringPiece& name, ResourceId id,
+  StaticSymbolSourceBuilder& AddSymbol(const android::StringPiece& name, ResourceId id,
                                        std::unique_ptr<Attribute> attr = {}) {
     std::unique_ptr<SymbolTable::Symbol> symbol =
         util::make_unique<SymbolTable::Symbol>(id, std::move(attr), false);
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index f034607..aa840e2 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -35,6 +35,8 @@
 #include <direct.h>
 #endif
 
+using android::StringPiece;
+
 namespace aapt {
 namespace file {
 
@@ -72,10 +74,9 @@
 
 inline static int MkdirImpl(const StringPiece& path) {
 #ifdef _WIN32
-  return _mkdir(path.ToString().c_str());
+  return _mkdir(path.to_string().c_str());
 #else
-  return mkdir(path.ToString().c_str(),
-               S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP);
+  return mkdir(path.to_string().c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP);
 #endif
 }
 
@@ -184,7 +185,7 @@
                         std::vector<std::string>* out_arglist,
                         std::string* out_error) {
   std::string contents;
-  if (!android::base::ReadFileToString(path.ToString(), &contents)) {
+  if (!android::base::ReadFileToString(path.to_string(), &contents)) {
     if (out_error) *out_error = "failed to read argument-list file";
     return false;
   }
@@ -192,7 +193,7 @@
   for (StringPiece line : util::Tokenize(contents, ' ')) {
     line = util::TrimWhitespace(line);
     if (!line.empty()) {
-      out_arglist->push_back(line.ToString());
+      out_arglist->push_back(line.to_string());
     }
   }
   return true;
diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h
index a157dbd..95c492f 100644
--- a/tools/aapt2/util/Files.h
+++ b/tools/aapt2/util/Files.h
@@ -22,12 +22,12 @@
 #include <vector>
 
 #include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
 #include "utils/FileMap.h"
 
 #include "Diagnostics.h"
 #include "Maybe.h"
 #include "Source.h"
-#include "util/StringPiece.h"
 
 namespace aapt {
 namespace file {
@@ -50,51 +50,49 @@
   kSocket,
 };
 
-FileType GetFileType(const StringPiece& path);
+FileType GetFileType(const android::StringPiece& path);
 
 /*
  * Appends a path to `base`, separated by the directory separator.
  */
-void AppendPath(std::string* base, StringPiece part);
+void AppendPath(std::string* base, android::StringPiece part);
 
 /*
  * Makes all the directories in `path`. The last element in the path
  * is interpreted as a directory.
  */
-bool mkdirs(const StringPiece& path);
+bool mkdirs(const android::StringPiece& path);
 
 /**
  * Returns all but the last part of the path.
  */
-StringPiece GetStem(const StringPiece& path);
+android::StringPiece GetStem(const android::StringPiece& path);
 
 /**
  * Returns the last part of the path with extension.
  */
-StringPiece GetFilename(const StringPiece& path);
+android::StringPiece GetFilename(const android::StringPiece& path);
 
 /**
  * Returns the extension of the path. This is the entire string after
  * the first '.' of the last part of the path.
  */
-StringPiece GetExtension(const StringPiece& path);
+android::StringPiece GetExtension(const android::StringPiece& path);
 
 /**
  * Converts a package name (com.android.app) to a path: com/android/app
  */
-std::string PackageToPath(const StringPiece& package);
+std::string PackageToPath(const android::StringPiece& package);
 
 /**
  * Creates a FileMap for the file at path.
  */
-Maybe<android::FileMap> MmapPath(const StringPiece& path,
-                                 std::string* out_error);
+Maybe<android::FileMap> MmapPath(const android::StringPiece& path, std::string* out_error);
 
 /**
  * Reads the file at path and appends each line to the outArgList vector.
  */
-bool AppendArgsFromFile(const StringPiece& path,
-                        std::vector<std::string>* out_arglist,
+bool AppendArgsFromFile(const android::StringPiece& path, std::vector<std::string>* out_arglist,
                         std::string* out_error);
 
 /*
@@ -120,7 +118,7 @@
    * - Otherwise the full string is matched.
    * - match is not case-sensitive.
    */
-  bool SetPattern(const StringPiece& pattern);
+  bool SetPattern(const android::StringPiece& pattern);
 
   /**
    * Applies the filter, returning true for pass, false for fail.
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index d5c0c8a..cf22322 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -15,9 +15,6 @@
  */
 
 #include "util/Util.h"
-#include "util/BigBuffer.h"
-#include "util/Maybe.h"
-#include "util/StringPiece.h"
 
 #include <utils/Unicode.h>
 #include <algorithm>
@@ -25,6 +22,14 @@
 #include <string>
 #include <vector>
 
+#include "androidfw/StringPiece.h"
+
+#include "util/BigBuffer.h"
+#include "util/Maybe.h"
+
+using android::StringPiece;
+using android::StringPiece16;
+
 namespace aapt {
 namespace util {
 
@@ -36,7 +41,7 @@
   StringPiece::const_iterator current;
   do {
     current = std::find(start, end, sep);
-    parts.emplace_back(str.substr(start, current).ToString());
+    parts.emplace_back(str.substr(start, current).to_string());
     if (f) {
       std::string& part = parts.back();
       std::transform(part.begin(), part.end(), part.begin(), f);
@@ -162,7 +167,7 @@
   }
 
   if (util::IsJavaClassName(classname)) {
-    return classname.ToString();
+    return classname.to_string();
   }
 
   if (package.empty()) {
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 05e9cc5..f8fa80e 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -24,11 +24,11 @@
 #include <vector>
 
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
 #include "utils/ByteOrder.h"
 
 #include "util/BigBuffer.h"
 #include "util/Maybe.h"
-#include "util/StringPiece.h"
 
 #ifdef _WIN32
 // TODO(adamlesinski): remove once http://b/32447322 is resolved.
@@ -44,26 +44,24 @@
 namespace aapt {
 namespace util {
 
-std::vector<std::string> Split(const StringPiece& str, char sep);
-std::vector<std::string> SplitAndLowercase(const StringPiece& str, char sep);
+std::vector<std::string> Split(const android::StringPiece& str, char sep);
+std::vector<std::string> SplitAndLowercase(const android::StringPiece& str, char sep);
 
 /**
  * Returns true if the string starts with prefix.
  */
-bool StartsWith(const StringPiece& str, const StringPiece& prefix);
+bool StartsWith(const android::StringPiece& str, const android::StringPiece& prefix);
 
 /**
  * Returns true if the string ends with suffix.
  */
-bool EndsWith(const StringPiece& str, const StringPiece& suffix);
+bool EndsWith(const android::StringPiece& str, const android::StringPiece& suffix);
 
 /**
  * Creates a new StringPiece16 that points to a substring
  * of the original string without leading or trailing whitespace.
  */
-StringPiece TrimWhitespace(const StringPiece& str);
-
-StringPiece TrimWhitespace(const StringPiece& str);
+android::StringPiece TrimWhitespace(const android::StringPiece& str);
 
 /**
  * UTF-16 isspace(). It basically checks for lower range characters that are
@@ -75,18 +73,18 @@
  * Returns an iterator to the first character that is not alpha-numeric and that
  * is not in the allowedChars set.
  */
-StringPiece::const_iterator FindNonAlphaNumericAndNotInSet(
-    const StringPiece& str, const StringPiece& allowed_chars);
+android::StringPiece::const_iterator FindNonAlphaNumericAndNotInSet(
+    const android::StringPiece& str, const android::StringPiece& allowed_chars);
 
 /**
  * Tests that the string is a valid Java class name.
  */
-bool IsJavaClassName(const StringPiece& str);
+bool IsJavaClassName(const android::StringPiece& str);
 
 /**
  * Tests that the string is a valid Java package name.
  */
-bool IsJavaPackageName(const StringPiece& str);
+bool IsJavaPackageName(const android::StringPiece& str);
 
 /**
  * Converts the class name to a fully qualified class name from the given
@@ -97,8 +95,8 @@
  * .a.b         --> package.a.b
  * asdf.adsf    --> asdf.adsf
  */
-Maybe<std::string> GetFullyQualifiedClassName(const StringPiece& package,
-                                              const StringPiece& class_name);
+Maybe<std::string> GetFullyQualifiedClassName(const android::StringPiece& package,
+                                              const android::StringPiece& class_name);
 
 /**
  * Makes a std::unique_ptr<> with the template parameter inferred by the
@@ -138,7 +136,7 @@
  * stored as UTF-8,
  * the conversion to UTF-16 happens within ResStringPool.
  */
-StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx);
+android::StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx);
 
 /**
  * Helper method to extract a UTF-8 string from a StringPool. If the string is
@@ -159,11 +157,11 @@
  * which will
  * break the string interpolation.
  */
-bool VerifyJavaStringFormat(const StringPiece& str);
+bool VerifyJavaStringFormat(const android::StringPiece& str);
 
 class StringBuilder {
  public:
-  StringBuilder& Append(const StringPiece& str);
+  StringBuilder& Append(const android::StringPiece& str);
   const std::string& ToString() const;
   const std::string& Error() const;
 
@@ -194,8 +192,8 @@
 /**
  * Converts a UTF8 string to a UTF16 string.
  */
-std::u16string Utf8ToUtf16(const StringPiece& utf8);
-std::string Utf16ToUtf8(const StringPiece16& utf16);
+std::u16string Utf8ToUtf16(const android::StringPiece& utf8);
+std::string Utf16ToUtf8(const android::StringPiece16& utf16);
 
 /**
  * Writes the entire BigBuffer to the output stream.
@@ -220,22 +218,22 @@
 
     iterator& operator++();
 
-    StringPiece operator*() { return token_; }
+    android::StringPiece operator*() { return token_; }
     bool operator==(const iterator& rhs) const;
     bool operator!=(const iterator& rhs) const;
 
    private:
     friend class Tokenizer;
 
-    iterator(StringPiece s, char sep, StringPiece tok, bool end);
+    iterator(android::StringPiece s, char sep, android::StringPiece tok, bool end);
 
-    StringPiece str_;
+    android::StringPiece str_;
     char separator_;
-    StringPiece token_;
+    android::StringPiece token_;
     bool end_;
   };
 
-  Tokenizer(StringPiece str, char sep);
+  Tokenizer(android::StringPiece str, char sep);
 
   iterator begin() { return begin_; }
 
@@ -246,9 +244,7 @@
   const iterator end_;
 };
 
-inline Tokenizer Tokenize(const StringPiece& str, char sep) {
-  return Tokenizer(str, sep);
-}
+inline Tokenizer Tokenize(const android::StringPiece& str, char sep) { return Tokenizer(str, sep); }
 
 inline uint16_t HostToDevice16(uint16_t value) { return htods(value); }
 
@@ -267,8 +263,8 @@
  *
  * Returns true if successful.
  */
-bool ExtractResFilePathParts(const StringPiece& path, StringPiece* out_prefix,
-                             StringPiece* out_entry, StringPiece* out_suffix);
+bool ExtractResFilePathParts(const android::StringPiece& path, android::StringPiece* out_prefix,
+                             android::StringPiece* out_entry, android::StringPiece* out_suffix);
 
 }  // namespace util
 
diff --git a/tools/aapt2/util/Util_test.cpp b/tools/aapt2/util/Util_test.cpp
index cac3de4..e49aee5 100644
--- a/tools/aapt2/util/Util_test.cpp
+++ b/tools/aapt2/util/Util_test.cpp
@@ -20,6 +20,8 @@
 
 #include "test/Test.h"
 
+using android::StringPiece;
+
 namespace aapt {
 
 TEST(UtilTest, TrimOnlyWhitespace) {
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 960d361..fab2f19 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -29,6 +29,9 @@
 #include "XmlPullParser.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+using android::StringPiece16;
+
 namespace aapt {
 namespace xml {
 
@@ -52,10 +55,10 @@
 
   if (*p == 0) {
     out_ns->clear();
-    *out_name = StringPiece(name).ToString();
+    out_name->assign(name);
   } else {
-    *out_ns = StringPiece(name, (p - name)).ToString();
-    *out_name = StringPiece(p + 1).ToString();
+    out_ns->assign(name, (p - name));
+    out_name->assign(p + 1);
   }
 }
 
@@ -83,11 +86,11 @@
 
   std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
   if (prefix) {
-    ns->namespace_prefix = StringPiece(prefix).ToString();
+    ns->namespace_prefix = prefix;
   }
 
   if (uri) {
-    ns->namespace_uri = StringPiece(uri).ToString();
+    ns->namespace_uri = uri;
   }
 
   AddToStack(stack, parser, std::move(ns));
@@ -117,7 +120,7 @@
   while (*attrs) {
     Attribute attribute;
     SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
-    attribute.value = StringPiece(*attrs++).ToString();
+    attribute.value = *attrs++;
 
     // Insert in sorted order.
     auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(),
@@ -153,14 +156,14 @@
     if (!currentParent->children.empty()) {
       Node* last_child = currentParent->children.back().get();
       if (Text* text = NodeCast<Text>(last_child)) {
-        text->text += StringPiece(s, len).ToString();
+        text->text.append(s, len);
         return;
       }
     }
   }
 
   std::unique_ptr<Text> text = util::make_unique<Text>();
-  text->text = StringPiece(s, len).ToString();
+  text->text.assign(s, len);
   AddToStack(stack, parser, std::move(text));
 }
 
@@ -495,15 +498,14 @@
 Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
     const StringPiece& alias, const StringPiece& local_package) const {
   if (alias.empty()) {
-    return ExtractedPackage{local_package.ToString(), false /* private */};
+    return ExtractedPackage{local_package.to_string(), false /* private */};
   }
 
   const auto rend = package_decls_.rend();
   for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
     if (alias == iter->prefix) {
       if (iter->package.package.empty()) {
-        return ExtractedPackage{local_package.ToString(),
-                                iter->package.private_namespace};
+        return ExtractedPackage{local_package.to_string(), iter->package.private_namespace};
       }
       return iter->package;
     }
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index 720fe35..90cdfb6 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -22,10 +22,11 @@
 #include <string>
 #include <vector>
 
+#include "androidfw/StringPiece.h"
+
 #include "Diagnostics.h"
 #include "Resource.h"
 #include "ResourceValues.h"
-#include "util/StringPiece.h"
 #include "util/Util.h"
 #include "xml/XmlUtil.h"
 
@@ -100,13 +101,13 @@
   std::string name;
   std::vector<Attribute> attributes;
 
-  Attribute* FindAttribute(const StringPiece& ns, const StringPiece& name);
-  xml::Element* FindChild(const StringPiece& ns, const StringPiece& name);
-  xml::Element* FindChildWithAttribute(const StringPiece& ns,
-                                       const StringPiece& name,
-                                       const StringPiece& attr_ns,
-                                       const StringPiece& attr_name,
-                                       const StringPiece& attr_value);
+  Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name);
+  xml::Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
+  xml::Element* FindChildWithAttribute(const android::StringPiece& ns,
+                                       const android::StringPiece& name,
+                                       const android::StringPiece& attr_ns,
+                                       const android::StringPiece& attr_name,
+                                       const android::StringPiece& attr_value);
   std::vector<xml::Element*> GetChildElements();
   std::unique_ptr<Node> Clone() override;
 };
@@ -190,8 +191,7 @@
 
   void Visit(Namespace* ns) override;
   Maybe<ExtractedPackage> TransformPackageAlias(
-      const StringPiece& alias,
-      const StringPiece& local_package) const override;
+      const android::StringPiece& alias, const android::StringPiece& local_package) const override;
 
  private:
   struct PackageDecl {
diff --git a/tools/aapt2/xml/XmlPullParser.cpp b/tools/aapt2/xml/XmlPullParser.cpp
index e59fa86..c2a9c82 100644
--- a/tools/aapt2/xml/XmlPullParser.cpp
+++ b/tools/aapt2/xml/XmlPullParser.cpp
@@ -22,6 +22,8 @@
 #include "xml/XmlPullParser.h"
 #include "xml/XmlUtil.h"
 
+using android::StringPiece;
+
 namespace aapt {
 namespace xml {
 
@@ -136,15 +138,14 @@
 Maybe<ExtractedPackage> XmlPullParser::TransformPackageAlias(
     const StringPiece& alias, const StringPiece& local_package) const {
   if (alias.empty()) {
-    return ExtractedPackage{local_package.ToString(), false /* private */};
+    return ExtractedPackage{local_package.to_string(), false /* private */};
   }
 
   const auto end_iter = package_aliases_.rend();
   for (auto iter = package_aliases_.rbegin(); iter != end_iter; ++iter) {
     if (alias == iter->prefix) {
       if (iter->package.package.empty()) {
-        return ExtractedPackage{local_package.ToString(),
-                                iter->package.private_namespace};
+        return ExtractedPackage{local_package.to_string(), iter->package.private_namespace};
       }
       return iter->package;
     }
@@ -188,19 +189,18 @@
 /**
  * Extracts the namespace and name of an expanded element or attribute name.
  */
-static void SplitName(const char* name, std::string& out_ns,
-                      std::string& out_name) {
+static void SplitName(const char* name, std::string* out_ns, std::string* out_name) {
   const char* p = name;
   while (*p != 0 && *p != kXmlNamespaceSep) {
     p++;
   }
 
   if (*p == 0) {
-    out_ns = std::string();
-    out_name = name;
+    out_ns->clear();
+    out_name->assign(name);
   } else {
-    out_ns = StringPiece(name, (p - name)).ToString();
-    out_name = p + 1;
+    out_ns->assign(name, (p - name));
+    out_name->assign(p + 1);
   }
 }
 
@@ -224,11 +224,11 @@
   EventData data = {Event::kStartElement,
                     XML_GetCurrentLineNumber(parser->parser_),
                     parser->depth_++};
-  SplitName(name, data.data1, data.data2);
+  SplitName(name, &data.data1, &data.data2);
 
   while (*attrs) {
     Attribute attribute;
-    SplitName(*attrs++, attribute.namespace_uri, attribute.name);
+    SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
     attribute.value = *attrs++;
 
     // Insert in sorted order.
@@ -245,9 +245,8 @@
                                                  int len) {
   XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
 
-  parser->event_queue_.push(
-      EventData{Event::kText, XML_GetCurrentLineNumber(parser->parser_),
-                parser->depth_, StringPiece(s, len).ToString()});
+  parser->event_queue_.push(EventData{Event::kText, XML_GetCurrentLineNumber(parser->parser_),
+                                      parser->depth_, std::string(s, len)});
 }
 
 void XMLCALL XmlPullParser::EndElementHandler(void* user_data,
@@ -257,7 +256,7 @@
   EventData data = {Event::kEndElement,
                     XML_GetCurrentLineNumber(parser->parser_),
                     --(parser->depth_)};
-  SplitName(name, data.data1, data.data2);
+  SplitName(name, &data.data1, &data.data2);
 
   // Move the data into the queue (no copy).
   parser->event_queue_.push(std::move(data));
diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h
index ff58d60..cdeeefd 100644
--- a/tools/aapt2/xml/XmlPullParser.h
+++ b/tools/aapt2/xml/XmlPullParser.h
@@ -28,11 +28,11 @@
 #include <vector>
 
 #include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
 
 #include "Resource.h"
 #include "process/IResourceTableConsumer.h"
 #include "util/Maybe.h"
-#include "util/StringPiece.h"
 #include "xml/XmlUtil.h"
 
 namespace aapt {
@@ -119,8 +119,7 @@
    * 'package' will be set to 'defaultPackage'.
    */
   Maybe<ExtractedPackage> TransformPackageAlias(
-      const StringPiece& alias,
-      const StringPiece& local_package) const override;
+      const android::StringPiece& alias, const android::StringPiece& local_package) const override;
 
   //
   // Remaining methods are for retrieving information about attributes
@@ -146,8 +145,7 @@
   const_iterator begin_attributes() const;
   const_iterator end_attributes() const;
   size_t attribute_count() const;
-  const_iterator FindAttribute(StringPiece namespace_uri,
-                               StringPiece name) const;
+  const_iterator FindAttribute(android::StringPiece namespace_uri, android::StringPiece name) const;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(XmlPullParser);
@@ -190,16 +188,16 @@
 /**
  * Finds the attribute in the current element within the global namespace.
  */
-Maybe<StringPiece> FindAttribute(const XmlPullParser* parser,
-                                 const StringPiece& name);
+Maybe<android::StringPiece> FindAttribute(const XmlPullParser* parser,
+                                          const android::StringPiece& name);
 
 /**
  * Finds the attribute in the current element within the global namespace. The
  * attribute's value
  * must not be the empty string.
  */
-Maybe<StringPiece> FindNonEmptyAttribute(const XmlPullParser* parser,
-                                         const StringPiece& name);
+Maybe<android::StringPiece> FindNonEmptyAttribute(const XmlPullParser* parser,
+                                                  const android::StringPiece& name);
 
 //
 // Implementation
@@ -299,13 +297,13 @@
 }
 
 inline XmlPullParser::const_iterator XmlPullParser::FindAttribute(
-    StringPiece namespace_uri, StringPiece name) const {
+    android::StringPiece namespace_uri, android::StringPiece name) const {
   const auto end_iter = end_attributes();
   const auto iter = std::lower_bound(
       begin_attributes(), end_iter,
-      std::pair<StringPiece, StringPiece>(namespace_uri, name),
+      std::pair<android::StringPiece, android::StringPiece>(namespace_uri, name),
       [](const Attribute& attr,
-         const std::pair<StringPiece, StringPiece>& rhs) -> bool {
+         const std::pair<android::StringPiece, android::StringPiece>& rhs) -> bool {
         int cmp = attr.namespace_uri.compare(
             0, attr.namespace_uri.size(), rhs.first.data(), rhs.first.size());
         if (cmp < 0) return true;
diff --git a/tools/aapt2/xml/XmlPullParser_test.cpp b/tools/aapt2/xml/XmlPullParser_test.cpp
index 4f18cd2..1cce485 100644
--- a/tools/aapt2/xml/XmlPullParser_test.cpp
+++ b/tools/aapt2/xml/XmlPullParser_test.cpp
@@ -18,8 +18,11 @@
 
 #include <sstream>
 
+#include "androidfw/StringPiece.h"
+
 #include "test/Test.h"
-#include "util/StringPiece.h"
+
+using android::StringPiece;
 
 namespace aapt {
 
diff --git a/tools/aapt2/xml/XmlUtil.cpp b/tools/aapt2/xml/XmlUtil.cpp
index d00f7f2..fb8cee8 100644
--- a/tools/aapt2/xml/XmlUtil.cpp
+++ b/tools/aapt2/xml/XmlUtil.cpp
@@ -21,6 +21,8 @@
 #include "util/Maybe.h"
 #include "util/Util.h"
 
+using android::StringPiece;
+
 namespace aapt {
 namespace xml {
 
@@ -42,7 +44,7 @@
     if (package.empty()) {
       return {};
     }
-    return ExtractedPackage{package.ToString(), false /* is_private */};
+    return ExtractedPackage{package.to_string(), false /* is_private */};
 
   } else if (util::StartsWith(namespace_uri, kSchemaPrivatePrefix)) {
     StringPiece schema_prefix = kSchemaPrivatePrefix;
@@ -52,7 +54,7 @@
     if (package.empty()) {
       return {};
     }
-    return ExtractedPackage{package.ToString(), true /* is_private */};
+    return ExtractedPackage{package.to_string(), true /* is_private */};
 
   } else if (namespace_uri == kSchemaAuto) {
     return ExtractedPackage{std::string(), true /* is_private */};
diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h
index 5365401..1650ac2 100644
--- a/tools/aapt2/xml/XmlUtil.h
+++ b/tools/aapt2/xml/XmlUtil.h
@@ -74,7 +74,7 @@
  *
  * http://schemas.android.com/apk/prv/res/<package>
  */
-std::string BuildPackageNamespace(const StringPiece& package,
+std::string BuildPackageNamespace(const android::StringPiece& package,
                                   bool private_reference = false);
 
 /**
@@ -90,7 +90,7 @@
    * package declaration.
    */
   virtual Maybe<ExtractedPackage> TransformPackageAlias(
-      const StringPiece& alias, const StringPiece& local_package) const = 0;
+      const android::StringPiece& alias, const android::StringPiece& local_package) const = 0;
 };
 
 /**
@@ -100,8 +100,7 @@
  * the namespace of the package declaration was private.
  */
 void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack,
-                                     const StringPiece& local_package,
-                                     Reference* in_ref);
+                                     const android::StringPiece& local_package, Reference* in_ref);
 
 }  // namespace xml
 }  // namespace aapt
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index d326935..50efc7f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -248,17 +248,14 @@
     // ---- delegate methods ----
     @LayoutlibDelegate
     /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex) {
-        if (thisFontFamily.mBuilderPtr == 0) {
-            throw new IllegalStateException("Unable to call addFont after freezing.");
-        }
-        final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mBuilderPtr);
+        final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mNativePtr);
         return delegate != null && delegate.addFont(path, ttcIndex);
     }
 
     // ---- native methods ----
 
     @LayoutlibDelegate
-    /*package*/ static long nInitBuilder(String lang, int variant) {
+    /*package*/ static long nCreateFamily(String lang, int variant) {
         // TODO: support lang. This is required for japanese locale.
         FontFamily_Delegate delegate = new FontFamily_Delegate();
         // variant can be 0, 1 or 2.
@@ -273,11 +270,6 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long nCreateFamily(long builderPtr) {
-        return builderPtr;
-    }
-
-    @LayoutlibDelegate
     /*package*/ static void nUnrefFamily(long nativePtr) {
         // Removing the java reference for the object doesn't mean that it's freed for garbage
         // collection. Typeface_Delegate may still hold a reference for it.
@@ -285,22 +277,22 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
+    /*package*/ static boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex) {
         assert false : "The only client of this method has been overriden.";
         return false;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
+    /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font,
             int ttcIndex, List<FontListParser.Axis> listOfAxis,
             int weight, boolean isItalic) {
         assert false : "The only client of this method has been overriden.";
         return false;
     }
 
-    static boolean addFont(long builderPtr, final String path, final int weight,
+    static boolean addFont(long nativeFamily, final String path, final int weight,
             final boolean isItalic) {
-        final FontFamily_Delegate delegate = getDelegate(builderPtr);
+        final FontFamily_Delegate delegate = getDelegate(nativeFamily);
         if (delegate != null) {
             if (sFontLocation == null) {
                 delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, isItalic));
@@ -312,8 +304,8 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean nAddFontFromAsset(long builderPtr, AssetManager mgr, String path) {
-        FontFamily_Delegate ffd = sManager.getDelegate(builderPtr);
+    /*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
+        FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily);
         if (ffd == null) {
             return false;
         }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index a554b6d..5cd34f6 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -212,10 +212,9 @@
             Map<String, ByteBuffer> bufferForPath) {
         FontFamily fontFamily = new FontFamily(family.lang, family.variant);
         for (FontListParser.Font font : family.fonts) {
-            FontFamily_Delegate.addFont(fontFamily.mBuilderPtr, font.fontName, font.weight,
+            FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.fontName, font.weight,
                     font.isItalic);
         }
-        fontFamily.freeze();
         return fontFamily;
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 663e56d..68680d5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -40,6 +40,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.Notification;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -1820,6 +1821,13 @@
     }
 
     @Override
+    public ComponentName startServiceInForeground(Intent service,
+            int id, Notification notification) {
+        // pass
+        return null;
+    }
+
+    @Override
     public boolean stopService(Intent arg0) {
         // pass
         return false;
@@ -1832,6 +1840,13 @@
     }
 
     @Override
+    public ComponentName startServiceInForegroundAsUser(Intent service,
+            int id, Notification notification, UserHandle user) {
+        // pass
+        return null;
+    }
+
+    @Override
     public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
         // pass
         return false;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 741eb27..7ba86fd 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -339,8 +339,7 @@
      */
     private final static String[] PROMOTED_FIELDS = new String[] {
         "android.graphics.drawable.VectorDrawable#mVectorState",
-        "android.view.Choreographer#mLastFrameTimeNanos",
-        "android.graphics.FontFamily#mBuilderPtr"
+        "android.view.Choreographer#mLastFrameTimeNanos"
     };
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 3a45671..8cf7a24 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -709,6 +709,16 @@
 
     /**
      * @hide
+     * Indicate that a WifiConfiguration is temporary and should not be saved
+     * nor considered by AutoJoin.
+     */
+    @SystemApi
+    public boolean isEphemeral() {
+      return ephemeral;
+    }
+
+    /**
+     * @hide
      * A hint about whether or not the network represented by this WifiConfiguration
      * is metered. This is hinted at via the meteredHint bit on DHCP results set in
      * {@link com.android.server.wifi.WifiStateMachine}, or via a network score in
diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
index 71124bb..36e4717 100755
--- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
+++ b/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
@@ -43,7 +43,7 @@
  */
 public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
     private static final String TAG = "WifiNetworkScoreCache";
-    private static final boolean DBG = false;
+    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
 
     // A Network scorer returns a score in the range [-128, +127]
     // We treat the lowest possible score as though there were no score, effectively allowing the
@@ -83,18 +83,28 @@
         if (networks == null || networks.isEmpty()) {
            return;
         }
-        Log.d(TAG, "updateScores list size=" + networks.size());
+        if (DBG) {
+            Log.d(TAG, "updateScores list size=" + networks.size());
+        }
+
+        boolean changed = false;
 
         synchronized(mNetworkCache) {
             for (ScoredNetwork network : networks) {
                 String networkKey = buildNetworkKey(network);
-                if (networkKey == null) continue;
+                if (networkKey == null) {
+                    if (DBG) {
+                        Log.d(TAG, "Failed to build network key for ScoredNetwork" + network);
+                    }
+                    continue;
+                }
                 mNetworkCache.put(networkKey, network);
+                changed = true;
             }
         }
 
         synchronized (mCacheLock) {
-            if (mListener != null) {
+            if (mListener != null && changed) {
                 mListener.post(networks);
             }
         }
@@ -170,25 +180,49 @@
         return score;
     }
 
-    private ScoredNetwork getScoredNetwork(ScanResult result) {
+    @Nullable
+    public ScoredNetwork getScoredNetwork(ScanResult result) {
         String key = buildNetworkKey(result);
         if (key == null) return null;
 
-        //find it
         synchronized(mNetworkCache) {
             ScoredNetwork network = mNetworkCache.get(key);
             return network;
         }
     }
 
-     private String buildNetworkKey(ScoredNetwork network) {
-        if (network == null || network.networkKey == null) return null;
-        if (network.networkKey.wifiKey == null) return null;
-        if (network.networkKey.type == NetworkKey.TYPE_WIFI) {
-            String key = network.networkKey.wifiKey.ssid;
+    /** Returns the ScoredNetwork for the given key. */
+    @Nullable
+    public ScoredNetwork getScoredNetwork(NetworkKey networkKey) {
+        String key = buildNetworkKey(networkKey);
+        if (key == null) {
+            if (DBG) {
+                Log.d(TAG, "Could not build key string for Network Key: " + networkKey);
+            }
+            return null;
+        }
+        synchronized (mNetworkCache) {
+            return mNetworkCache.get(key);
+        }
+    }
+
+    private String buildNetworkKey(ScoredNetwork network) {
+        if (network == null) {
+            return null;
+        }
+        return buildNetworkKey(network.networkKey);
+    }
+
+    private String buildNetworkKey(NetworkKey networkKey) {
+        if (networkKey == null) {
+            return null;
+        }
+        if (networkKey.wifiKey == null) return null;
+        if (networkKey.type == NetworkKey.TYPE_WIFI) {
+            String key = networkKey.wifiKey.ssid;
             if (key == null) return null;
-            if (network.networkKey.wifiKey.bssid != null) {
-                key = key + network.networkKey.wifiKey.bssid;
+            if (networkKey.wifiKey.bssid != null) {
+                key = key + networkKey.wifiKey.bssid;
             }
             return key;
         }