Merge "Only animate when the slice is actually animating" into pi-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 20f0ba8..3b4a0be 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -384,16 +384,16 @@
 
   public final class StatsManager {
     method public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
-    method public boolean addConfiguration(long, byte[]);
-    method public byte[] getData(long);
-    method public byte[] getMetadata();
+    method public deprecated boolean addConfiguration(long, byte[]);
+    method public deprecated byte[] getData(long);
+    method public deprecated byte[] getMetadata();
     method public byte[] getReports(long) throws android.app.StatsManager.StatsUnavailableException;
     method public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException;
     method public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException;
-    method public boolean removeConfiguration(long);
+    method public deprecated boolean removeConfiguration(long);
     method public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException;
-    method public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
-    method public boolean setDataFetchOperation(long, android.app.PendingIntent);
+    method public deprecated boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
+    method public deprecated boolean setDataFetchOperation(long, android.app.PendingIntent);
     method public void setFetchReportsOperation(android.app.PendingIntent, long) throws android.app.StatsManager.StatsUnavailableException;
     field public static final java.lang.String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
     field public static final java.lang.String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
diff --git a/api/test-current.txt b/api/test-current.txt
index f1c6120..f0017b9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -621,6 +621,19 @@
     method public static final int getThreadScheduler(int) throws java.lang.IllegalArgumentException;
   }
 
+  public final class RemoteCallback implements android.os.Parcelable {
+    ctor public RemoteCallback(android.os.RemoteCallback.OnResultListener);
+    ctor public RemoteCallback(android.os.RemoteCallback.OnResultListener, android.os.Handler);
+    method public int describeContents();
+    method public void sendResult(android.os.Bundle);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.os.RemoteCallback> CREATOR;
+  }
+
+  public static abstract interface RemoteCallback.OnResultListener {
+    method public abstract void onResult(android.os.Bundle);
+  }
+
   public final class StrictMode {
     method public static void setViolationLogger(android.os.StrictMode.ViolationLogger);
     field public static final int DETECT_CUSTOM = 8; // 0x8
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
index 2fc5808..c6d2bc8 100644
--- a/cmds/media/src/com/android/commands/media/Media.java
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -171,7 +171,6 @@
             showError("Error: unknown dispatch code '" + cmd + "'");
             return;
         }
-
         final long now = SystemClock.uptimeMillis();
         sendMediaKey(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0, 0,
                 KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
@@ -189,7 +188,6 @@
         @Override
         public void onSessionDestroyed() {
             System.out.println("onSessionDestroyed. Enter q to quit.");
-
         }
 
         @Override
@@ -246,7 +244,7 @@
                 @Override
                 protected void onLooperPrepared() {
                     try {
-                        mController.registerCallbackListener(ControllerMonitor.this);
+                        mController.registerCallbackListener(PACKAGE_NAME, ControllerMonitor.this);
                     } catch (RemoteException e) {
                         System.out.println("Error registering monitor callback");
                     }
@@ -266,13 +264,13 @@
                     } else if ("q".equals(line) || "quit".equals(line)) {
                         break;
                     } else if ("play".equals(line)) {
-                        mController.play(PACKAGE_NAME);
+                        dispatchKeyCode(KeyEvent.KEYCODE_MEDIA_PLAY);
                     } else if ("pause".equals(line)) {
-                        mController.pause(PACKAGE_NAME);
+                        dispatchKeyCode(KeyEvent.KEYCODE_MEDIA_PAUSE);
                     } else if ("next".equals(line)) {
-                        mController.next(PACKAGE_NAME);
+                        dispatchKeyCode(KeyEvent.KEYCODE_MEDIA_NEXT);
                     } else if ("previous".equals(line)) {
-                        mController.previous(PACKAGE_NAME);
+                        dispatchKeyCode(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
                     } else {
                         System.out.println("Invalid command: " + line);
                     }
@@ -295,6 +293,20 @@
                 }
             }
         }
+
+        private void dispatchKeyCode(int keyCode) {
+            final long now = SystemClock.uptimeMillis();
+            KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
+                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD);
+            KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
+                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD);
+            try {
+                mController.sendMediaButton(PACKAGE_NAME, null, false, down);
+                mController.sendMediaButton(PACKAGE_NAME, null, false, up);
+            } catch (RemoteException e) {
+                System.out.println("Failed to dispatch " + keyCode);
+            }
+        }
     }
 
     private void runListSessions() {
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 96f04ac..d278b55 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -352,6 +352,12 @@
 Landroid/app/ApplicationPackageManager;->mPM:Landroid/content/pm/IPackageManager;
 Landroid/app/ApplicationPackageManager;->shouldShowRequestPermissionRationale(Ljava/lang/String;)Z
 Landroid/app/AppOpsManager$OpEntry;->getDuration()I
+Landroid/app/AppOpsManager$OpEntry;->getLastAccessBackgroundTime()J
+Landroid/app/AppOpsManager$OpEntry;->getLastAccessForegroundTime()J
+Landroid/app/AppOpsManager$OpEntry;->getLastAccessTime()J
+Landroid/app/AppOpsManager$OpEntry;->getLastRejectBackgroundTime()J
+Landroid/app/AppOpsManager$OpEntry;->getLastRejectForegroundTime()J
+Landroid/app/AppOpsManager$OpEntry;->getLastRejectTime()J
 Landroid/app/AppOpsManager$OpEntry;->getMode()I
 Landroid/app/AppOpsManager$OpEntry;->getRejectTime()J
 Landroid/app/AppOpsManager$PackageOps;-><init>(Ljava/lang/String;ILjava/util/List;)V
@@ -359,6 +365,7 @@
 Landroid/app/AppOpsManager;->checkOp(IILjava/lang/String;)I
 Landroid/app/AppOpsManager;->checkOpNoThrow(IILjava/lang/String;)I
 Landroid/app/AppOpsManager;->getOpsForPackage(ILjava/lang/String;[I)Ljava/util/List;
+Landroid/app/AppOpsManager;->MODE_FOREGROUND:I
 Landroid/app/AppOpsManager;->mService:Lcom/android/internal/app/IAppOpsService;
 Landroid/app/AppOpsManager;->noteOp(I)I
 Landroid/app/AppOpsManager;->noteOp(IILjava/lang/String;)I
@@ -448,7 +455,10 @@
 Landroid/app/AppOpsManager;->resetAllModes()V
 Landroid/app/AppOpsManager;->setRestriction(III[Ljava/lang/String;)V
 Landroid/app/AppOpsManager;->sOpPerms:[Ljava/lang/String;
+Landroid/app/AppOpsManager;->startWatchingMode(Ljava/lang/String;Ljava/lang/String;ILandroid/app/AppOpsManager$OnOpChangedListener;)V
 Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I
+Landroid/app/AppOpsManager;->unsafeCheckOpRaw(Ljava/lang/String;ILjava/lang/String;)I
+Landroid/app/AppOpsManager;->WATCH_FOREGROUND_CHANGES:I
 Landroid/app/AppOpsManager;->_NUM_OP:I
 Landroid/app/assist/AssistContent;-><init>(Landroid/os/Parcel;)V
 Landroid/app/assist/AssistContent;->mClipData:Landroid/content/ClipData;
@@ -855,7 +865,9 @@
 Landroid/app/PictureInPictureArgs;-><init>()V
 Landroid/app/PictureInPictureArgs;->setActions(Ljava/util/List;)V
 Landroid/app/PictureInPictureArgs;->setAspectRatio(F)V
+Landroid/app/PictureInPictureParams;->getActions()Ljava/util/List;
 Landroid/app/PictureInPictureParams;->getAspectRatio()F
+Landroid/app/PictureInPictureParams;->getSourceRectHint()Landroid/graphics/Rect;
 Landroid/app/Presentation;->createPresentationContext(Landroid/content/Context;Landroid/view/Display;I)Landroid/content/Context;
 Landroid/app/ProgressDialog;->mMessageView:Landroid/widget/TextView;
 Landroid/app/ProgressDialog;->mProgress:Landroid/widget/ProgressBar;
@@ -1029,6 +1041,7 @@
 Landroid/bluetooth/BluetoothA2dp;->setOptionalCodecsEnabled(Landroid/bluetooth/BluetoothDevice;I)V
 Landroid/bluetooth/BluetoothA2dp;->stateToString(I)Ljava/lang/String;
 Landroid/bluetooth/BluetoothA2dp;->supportsOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)I
+Landroid/bluetooth/BluetoothA2dpSink;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
 Landroid/bluetooth/BluetoothAdapter;->disable(Z)Z
 Landroid/bluetooth/BluetoothAdapter;->factoryReset()Z
 Landroid/bluetooth/BluetoothAdapter;->getBluetoothManager()Landroid/bluetooth/IBluetoothManager;
@@ -1104,6 +1117,7 @@
 Landroid/bluetooth/BluetoothDevice;->EXTRA_SDP_SEARCH_STATUS:Ljava/lang/String;
 Landroid/bluetooth/BluetoothDevice;->getAlias()Ljava/lang/String;
 Landroid/bluetooth/BluetoothDevice;->getAliasName()Ljava/lang/String;
+Landroid/bluetooth/BluetoothDevice;->getBatteryLevel()I
 Landroid/bluetooth/BluetoothDevice;->getMessageAccessPermission()I
 Landroid/bluetooth/BluetoothDevice;->getPhonebookAccessPermission()I
 Landroid/bluetooth/BluetoothDevice;->getService()Landroid/bluetooth/IBluetooth;
@@ -1164,6 +1178,7 @@
 Landroid/bluetooth/BluetoothHearingAid;->ACTION_ACTIVE_DEVICE_CHANGED:Ljava/lang/String;
 Landroid/bluetooth/BluetoothHearingAid;->getActiveDevices()Ljava/util/List;
 Landroid/bluetooth/BluetoothHearingAid;->setActiveDevice(Landroid/bluetooth/BluetoothDevice;)Z
+Landroid/bluetooth/BluetoothMap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
 Landroid/bluetooth/BluetoothMapClient;->sendMessage(Landroid/bluetooth/BluetoothDevice;[Landroid/net/Uri;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)Z
 Landroid/bluetooth/BluetoothPan;-><init>(Landroid/content/Context;Landroid/bluetooth/BluetoothProfile$ServiceListener;)V
 Landroid/bluetooth/BluetoothPan;->close()V
@@ -1175,11 +1190,13 @@
 Landroid/bluetooth/BluetoothPan;->isValidDevice(Landroid/bluetooth/BluetoothDevice;)Z
 Landroid/bluetooth/BluetoothPan;->log(Ljava/lang/String;)V
 Landroid/bluetooth/BluetoothPan;->setBluetoothTethering(Z)V
+Landroid/bluetooth/BluetoothPbap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
 Landroid/bluetooth/BluetoothProfile;->A2DP_SINK:I
 Landroid/bluetooth/BluetoothProfile;->AVRCP_CONTROLLER:I
 Landroid/bluetooth/BluetoothProfile;->PAN:I
 Landroid/bluetooth/BluetoothProfile;->PRIORITY_AUTO_CONNECT:I
 Landroid/bluetooth/BluetoothProfile;->PRIORITY_UNDEFINED:I
+Landroid/bluetooth/BluetoothSap;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
 Landroid/bluetooth/BluetoothServerSocket;->mSocket:Landroid/bluetooth/BluetoothSocket;
 Landroid/bluetooth/BluetoothSocket;->EADDRINUSE:I
 Landroid/bluetooth/BluetoothSocket;->flush()V
@@ -1311,6 +1328,7 @@
 Landroid/content/Context;->checkPermission(Ljava/lang/String;IILandroid/os/IBinder;)I
 Landroid/content/Context;->COUNTRY_DETECTOR:Ljava/lang/String;
 Landroid/content/Context;->createApplicationContext(Landroid/content/pm/ApplicationInfo;I)Landroid/content/Context;
+Landroid/content/Context;->ETHERNET_SERVICE:Ljava/lang/String;
 Landroid/content/Context;->getBasePackageName()Ljava/lang/String;
 Landroid/content/Context;->getDisplay()Landroid/view/Display;
 Landroid/content/Context;->getSharedPrefsFile(Ljava/lang/String;)Ljava/io/File;
@@ -1389,6 +1407,7 @@
 Landroid/content/ISyncAdapter$Stub;-><init>()V
 Landroid/content/ISyncAdapter$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncAdapter;
 Landroid/content/ISyncAdapter;->cancelSync(Landroid/content/ISyncContext;)V
+Landroid/content/ISyncAdapter;->onUnsyncableAccount(Landroid/content/ISyncAdapterUnsyncableAccountCallback;)V
 Landroid/content/ISyncAdapter;->startSync(Landroid/content/ISyncContext;Ljava/lang/String;Landroid/accounts/Account;Landroid/os/Bundle;)V
 Landroid/content/ISyncContext$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/ISyncContext$Stub$Proxy;->mRemote:Landroid/os/IBinder;
@@ -1434,6 +1453,8 @@
 Landroid/content/pm/ApplicationInfo;->secondaryCpuAbi:Ljava/lang/String;
 Landroid/content/pm/ApplicationInfo;->secondaryNativeLibraryDir:Ljava/lang/String;
 Landroid/content/pm/ApplicationInfo;->versionCode:I
+Landroid/content/pm/BaseParceledListSlice;->getList()Ljava/util/List;
+Landroid/content/pm/BaseParceledListSlice;->writeParcelableCreator(Ljava/lang/Object;Landroid/os/Parcel;)V
 Landroid/content/pm/ComponentInfo;->getComponentName()Landroid/content/ComponentName;
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
@@ -1653,6 +1674,7 @@
 Landroid/content/pm/PackageParser$Package;->mSharedUserId:Ljava/lang/String;
 Landroid/content/pm/PackageParser$Package;->mSharedUserLabel:I
 Landroid/content/pm/PackageParser$Package;->mSigningDetails:Landroid/content/pm/PackageParser$SigningDetails;
+Landroid/content/pm/PackageParser$Package;->mUpgradeKeySets:Landroid/util/ArraySet;
 Landroid/content/pm/PackageParser$Package;->mVersionCode:I
 Landroid/content/pm/PackageParser$Package;->mVersionName:Ljava/lang/String;
 Landroid/content/pm/PackageParser$Package;->packageName:Ljava/lang/String;
@@ -1706,6 +1728,8 @@
 Landroid/content/pm/PackageStats;->userHandle:I
 Landroid/content/pm/PackageUserState;-><init>()V
 Landroid/content/pm/ParceledListSlice;-><init>(Ljava/util/List;)V
+Landroid/content/pm/ParceledListSlice;->CREATOR:Landroid/os/Parcelable$ClassLoaderCreator;
+Landroid/content/pm/ParceledListSlice;->writeParcelableCreator(Landroid/os/Parcelable;Landroid/os/Parcel;)V
 Landroid/content/pm/PermissionInfo;->protectionToString(I)Ljava/lang/String;
 Landroid/content/pm/RegisteredServicesCache$ServiceInfo;->componentName:Landroid/content/ComponentName;
 Landroid/content/pm/RegisteredServicesCache$ServiceInfo;->type:Ljava/lang/Object;
@@ -2088,6 +2112,8 @@
 Landroid/graphics/Canvas;->mBitmap:Landroid/graphics/Bitmap;
 Landroid/graphics/Canvas;->release()V
 Landroid/graphics/Canvas;->setScreenDensity(I)V
+Landroid/graphics/CanvasProperty;->createFloat(F)Landroid/graphics/CanvasProperty;
+Landroid/graphics/CanvasProperty;->createPaint(Landroid/graphics/Paint;)Landroid/graphics/CanvasProperty;
 Landroid/graphics/ColorMatrixColorFilter;->mMatrix:Landroid/graphics/ColorMatrix;
 Landroid/graphics/ColorMatrixColorFilter;->setColorMatrix(Landroid/graphics/ColorMatrix;)V
 Landroid/graphics/drawable/AnimatedImageDrawable;->onAnimationEnd()V
@@ -2197,6 +2223,7 @@
 Landroid/graphics/drawable/VectorDrawable;->mTintFilter:Landroid/graphics/PorterDuffColorFilter;
 Landroid/graphics/drawable/VectorDrawable;->setAllowCaching(Z)V
 Landroid/graphics/FontFamily;-><init>()V
+Landroid/graphics/FontFamily;-><init>([Ljava/lang/String;I)V
 Landroid/graphics/FontFamily;->abortCreation()V
 Landroid/graphics/FontFamily;->addFontFromAssetManager(Landroid/content/res/AssetManager;Ljava/lang/String;IZIII[Landroid/graphics/fonts/FontVariationAxis;)Z
 Landroid/graphics/FontFamily;->addFontFromBuffer(Ljava/nio/ByteBuffer;I[Landroid/graphics/fonts/FontVariationAxis;II)Z
@@ -2216,6 +2243,8 @@
 Landroid/graphics/Insets;->of(Landroid/graphics/Rect;)Landroid/graphics/Insets;
 Landroid/graphics/Insets;->right:I
 Landroid/graphics/Insets;->top:I
+Landroid/graphics/LightingColorFilter;->setColorAdd(I)V
+Landroid/graphics/LightingColorFilter;->setColorMultiply(I)V
 Landroid/graphics/LinearGradient;->mColor0:I
 Landroid/graphics/LinearGradient;->mColor1:I
 Landroid/graphics/LinearGradient;->mColors:[I
@@ -2281,6 +2310,7 @@
 Landroid/graphics/TableMaskFilter;->CreateClipTable(II)Landroid/graphics/TableMaskFilter;
 Landroid/graphics/TemporaryBuffer;->obtain(I)[C
 Landroid/graphics/TemporaryBuffer;->recycle([C)V
+Landroid/graphics/Typeface;-><init>(J)V
 Landroid/graphics/Typeface;->createFromFamilies([Landroid/graphics/FontFamily;)Landroid/graphics/Typeface;
 Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;II)Landroid/graphics/Typeface;
 Landroid/graphics/Typeface;->createFromFamiliesWithDefault([Landroid/graphics/FontFamily;Ljava/lang/String;II)Landroid/graphics/Typeface;
@@ -2290,6 +2320,7 @@
 Landroid/graphics/Typeface;->native_instance:J
 Landroid/graphics/Typeface;->sDefaults:[Landroid/graphics/Typeface;
 Landroid/graphics/Typeface;->setDefault(Landroid/graphics/Typeface;)V
+Landroid/graphics/Typeface;->sSystemFallbackMap:Ljava/util/Map;
 Landroid/graphics/Typeface;->sSystemFontMap:Ljava/util/Map;
 Landroid/graphics/Xfermode;->porterDuffMode:I
 Landroid/hardware/biometrics/BiometricConstants;->BIOMETRIC_ACQUIRED_GOOD:I
@@ -2413,6 +2444,7 @@
 Landroid/hardware/Camera;->openLegacy(II)Landroid/hardware/Camera;
 Landroid/hardware/Camera;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
 Landroid/hardware/Camera;->previewEnabled()Z
+Landroid/hardware/Camera;->setPreviewSurface(Landroid/view/Surface;)V
 Landroid/hardware/display/DisplayManager;->ACTION_WIFI_DISPLAY_STATUS_CHANGED:Ljava/lang/String;
 Landroid/hardware/display/DisplayManager;->connectWifiDisplay(Ljava/lang/String;)V
 Landroid/hardware/display/DisplayManager;->disconnectWifiDisplay()V
@@ -3241,6 +3273,14 @@
 Landroid/net/ConnectivityManager;->TYPE_PROXY:I
 Landroid/net/ConnectivityManager;->TYPE_WIFI_P2P:I
 Landroid/net/ConnectivityManager;->unregisterNetworkFactory(Landroid/os/Messenger;)V
+Landroid/net/EthernetManager$Listener;->onAvailabilityChanged(Ljava/lang/String;Z)V
+Landroid/net/EthernetManager;->addListener(Landroid/net/EthernetManager$Listener;)V
+Landroid/net/EthernetManager;->getAvailableInterfaces()[Ljava/lang/String;
+Landroid/net/EthernetManager;->getConfiguration(Ljava/lang/String;)Landroid/net/IpConfiguration;
+Landroid/net/EthernetManager;->isAvailable()Z
+Landroid/net/EthernetManager;->isAvailable(Ljava/lang/String;)Z
+Landroid/net/EthernetManager;->removeListener(Landroid/net/EthernetManager$Listener;)V
+Landroid/net/EthernetManager;->setConfiguration(Ljava/lang/String;Landroid/net/IpConfiguration;)V
 Landroid/net/http/SslCertificate;->getDigest(Ljava/security/cert/X509Certificate;Ljava/lang/String;)Ljava/lang/String;
 Landroid/net/http/SslCertificate;->getSerialNumber(Ljava/security/cert/X509Certificate;)Ljava/lang/String;
 Landroid/net/http/SslCertificate;->inflateCertificateView(Landroid/content/Context;)Landroid/view/View;
@@ -3855,6 +3895,7 @@
 Landroid/os/Environment;->buildExternalStorageAppFilesDirs(Ljava/lang/String;)[Ljava/io/File;
 Landroid/os/Environment;->buildExternalStorageAppMediaDirs(Ljava/lang/String;)[Ljava/io/File;
 Landroid/os/Environment;->buildExternalStorageAppObbDirs(Ljava/lang/String;)[Ljava/io/File;
+Landroid/os/Environment;->getDataSystemDirectory()Ljava/io/File;
 Landroid/os/Environment;->getLegacyExternalStorageObbDirectory()Ljava/io/File;
 Landroid/os/Environment;->getOemDirectory()Ljava/io/File;
 Landroid/os/Environment;->getStorageDirectory()Ljava/io/File;
@@ -4129,6 +4170,7 @@
 Landroid/os/storage/StorageManager;->getVolumes()Ljava/util/List;
 Landroid/os/storage/StorageManager;->getVolumeState(Ljava/lang/String;)Ljava/lang/String;
 Landroid/os/storage/StorageManager;->isFileEncryptedNativeOnly()Z
+Landroid/os/storage/StorageManager;->isUsbMassStorageConnected()Z
 Landroid/os/storage/StorageManager;->isUsbMassStorageEnabled()Z
 Landroid/os/storage/StorageManager;->partitionPublic(Ljava/lang/String;)V
 Landroid/os/storage/StorageManager;->unmount(Ljava/lang/String;)V
@@ -4139,7 +4181,10 @@
 Landroid/os/storage/StorageVolume;->getPath()Ljava/lang/String;
 Landroid/os/storage/StorageVolume;->getPathFile()Ljava/io/File;
 Landroid/os/storage/StorageVolume;->getUserLabel()Ljava/lang/String;
+Landroid/os/storage/StorageVolume;->mDescription:Ljava/lang/String;
+Landroid/os/storage/StorageVolume;->mId:Ljava/lang/String;
 Landroid/os/storage/StorageVolume;->mPath:Ljava/io/File;
+Landroid/os/storage/StorageVolume;->mPrimary:Z
 Landroid/os/storage/StorageVolume;->mRemovable:Z
 Landroid/os/storage/VolumeInfo;-><init>(Landroid/os/Parcel;)V
 Landroid/os/storage/VolumeInfo;->buildBrowseIntent()Landroid/content/Intent;
@@ -4187,6 +4232,7 @@
 Landroid/os/StrictMode;->onBinderStrictModePolicyChange(I)V
 Landroid/os/StrictMode;->onWebViewMethodCalledOnWrongThread(Ljava/lang/Throwable;)V
 Landroid/os/StrictMode;->sLastVmViolationTime:Ljava/util/HashMap;
+Landroid/os/StrictMode;->sWindowManager:Landroid/util/Singleton;
 Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal;
 Landroid/os/SystemClock;->currentThreadTimeMicro()J
 Landroid/os/SystemClock;->currentTimeMicro()J
@@ -4467,6 +4513,7 @@
 Landroid/provider/Settings$Global;->putStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;Ljava/lang/String;I)Z
 Landroid/provider/Settings$Global;->REQUIRE_PASSWORD_TO_DECRYPT:Ljava/lang/String;
 Landroid/provider/Settings$Global;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
+Landroid/provider/Settings$Global;->sProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
 Landroid/provider/Settings$Global;->WEBVIEW_PROVIDER:Ljava/lang/String;
 Landroid/provider/Settings$Global;->WIFI_SAVED_STATE:Ljava/lang/String;
 Landroid/provider/Settings$Global;->WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED:Ljava/lang/String;
@@ -4479,6 +4526,7 @@
 Landroid/provider/Settings$NameValueCache;->mProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
 Landroid/provider/Settings$Secure;->ACCESSIBILITY_AUTOCLICK_ENABLED:Ljava/lang/String;
 Landroid/provider/Settings$Secure;->ACCESSIBILITY_CAPTIONING_TYPEFACE:Ljava/lang/String;
+Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_DALTONIZER:Ljava/lang/String;
 Landroid/provider/Settings$Secure;->ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED:Ljava/lang/String;
 Landroid/provider/Settings$Secure;->ACCESSIBILITY_LARGE_POINTER_ICON:Ljava/lang/String;
 Landroid/provider/Settings$Secure;->ANR_SHOW_BACKGROUND:Ljava/lang/String;
@@ -4526,6 +4574,7 @@
 Landroid/provider/Settings$System;->LOCKSCREEN_SOUNDS_ENABLED:Ljava/lang/String;
 Landroid/provider/Settings$System;->LOCK_SOUND:Ljava/lang/String;
 Landroid/provider/Settings$System;->MASTER_MONO:Ljava/lang/String;
+Landroid/provider/Settings$System;->NOTIFICATION_LIGHT_PULSE:Ljava/lang/String;
 Landroid/provider/Settings$System;->POINTER_LOCATION:Ljava/lang/String;
 Landroid/provider/Settings$System;->POINTER_SPEED:Ljava/lang/String;
 Landroid/provider/Settings$System;->PRIVATE_SETTINGS:Ljava/util/Set;
@@ -4536,6 +4585,7 @@
 Landroid/provider/Settings$System;->SETTINGS_TO_BACKUP:[Ljava/lang/String;
 Landroid/provider/Settings$System;->SHOW_TOUCHES:Ljava/lang/String;
 Landroid/provider/Settings$System;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
+Landroid/provider/Settings$System;->sProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
 Landroid/provider/Settings$System;->TTY_MODE:Ljava/lang/String;
 Landroid/provider/Settings$System;->UNLOCK_SOUND:Ljava/lang/String;
 Landroid/provider/Settings$System;->VIBRATE_IN_SILENT:Ljava/lang/String;
@@ -4651,6 +4701,7 @@
 Landroid/R$styleable;->ProgressBar_progressDrawable:I
 Landroid/R$styleable;->RingtonePreference:[I
 Landroid/R$styleable;->ScrollView:[I
+Landroid/R$styleable;->SearchView:[I
 Landroid/R$styleable;->SeekBar:[I
 Landroid/R$styleable;->SeekBar_thumb:I
 Landroid/R$styleable;->SeekBar_thumbOffset:I
@@ -5201,6 +5252,7 @@
 Landroid/telephony/DisconnectCause;->toString(I)Ljava/lang/String;
 Landroid/telephony/euicc/EuiccInfo;->osVersion:Ljava/lang/String;
 Landroid/telephony/gsm/GsmCellLocation;->setPsc(I)V
+Landroid/telephony/ims/ImsSsInfo;-><init>()V
 Landroid/telephony/NeighboringCellInfo;->mCid:I
 Landroid/telephony/NeighboringCellInfo;->mLac:I
 Landroid/telephony/NeighboringCellInfo;->mNetworkType:I
@@ -5218,6 +5270,7 @@
 Landroid/telephony/PhoneNumberUtils;->isEmergencyNumber(Ljava/lang/String;Ljava/lang/String;)Z
 Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
 Landroid/telephony/PhoneNumberUtils;->isNanp(Ljava/lang/String;)Z
+Landroid/telephony/PhoneNumberUtils;->isPotentialLocalEmergencyNumber(Landroid/content/Context;Ljava/lang/String;)Z
 Landroid/telephony/PhoneNumberUtils;->isUriNumber(Ljava/lang/String;)Z
 Landroid/telephony/PhoneNumberUtils;->isVoiceMailNumber(Landroid/content/Context;ILjava/lang/String;)Z
 Landroid/telephony/PhoneNumberUtils;->MIN_MATCH:I
@@ -5381,6 +5434,7 @@
 Landroid/telephony/SubscriptionManager;->setDataRoaming(II)I
 Landroid/telephony/SubscriptionManager;->setDefaultDataSubId(I)V
 Landroid/telephony/SubscriptionManager;->setDefaultSmsSubId(I)V
+Landroid/telephony/SubscriptionManager;->setDisplayNumber(Ljava/lang/String;I)I
 Landroid/telephony/TelephonyManager$MultiSimVariants;->TSTS:Landroid/telephony/TelephonyManager$MultiSimVariants;
 Landroid/telephony/TelephonyManager$MultiSimVariants;->UNKNOWN:Landroid/telephony/TelephonyManager$MultiSimVariants;
 Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants;
@@ -5678,6 +5732,7 @@
 Landroid/util/MathUtils;->constrain(FFF)F
 Landroid/util/MathUtils;->constrain(III)I
 Landroid/util/MathUtils;->lerp(FFF)F
+Landroid/util/MathUtils;->max(II)F
 Landroid/util/NtpTrustedTime;->forceRefresh()Z
 Landroid/util/NtpTrustedTime;->getCachedNtpTime()J
 Landroid/util/NtpTrustedTime;->getCachedNtpTimeReference()J
@@ -5727,6 +5782,7 @@
 Landroid/view/accessibility/AccessibilityInteractionClient;->clearCache()V
 Landroid/view/accessibility/AccessibilityInteractionClient;->getInstance()Landroid/view/accessibility/AccessibilityInteractionClient;
 Landroid/view/accessibility/AccessibilityInteractionClient;->setSameThreadMessage(Landroid/os/Message;)V
+Landroid/view/accessibility/AccessibilityManager;->DALTONIZER_SIMULATE_MONOCHROMACY:I
 Landroid/view/accessibility/AccessibilityManager;->getInstance(Landroid/content/Context;)Landroid/view/accessibility/AccessibilityManager;
 Landroid/view/accessibility/AccessibilityManager;->isHighTextContrastEnabled()Z
 Landroid/view/accessibility/AccessibilityManager;->mAccessibilityStateChangeListeners:Landroid/util/ArrayMap;
@@ -5764,6 +5820,7 @@
 Landroid/view/ActionProvider;->reset()V
 Landroid/view/ActionProvider;->setSubUiVisibilityListener(Landroid/view/ActionProvider$SubUiVisibilityListener;)V
 Landroid/view/animation/Animation;->detach()V
+Landroid/view/animation/Animation;->getInvalidateRegion(IIIILandroid/graphics/RectF;Landroid/view/animation/Transformation;)V
 Landroid/view/animation/Animation;->initializeInvalidateRegion(IIII)V
 Landroid/view/animation/Animation;->mListener:Landroid/view/animation/Animation$AnimationListener;
 Landroid/view/animation/Animation;->mPreviousRegion:Landroid/graphics/RectF;
@@ -5825,6 +5882,7 @@
 Landroid/view/DisplayInfo;->logicalWidth:I
 Landroid/view/DisplayInfo;->rotation:I
 Landroid/view/DisplayListCanvas;->callDrawGLFunction2(J)V
+Landroid/view/DisplayListCanvas;->drawCircle(Landroid/graphics/CanvasProperty;Landroid/graphics/CanvasProperty;Landroid/graphics/CanvasProperty;Landroid/graphics/CanvasProperty;)V
 Landroid/view/DisplayListCanvas;->drawGLFunctor2(JLjava/lang/Runnable;)V
 Landroid/view/DragEvent;->mClipData:Landroid/content/ClipData;
 Landroid/view/DragEvent;->mClipDescription:Landroid/content/ClipDescription;
@@ -6031,9 +6089,13 @@
 Landroid/view/RenderNode;->offsetLeftAndRight(I)Z
 Landroid/view/RenderNode;->output()V
 Landroid/view/RenderNode;->setHasOverlappingRendering(Z)Z
+Landroid/view/RenderNode;->setProjectBackwards(Z)Z
 Landroid/view/RenderNodeAnimator;-><init>(IF)V
+Landroid/view/RenderNodeAnimator;-><init>(Landroid/graphics/CanvasProperty;F)V
+Landroid/view/RenderNodeAnimator;-><init>(Landroid/graphics/CanvasProperty;IF)V
 Landroid/view/RenderNodeAnimator;->callOnFinished(Landroid/view/RenderNodeAnimator;)V
 Landroid/view/RenderNodeAnimator;->mapViewPropertyToRenderProperty(I)I
+Landroid/view/RenderNodeAnimator;->setStartValue(F)V
 Landroid/view/RenderNodeAnimator;->setTarget(Landroid/view/View;)V
 Landroid/view/ScaleGestureDetector;->mListener:Landroid/view/ScaleGestureDetector$OnScaleGestureListener;
 Landroid/view/ScaleGestureDetector;->mMinSpan:I
@@ -6125,6 +6187,10 @@
 Landroid/view/TextureView;->nCreateNativeWindow(Landroid/graphics/SurfaceTexture;)V
 Landroid/view/TextureView;->nDestroyNativeWindow()V
 Landroid/view/TextureView;->onDetachedFromWindowInternal()V
+Landroid/view/ThreadedRenderer;->addRenderNode(Landroid/view/RenderNode;Z)V
+Landroid/view/ThreadedRenderer;->drawRenderNode(Landroid/view/RenderNode;)V
+Landroid/view/ThreadedRenderer;->removeRenderNode(Landroid/view/RenderNode;)V
+Landroid/view/ThreadedRenderer;->setContentDrawBounds(IIII)V
 Landroid/view/ThreadedRenderer;->setupDiskCache(Ljava/io/File;)V
 Landroid/view/TouchDelegate;->mDelegateTargeted:Z
 Landroid/view/VelocityTracker$Estimator;->confidence:F
@@ -6204,10 +6270,12 @@
 Landroid/view/View;->getIterableTextForAccessibility()Ljava/lang/CharSequence;
 Landroid/view/View;->getIteratorForGranularity(I)Landroid/view/AccessibilityIterators$TextSegmentIterator;
 Landroid/view/View;->getListenerInfo()Landroid/view/View$ListenerInfo;
+Landroid/view/View;->getLocationInSurface([I)V
 Landroid/view/View;->getLocationOnScreen()[I
 Landroid/view/View;->getRawTextAlignment()I
 Landroid/view/View;->getRawTextDirection()I
 Landroid/view/View;->getScrollCache()Landroid/view/View$ScrollabilityCache;
+Landroid/view/View;->getThreadedRenderer()Landroid/view/ThreadedRenderer;
 Landroid/view/View;->getTransitionAlpha()F
 Landroid/view/View;->getVerticalScrollFactor()F
 Landroid/view/View;->getViewRootImpl()Landroid/view/ViewRootImpl;
@@ -6277,8 +6345,11 @@
 Landroid/view/View;->notifySubtreeAccessibilityStateChangedIfNeeded()V
 Landroid/view/View;->notifyViewAccessibilityStateChangedIfNeeded(I)V
 Landroid/view/View;->onCloseSystemDialogs(Ljava/lang/String;)V
+Landroid/view/View;->onDetachedFromWindowInternal()V
+Landroid/view/View;->onDrawHorizontalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
 Landroid/view/View;->onDrawVerticalScrollBar(Landroid/graphics/Canvas;Landroid/graphics/drawable/Drawable;IIII)V
 Landroid/view/View;->onFocusLost()V
+Landroid/view/View;->onInitializeAccessibilityEventInternal(Landroid/view/accessibility/AccessibilityEvent;)V
 Landroid/view/View;->performAccessibilityActionInternal(ILandroid/os/Bundle;)Z
 Landroid/view/View;->pointInView(FFF)Z
 Landroid/view/View;->recomputePadding()V
@@ -6312,6 +6383,7 @@
 Landroid/view/View;->toLocalMotionEvent(Landroid/view/MotionEvent;)Z
 Landroid/view/View;->transformMatrixToGlobal(Landroid/graphics/Matrix;)V
 Landroid/view/View;->transformMatrixToLocal(Landroid/graphics/Matrix;)V
+Landroid/view/View;->updateDisplayListIfDirty()Landroid/view/RenderNode;
 Landroid/view/ViewConfiguration;->getDeviceGlobalActionKeyTimeout()J
 Landroid/view/ViewConfiguration;->getDoubleTapMinTime()I
 Landroid/view/ViewConfiguration;->getDoubleTapSlop()I
@@ -6340,6 +6412,7 @@
 Landroid/view/ViewGroup;->dispatchGetDisplayList()V
 Landroid/view/ViewGroup;->dispatchViewAdded(Landroid/view/View;)V
 Landroid/view/ViewGroup;->dispatchViewRemoved(Landroid/view/View;)V
+Landroid/view/ViewGroup;->encodeProperties(Landroid/view/ViewHierarchyEncoder;)V
 Landroid/view/ViewGroup;->FLAG_DISALLOW_INTERCEPT:I
 Landroid/view/ViewGroup;->FLAG_SUPPORT_STATIC_TRANSFORMATIONS:I
 Landroid/view/ViewGroup;->FLAG_USE_CHILD_DRAWING_ORDER:I
@@ -6357,6 +6430,7 @@
 Landroid/view/ViewGroup;->mPersistentDrawingCache:I
 Landroid/view/ViewGroup;->offsetChildrenTopAndBottom(I)V
 Landroid/view/ViewGroup;->onChildVisibilityChanged(Landroid/view/View;II)V
+Landroid/view/ViewGroup;->onInitializeAccessibilityNodeInfoInternal(Landroid/view/accessibility/AccessibilityNodeInfo;)V
 Landroid/view/ViewGroup;->removeTransientView(Landroid/view/View;)V
 Landroid/view/ViewGroup;->resetResolvedDrawables()V
 Landroid/view/ViewGroup;->resetResolvedLayoutDirection()V
@@ -6530,6 +6604,8 @@
 Landroid/webkit/IWebViewUpdateService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/webkit/IWebViewUpdateService$Stub$Proxy;->waitForAndGetProvider()Landroid/webkit/WebViewProviderResponse;
 Landroid/webkit/IWebViewUpdateService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/webkit/IWebViewUpdateService;
+Landroid/webkit/IWebViewUpdateService;->getCurrentWebViewPackageName()Ljava/lang/String;
+Landroid/webkit/IWebViewUpdateService;->getValidWebViewPackages()[Landroid/webkit/WebViewProviderInfo;
 Landroid/webkit/IWebViewUpdateService;->isFallbackPackage(Ljava/lang/String;)Z
 Landroid/webkit/JsResult;->mReceiver:Landroid/webkit/JsResult$ResultReceiver;
 Landroid/webkit/PluginData;-><init>(Ljava/io/InputStream;JLjava/util/Map;I)V
@@ -6537,6 +6613,8 @@
 Landroid/webkit/PluginData;->getHeaders()Ljava/util/Map;
 Landroid/webkit/PluginData;->getInputStream()Ljava/io/InputStream;
 Landroid/webkit/PluginData;->getStatusCode()I
+Landroid/webkit/UrlInterceptHandler;->getPluginData(Ljava/lang/String;Ljava/util/Map;)Landroid/webkit/PluginData;
+Landroid/webkit/UrlInterceptHandler;->service(Ljava/lang/String;Ljava/util/Map;)Landroid/webkit/CacheManager$CacheResult;
 Landroid/webkit/UrlInterceptRegistry;->getPluginData(Ljava/lang/String;Ljava/util/Map;)Landroid/webkit/PluginData;
 Landroid/webkit/UrlInterceptRegistry;->registerHandler(Landroid/webkit/UrlInterceptHandler;)Z
 Landroid/webkit/UrlInterceptRegistry;->setUrlInterceptDisabled(Z)V
@@ -6695,6 +6773,7 @@
 Landroid/widget/AutoCompleteTextView;->mPopup:Landroid/widget/ListPopupWindow;
 Landroid/widget/AutoCompleteTextView;->setDropDownAlwaysVisible(Z)V
 Landroid/widget/AutoCompleteTextView;->setDropDownAnimationStyle(I)V
+Landroid/widget/AutoCompleteTextView;->setDropDownDismissedOnCompletion(Z)V
 Landroid/widget/AutoCompleteTextView;->setForceIgnoreOutsideTouch(Z)V
 Landroid/widget/AutoCompleteTextView;->showDropDownAfterLayout()V
 Landroid/widget/BaseAdapter;->mDataSetObservable:Landroid/database/DataSetObservable;
@@ -6721,7 +6800,9 @@
 Landroid/widget/Editor;->invalidateTextDisplayList()V
 Landroid/widget/Editor;->mCreatedWithASelection:Z
 Landroid/widget/Editor;->mInsertionControllerEnabled:Z
+Landroid/widget/Editor;->mSelectHandleCenter:Landroid/graphics/drawable/Drawable;
 Landroid/widget/Editor;->mSelectHandleLeft:Landroid/graphics/drawable/Drawable;
+Landroid/widget/Editor;->mSelectHandleRight:Landroid/graphics/drawable/Drawable;
 Landroid/widget/Editor;->mSelectionControllerEnabled:Z
 Landroid/widget/Editor;->mShowCursor:J
 Landroid/widget/Editor;->mShowSoftInputOnFocus:Z
@@ -6822,8 +6903,10 @@
 Landroid/widget/LinearLayout;->mTotalLength:I
 Landroid/widget/LinearLayout;->mUseLargestChild:Z
 Landroid/widget/ListPopupWindow;->buildDropDown()I
+Landroid/widget/ListPopupWindow;->isDropDownAlwaysVisible()Z
 Landroid/widget/ListPopupWindow;->mDropDownList:Landroid/widget/DropDownListView;
 Landroid/widget/ListPopupWindow;->mPopup:Landroid/widget/PopupWindow;
+Landroid/widget/ListPopupWindow;->setDropDownAlwaysVisible(Z)V
 Landroid/widget/ListPopupWindow;->setForceIgnoreOutsideTouch(Z)V
 Landroid/widget/ListPopupWindow;->setListItemExpandMax(I)V
 Landroid/widget/ListView;->arrowScroll(I)Z
@@ -7441,6 +7524,7 @@
 Lcom/android/internal/os/BatteryStatsHelper;-><init>(Landroid/content/Context;ZZ)V
 Lcom/android/internal/os/BatteryStatsHelper;->clearStats()V
 Lcom/android/internal/os/BatteryStatsHelper;->create(Landroid/os/Bundle;)V
+Lcom/android/internal/os/BatteryStatsHelper;->dropFile(Landroid/content/Context;Ljava/lang/String;)V
 Lcom/android/internal/os/BatteryStatsHelper;->getBatteryBroadcast()Landroid/content/Intent;
 Lcom/android/internal/os/BatteryStatsHelper;->getMaxPower()D
 Lcom/android/internal/os/BatteryStatsHelper;->getStats()Landroid/os/BatteryStats;
@@ -7565,6 +7649,8 @@
 Lcom/android/internal/policy/IKeyguardService;->setKeyguardEnabled(Z)V
 Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback;
 Lcom/android/internal/R$anim;->fade_in:I
+Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I
+Lcom/android/internal/R$array;->config_autoBrightnessLevels:I
 Lcom/android/internal/R$array;->config_mobile_hotspot_provision_app:I
 Lcom/android/internal/R$array;->config_sms_enabled_locking_shift_tables:I
 Lcom/android/internal/R$array;->config_sms_enabled_single_shift_tables:I
@@ -7607,6 +7693,7 @@
 Lcom/android/internal/R$drawable;->no_tile_256:I
 Lcom/android/internal/R$drawable;->reticle:I
 Lcom/android/internal/R$drawable;->stat_sys_download:I
+Lcom/android/internal/R$fraction;->config_autoBrightnessAdjustmentMaxGamma:I
 Lcom/android/internal/R$id;->account_name:I
 Lcom/android/internal/R$id;->account_type:I
 Lcom/android/internal/R$id;->alertTitle:I
@@ -7683,6 +7770,8 @@
 Lcom/android/internal/R$id;->zoomControls:I
 Lcom/android/internal/R$id;->zoomMagnify:I
 Lcom/android/internal/R$integer;->config_screenBrightnessDim:I
+Lcom/android/internal/R$integer;->config_screenBrightnessSettingMaximum:I
+Lcom/android/internal/R$integer;->config_screenBrightnessSettingMinimum:I
 Lcom/android/internal/R$integer;->config_toastDefaultGravity:I
 Lcom/android/internal/R$interpolator;->accelerate_cubic:I
 Lcom/android/internal/R$interpolator;->decelerate_cubic:I
@@ -7862,6 +7951,8 @@
 Lcom/android/internal/R$styleable;->ListView_overScrollHeader:I
 Lcom/android/internal/R$styleable;->MapView:[I
 Lcom/android/internal/R$styleable;->MapView_apiKey:I
+Lcom/android/internal/R$styleable;->MenuGroup:[I
+Lcom/android/internal/R$styleable;->MenuItem:[I
 Lcom/android/internal/R$styleable;->MenuView:[I
 Lcom/android/internal/R$styleable;->PopupWindow:[I
 Lcom/android/internal/R$styleable;->PopupWindow_popupAnimationStyle:I
@@ -8092,6 +8183,8 @@
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephony;
+Lcom/android/internal/telephony/ITelephony$Stub;->DESCRIPTOR:Ljava/lang/String;
+Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_answerRingingCall:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_call:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_endCall:I
 Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
@@ -8250,6 +8343,7 @@
 Lcom/android/internal/view/menu/MenuBuilder$Callback;->onMenuItemSelected(Lcom/android/internal/view/menu/MenuBuilder;Landroid/view/MenuItem;)Z
 Lcom/android/internal/view/menu/MenuBuilder$Callback;->onMenuModeChange(Lcom/android/internal/view/menu/MenuBuilder;)V
 Lcom/android/internal/view/menu/MenuBuilder;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/view/menu/MenuBuilder;->addMenuPresenter(Lcom/android/internal/view/menu/MenuPresenter;)V
 Lcom/android/internal/view/menu/MenuBuilder;->addMenuPresenter(Lcom/android/internal/view/menu/MenuPresenter;Landroid/content/Context;)V
 Lcom/android/internal/view/menu/MenuBuilder;->collapseItemActionView(Lcom/android/internal/view/menu/MenuItemImpl;)Z
 Lcom/android/internal/view/menu/MenuBuilder;->getContext()Landroid/content/Context;
@@ -8257,6 +8351,7 @@
 Lcom/android/internal/view/menu/MenuBuilder;->getRootMenu()Lcom/android/internal/view/menu/MenuBuilder;
 Lcom/android/internal/view/menu/MenuBuilder;->getVisibleItems()Ljava/util/ArrayList;
 Lcom/android/internal/view/menu/MenuBuilder;->mContext:Landroid/content/Context;
+Lcom/android/internal/view/menu/MenuBuilder;->removeMenuPresenter(Lcom/android/internal/view/menu/MenuPresenter;)V
 Lcom/android/internal/view/menu/MenuBuilder;->setCallback(Lcom/android/internal/view/menu/MenuBuilder$Callback;)V
 Lcom/android/internal/view/menu/MenuBuilder;->setCurrentMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V
 Lcom/android/internal/view/menu/MenuBuilder;->setDefaultShowAsAction(I)Lcom/android/internal/view/menu/MenuBuilder;
@@ -8435,6 +8530,7 @@
 Ldalvik/system/DexPathList$Element;-><init>(Ldalvik/system/DexFile;Ljava/io/File;)V
 Ldalvik/system/DexPathList$Element;-><init>(Ljava/io/File;ZLjava/io/File;Ldalvik/system/DexFile;)V
 Ldalvik/system/DexPathList$Element;->dexFile:Ldalvik/system/DexFile;
+Ldalvik/system/DexPathList$Element;->path:Ljava/io/File;
 Ldalvik/system/DexPathList$NativeLibraryElement;-><init>(Ljava/io/File;)V
 Ldalvik/system/DexPathList$NativeLibraryElement;->path:Ljava/io/File;
 Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)V
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 494ea39..37bf21a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -939,7 +939,8 @@
         }
 
         public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) {
-            final ConnectivityManager cm = ConnectivityManager.from(getSystemContext());
+            final ConnectivityManager cm = ConnectivityManager.from(
+                    getApplication() != null ? getApplication() : getSystemContext());
             final Network network = cm.getBoundNetworkForProcess();
             if (network != null) {
                 Proxy.setHttpProxySystemProperty(cm.getDefaultProxy());
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a591eaf..54cb095 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4922,7 +4922,8 @@
 
             CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY);
             if (!p.ambient && validRemoteInput && replyText != null
-                    && replyText.length > 0 && !TextUtils.isEmpty(replyText[0])) {
+                    && replyText.length > 0 && !TextUtils.isEmpty(replyText[0])
+                    && p.maxRemoteInputHistory > 0) {
                 boolean showSpinner = mN.extras.getBoolean(EXTRA_SHOW_REMOTE_INPUT_SPINNER);
                 big.setViewVisibility(R.id.notification_material_reply_container, View.VISIBLE);
                 big.setViewVisibility(R.id.notification_material_reply_text_1_container,
@@ -4937,13 +4938,15 @@
                         ColorStateList.valueOf(
                                 isColorized() ? getPrimaryTextColor() : resolveContrastColor()));
 
-                if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1])) {
+                if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1])
+                        && p.maxRemoteInputHistory > 1) {
                     big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE);
                     big.setTextViewText(R.id.notification_material_reply_text_2,
                             processTextSpans(replyText[1]));
                     setTextViewColorSecondary(big, R.id.notification_material_reply_text_2);
 
-                    if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2])) {
+                    if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2])
+                            && p.maxRemoteInputHistory > 2) {
                         big.setViewVisibility(
                                 R.id.notification_material_reply_text_3, View.VISIBLE);
                         big.setTextViewText(R.id.notification_material_reply_text_3,
@@ -5106,7 +5109,13 @@
                 return null;
             }
 
-            return applyStandardTemplateWithActions(getBigBaseLayoutResource(), null /* result */);
+            // We only want at most a single remote input history to be shown here, otherwise
+            // the content would become squished.
+            StandardTemplateParams p = mParams.reset().fillTextsFrom(this)
+                    .setMaxRemoteInputHistory(1);
+            return applyStandardTemplateWithActions(getBigBaseLayoutResource(),
+                    p,
+                    null /* result */);
         }
 
         /**
@@ -5975,6 +5984,12 @@
      * object.
      */
     public static abstract class Style {
+
+        /**
+         * The number of items allowed simulatanously in the remote input history.
+         * @hide
+         */
+        static final int MAX_REMOTE_INPUT_HISTORY_LINES = 3;
         private CharSequence mBigContentTitle;
 
         /**
@@ -7376,7 +7391,14 @@
                 return messages;
             }
 
-            static Message getMessageFromBundle(Bundle bundle) {
+            /**
+             * @return The message that is stored in the bundle or null if the message couldn't be
+             * resolved.
+             *
+             * @hide
+             */
+            @Nullable
+            public static Message getMessageFromBundle(Bundle bundle) {
                 try {
                     if (!bundle.containsKey(KEY_TEXT) || !bundle.containsKey(KEY_TIMESTAMP)) {
                         return null;
@@ -7434,6 +7456,11 @@
      * @see Notification#bigContentView
      */
     public static class InboxStyle extends Style {
+
+        /**
+         * The number of lines of remote input history allowed until we start reducing lines.
+         */
+        private static final int NUMBER_OF_HISTORY_ALLOWED_UNTIL_REDUCTION = 1;
         private ArrayList<CharSequence> mTexts = new ArrayList<CharSequence>(5);
 
         public InboxStyle() {
@@ -7533,6 +7560,28 @@
             if (mBuilder.mActions.size() > 0) {
                 maxRows--;
             }
+            CharSequence[] remoteInputHistory = mBuilder.mN.extras.getCharSequenceArray(
+                    EXTRA_REMOTE_INPUT_HISTORY);
+            if (remoteInputHistory != null
+                    && remoteInputHistory.length > NUMBER_OF_HISTORY_ALLOWED_UNTIL_REDUCTION) {
+                // Let's remove some messages to make room for the remote input history.
+                // 1 is always able to fit, but let's remove them if they are 2 or 3
+                int numRemoteInputs = Math.min(remoteInputHistory.length,
+                        MAX_REMOTE_INPUT_HISTORY_LINES);
+                int totalNumRows = mTexts.size() + numRemoteInputs
+                        - NUMBER_OF_HISTORY_ALLOWED_UNTIL_REDUCTION;
+                if (totalNumRows > maxRows) {
+                    int overflow = totalNumRows - maxRows;
+                    if (mTexts.size() > maxRows) {
+                        // Heuristic: if the Texts don't fit anyway, we'll rather drop the last
+                        // few messages, even with the remote input
+                        maxRows -= overflow;
+                    } else  {
+                        // otherwise we drop the first messages
+                        i = overflow;
+                    }
+                }
+            }
             while (i < mTexts.size() && i < maxRows) {
                 CharSequence str = mTexts.get(i);
                 if (!TextUtils.isEmpty(str)) {
@@ -9603,6 +9652,7 @@
         CharSequence title;
         CharSequence text;
         CharSequence headerTextSecondary;
+        int maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
         boolean hideLargeIcon;
         boolean hideReplyIcon;
 
@@ -9612,6 +9662,7 @@
             title = null;
             text = null;
             headerTextSecondary = null;
+            maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
             return this;
         }
 
@@ -9663,5 +9714,15 @@
             this.text = b.processLegacyText(text, ambient);
             return this;
         }
+
+        /**
+         * Set the maximum lines of remote input history lines allowed.
+         * @param maxRemoteInputHistory The number of lines.
+         * @return The builder for method chaining.
+         */
+        public StandardTemplateParams setMaxRemoteInputHistory(int maxRemoteInputHistory) {
+            this.maxRemoteInputHistory = maxRemoteInputHistory;
+            return this;
+        }
     }
 }
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index fc5ea66..30256b4 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -124,7 +124,7 @@
     /**
      * The ApkAssets we are caching and intend to hold strong references to.
      */
-    private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = new LruCache<>(15);
+    private final LruCache<ApkKey, ApkAssets> mLoadedApkAssets = new LruCache<>(3);
 
     /**
      * The ApkAssets that are being referenced in the wild that we can reuse, even if they aren't
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index 45754ae..32fc0dc 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -115,8 +115,9 @@
         }
     }
 
+    // TODO: Temporary for backwards compatibility. Remove.
     /**
-     * TODO: Temporary for backwards compatibility. Remove.
+     * @deprecated Use {@link #addConfig(long, byte[])}
      */
     @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public boolean addConfiguration(long configKey, byte[] config) {
@@ -149,8 +150,9 @@
         }
     }
 
+    // TODO: Temporary for backwards compatibility. Remove.
     /**
-     * TODO: Temporary for backwards compatibility. Remove.
+     * @deprecated Use {@link #removeConfig(long)}
      */
     @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public boolean removeConfiguration(long configKey) {
@@ -216,8 +218,9 @@
         }
     }
 
+    // TODO: Temporary for backwards compatibility. Remove.
     /**
-     * TODO: Temporary for backwards compatibility. Remove.
+     * @deprecated Use {@link #setBroadcastSubscriber(PendingIntent, long, long)}
      */
     @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public boolean setBroadcastSubscriber(
@@ -268,8 +271,9 @@
         }
     }
 
+    // TODO: Temporary for backwards compatibility. Remove.
     /**
-     * TODO: Temporary for backwards compatibility. Remove.
+     * @deprecated Use {@link #setFetchReportsOperation(PendingIntent, long)}
      */
     @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public boolean setDataFetchOperation(long configKey, PendingIntent pendingIntent) {
@@ -304,8 +308,9 @@
         }
     }
 
+    // TODO: Temporary for backwards compatibility. Remove.
     /**
-     * TODO: Temporary for backwards compatibility. Remove.
+     * @deprecated Use {@link #getReports(long)}
      */
     @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public @Nullable byte[] getData(long configKey) {
@@ -339,12 +344,9 @@
         }
     }
 
+    // TODO: Temporary for backwards compatibility. Remove.
     /**
-     * Clients can request metadata for statsd. Will contain stats across all configurations but not
-     * the actual metrics themselves (metrics must be collected via {@link #getReports(long)}.
-     * This getter is not destructive and will not reset any metrics/counters.
-     *
-     * @return Serialized StatsdStatsReport proto. Returns null on failure (eg, if statsd crashed).
+     * @deprecated Use {@link #getStatsMetadata()}
      */
     @RequiresPermission(allOf = { DUMP, PACKAGE_USAGE_STATS })
     public @Nullable byte[] getMetadata() {
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index c03340e..5662aea 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -28,6 +28,8 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.hardware.display.DisplayManagerGlobal;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
@@ -47,6 +49,7 @@
 import android.view.accessibility.AccessibilityWindowInfo;
 import android.view.accessibility.IAccessibilityInteractionConnection;
 
+import com.android.internal.util.function.pooled.PooledLambda;
 import libcore.io.IoUtils;
 
 import java.io.IOException;
@@ -118,10 +121,14 @@
 
     private final ArrayList<AccessibilityEvent> mEventQueue = new ArrayList<AccessibilityEvent>();
 
-    private final IAccessibilityServiceClient mClient;
+    private final Handler mLocalCallbackHandler;
 
     private final IUiAutomationConnection mUiAutomationConnection;
 
+    private HandlerThread mRemoteCallbackThread;
+
+    private IAccessibilityServiceClient mClient;
+
     private int mConnectionId = CONNECTION_ID_UNDEFINED;
 
     private OnAccessibilityEventListener mOnAccessibilityEventListener;
@@ -190,8 +197,8 @@
         if (connection == null) {
             throw new IllegalArgumentException("Connection cannot be null!");
         }
+        mLocalCallbackHandler = new Handler(looper);
         mUiAutomationConnection = connection;
-        mClient = new IAccessibilityServiceClientImpl(looper);
     }
 
     /**
@@ -217,6 +224,9 @@
                 return;
             }
             mIsConnecting = true;
+            mRemoteCallbackThread = new HandlerThread("UiAutomation");
+            mRemoteCallbackThread.start();
+            mClient = new IAccessibilityServiceClientImpl(mRemoteCallbackThread.getLooper());
         }
 
         try {
@@ -281,6 +291,9 @@
             mUiAutomationConnection.disconnect();
         } catch (RemoteException re) {
             throw new RuntimeException("Error while disconnecting UiAutomation", re);
+        } finally {
+            mRemoteCallbackThread.quit();
+            mRemoteCallbackThread = null;
         }
     }
 
@@ -311,6 +324,7 @@
 
     /**
      * Sets a callback for observing the stream of {@link AccessibilityEvent}s.
+     * The callbacks are delivered on the main application thread.
      *
      * @param listener The callback.
      */
@@ -1139,17 +1153,21 @@
 
                 @Override
                 public void onAccessibilityEvent(AccessibilityEvent event) {
+                    final OnAccessibilityEventListener listener;
                     synchronized (mLock) {
                         mLastEventTimeMillis = event.getEventTime();
                         if (mWaitingForEventDelivery) {
                             mEventQueue.add(AccessibilityEvent.obtain(event));
                         }
                         mLock.notifyAll();
+                        listener = mOnAccessibilityEventListener;
                     }
-                    // Calling out only without a lock held.
-                    final OnAccessibilityEventListener listener = mOnAccessibilityEventListener;
                     if (listener != null) {
-                        listener.onAccessibilityEvent(AccessibilityEvent.obtain(event));
+                        // Calling out only without a lock held.
+                        mLocalCallbackHandler.post(PooledLambda.obtainRunnable(
+                                OnAccessibilityEventListener::onAccessibilityEvent,
+                                listener, AccessibilityEvent.obtain(event))
+                                .recycleOnUse());
                     }
                 }
 
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index f682ec1..ad862fc 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -245,7 +245,8 @@
         ContentResolver resolver = mContext.getContentResolver();
         try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
             if (provider == null) {
-                throw new IllegalArgumentException("Unknown URI " + uri);
+                Log.w(TAG, String.format("Unknown URI: %s", uri));
+                return null;
             }
             Bundle extras = new Bundle();
             extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
@@ -306,7 +307,8 @@
                 .authority(authority).build();
         try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
             if (provider == null) {
-                throw new IllegalArgumentException("Unknown URI " + uri);
+                Log.w(TAG, String.format("Unknown URI: %s", uri));
+                return null;
             }
             Bundle extras = new Bundle();
             extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
@@ -383,7 +385,8 @@
                 .authority(authority).build();
         try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) {
             if (provider == null) {
-                throw new IllegalArgumentException("Unknown URI " + uri);
+                Log.w(TAG, String.format("Unknown URI: %s", uri));
+                return null;
             }
             Bundle extras = new Bundle();
             extras.putParcelable(SliceProvider.EXTRA_INTENT, intent);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 34ac9ae..c3548e5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5574,8 +5574,7 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(anyOf = {Manifest.permission.SUSPEND_APPS,
-            Manifest.permission.MANAGE_USERS})
+    @RequiresPermission(Manifest.permission.SUSPEND_APPS)
     public String[] setPackagesSuspended(String[] packageNames, boolean suspended,
             @Nullable PersistableBundle appExtras, @Nullable PersistableBundle launcherExtras,
             String dialogMessage) {
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 2306e5f..16c1f6d 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -21,18 +21,15 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.Paint.Align;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Typeface;
-import android.graphics.Paint.Align;
-import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
 import android.inputmethodservice.Keyboard.Key;
 import android.media.AudioManager;
 import android.os.Handler;
 import android.os.Message;
-import android.os.UserHandle;
-import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.GestureDetector;
@@ -662,11 +659,13 @@
             invalidateAllKeys();
             mKeyboardChanged = false;
         }
-        final Canvas canvas = mCanvas;
-        canvas.clipRect(mDirtyRect, Op.REPLACE);
 
         if (mKeyboard == null) return;
 
+        mCanvas.save();
+        final Canvas canvas = mCanvas;
+        canvas.clipRect(mDirtyRect);
+
         final Paint paint = mPaint;
         final Drawable keyBackground = mKeyBackground;
         final Rect clipRegion = mClipRegion;
@@ -758,7 +757,7 @@
             paint.setColor(0xFF00FF00);
             canvas.drawCircle((mStartX + mLastX) / 2, (mStartY + mLastY) / 2, 2, paint);
         }
-
+        mCanvas.restore();
         mDrawPending = false;
         mDirtyRect.setEmpty();
     }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c3b8f39..c5cb1f5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -238,6 +238,14 @@
     public static final String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
 
     /**
+     * Key for passing a {@link android.net.captiveportal.CaptivePortalProbeSpec} to the captive
+     * portal login activity.
+     * {@hide}
+     */
+    public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC =
+            "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
+
+    /**
      * Key for passing a user agent string to the captive portal login activity.
      * {@hide}
      */
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 15a0ee5..d75d439 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -85,6 +85,21 @@
     private static final long HANDLE_MAGIC = 0xcafed00dL;
     private static final int HANDLE_MAGIC_SIZE = 32;
 
+    // A boolean to control how getAllByName()/getByName() behaves in the face
+    // of Private DNS.
+    //
+    // When true, these calls will request that DNS resolution bypass any
+    // Private DNS that might otherwise apply. Use of this feature is restricted
+    // and permission checks are made by netd (attempts to bypass Private DNS
+    // without appropriate permission are silently turned into vanilla DNS
+    // requests). This only affects DNS queries made using this network object.
+    //
+    // It it not parceled to receivers because (a) it can be set or cleared at
+    // anytime and (b) receivers should be explicit about attempts to bypass
+    // Private DNS so that the intent of the code is easily determined and
+    // code search audits are possible.
+    private boolean mPrivateDnsBypass = false;
+
     /**
      * @hide
      */
@@ -108,7 +123,7 @@
      * @throws UnknownHostException if the address lookup fails.
      */
     public InetAddress[] getAllByName(String host) throws UnknownHostException {
-        return InetAddress.getAllByNameOnNet(host, netId);
+        return InetAddress.getAllByNameOnNet(host, getNetIdForResolv());
     }
 
     /**
@@ -122,7 +137,32 @@
      *             if the address lookup fails.
      */
     public InetAddress getByName(String host) throws UnknownHostException {
-        return InetAddress.getByNameOnNet(host, netId);
+        return InetAddress.getByNameOnNet(host, getNetIdForResolv());
+    }
+
+    /**
+     * Specify whether or not Private DNS should be bypassed when attempting
+     * to use {@link getAllByName()}/{@link getByName()} methods on the given
+     * instance for hostname resolution.
+     *
+     * @hide
+     */
+    public void setPrivateDnsBypass(boolean bypass) {
+        mPrivateDnsBypass = bypass;
+    }
+
+    /**
+     * Returns a netid marked with the Private DNS bypass flag.
+     *
+     * This flag must be kept in sync with the NETID_USE_LOCAL_NAMESERVERS flag
+     * in system/netd/include/NetdClient.h.
+     *
+     * @hide
+     */
+    public int getNetIdForResolv() {
+        return mPrivateDnsBypass
+                ? (int) (0x80000000L | (long) netId)  // Non-portable DNS resolution flag.
+                : netId;
     }
 
     /**
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a808c64..e3a1107 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -63,16 +63,7 @@
 
     public NetworkCapabilities(NetworkCapabilities nc) {
         if (nc != null) {
-            mNetworkCapabilities = nc.mNetworkCapabilities;
-            mTransportTypes = nc.mTransportTypes;
-            mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
-            mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
-            mNetworkSpecifier = nc.mNetworkSpecifier;
-            mSignalStrength = nc.mSignalStrength;
-            mUids = nc.mUids;
-            mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
-            mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
-            mSSID = nc.mSSID;
+            set(nc);
         }
     }
 
@@ -92,6 +83,23 @@
     }
 
     /**
+     * Set all contents of this object to the contents of a NetworkCapabilities.
+     * @hide
+     */
+    public void set(NetworkCapabilities nc) {
+        mNetworkCapabilities = nc.mNetworkCapabilities;
+        mTransportTypes = nc.mTransportTypes;
+        mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
+        mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
+        mNetworkSpecifier = nc.mNetworkSpecifier;
+        mSignalStrength = nc.mSignalStrength;
+        setUids(nc.mUids); // Will make the defensive copy
+        mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
+        mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
+        mSSID = nc.mSSID;
+    }
+
+    /**
      * Represents the network's capabilities.  If any are specified they will be satisfied
      * by any Network that matches all of them.
      */
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 227a4cb..16c2342 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -198,8 +198,7 @@
          * @hide
          */
         public Builder setCapabilities(NetworkCapabilities nc) {
-            mNetworkCapabilities.clearAll();
-            mNetworkCapabilities.combineCapabilities(nc);
+            mNetworkCapabilities.set(nc);
             return this;
         }
 
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index f0dd262..edf9bc1 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -1100,6 +1100,8 @@
     public interface NonMonotonicObserver<C> {
         public void foundNonMonotonic(
                 NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie);
+        public void foundNonMonotonic(
+                NetworkStats stats, int statsIndex, C cookie);
     }
 
     /**
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index 66cdc99..ddf63ca 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -84,6 +84,10 @@
      * @return true if the transaction was successful.
      */
     public boolean requestTime(String host, int timeout, Network network) {
+        // This flag only affects DNS resolution and not other socket semantics,
+        // therefore it's safe to set unilaterally rather than take more
+        // defensive measures like making a copy.
+        network.setPrivateDnsBypass(true);
         InetAddress address = null;
         try {
             address = network.getByName(host);
diff --git a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java
new file mode 100644
index 0000000..1634694
--- /dev/null
+++ b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.captiveportal;
+
+import android.annotation.Nullable;
+
+/**
+ * Result of calling isCaptivePortal().
+ * @hide
+ */
+public final class CaptivePortalProbeResult {
+    public static final int SUCCESS_CODE = 204;
+    public static final int FAILED_CODE = 599;
+    public static final int PORTAL_CODE = 302;
+
+    public static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE);
+    public static final CaptivePortalProbeResult SUCCESS =
+            new CaptivePortalProbeResult(SUCCESS_CODE);
+
+    private final int mHttpResponseCode;  // HTTP response code returned from Internet probe.
+    public final String redirectUrl;      // Redirect destination returned from Internet probe.
+    public final String detectUrl;        // URL where a 204 response code indicates
+                                          // captive portal has been appeased.
+    @Nullable
+    public final CaptivePortalProbeSpec probeSpec;
+
+    public CaptivePortalProbeResult(int httpResponseCode) {
+        this(httpResponseCode, null, null);
+    }
+
+    public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl, String detectUrl) {
+        this(httpResponseCode, redirectUrl, detectUrl, null);
+    }
+
+    public CaptivePortalProbeResult(int httpResponseCode, String redirectUrl, String detectUrl,
+            CaptivePortalProbeSpec probeSpec) {
+        mHttpResponseCode = httpResponseCode;
+        this.redirectUrl = redirectUrl;
+        this.detectUrl = detectUrl;
+        this.probeSpec = probeSpec;
+    }
+
+    public boolean isSuccessful() {
+        return mHttpResponseCode == SUCCESS_CODE;
+    }
+
+    public boolean isPortal() {
+        return !isSuccessful() && (mHttpResponseCode >= 200) && (mHttpResponseCode <= 399);
+    }
+
+    public boolean isFailed() {
+        return !isSuccessful() && !isPortal();
+    }
+}
diff --git a/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java b/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java
new file mode 100644
index 0000000..57a926a
--- /dev/null
+++ b/core/java/android/net/captiveportal/CaptivePortalProbeSpec.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.captiveportal;
+
+import static android.net.captiveportal.CaptivePortalProbeResult.PORTAL_CODE;
+import static android.net.captiveportal.CaptivePortalProbeResult.SUCCESS_CODE;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/** @hide */
+public abstract class CaptivePortalProbeSpec {
+    public static final String HTTP_LOCATION_HEADER_NAME = "Location";
+
+    private static final String TAG = CaptivePortalProbeSpec.class.getSimpleName();
+    private static final String REGEX_SEPARATOR = "@@/@@";
+    private static final String SPEC_SEPARATOR = "@@,@@";
+
+    private final String mEncodedSpec;
+    private final URL mUrl;
+
+    CaptivePortalProbeSpec(String encodedSpec, URL url) {
+        mEncodedSpec = encodedSpec;
+        mUrl = url;
+    }
+
+    /**
+     * Parse a {@link CaptivePortalProbeSpec} from a {@link String}.
+     *
+     * <p>The valid format is a URL followed by two regular expressions, each separated by "@@/@@".
+     * @throws MalformedURLException The URL has invalid format for {@link URL#URL(String)}.
+     * @throws ParseException The string is empty, does not match the above format, or a regular
+     * expression is invalid for {@link Pattern#compile(String)}.
+     */
+    @NonNull
+    public static CaptivePortalProbeSpec parseSpec(String spec) throws ParseException,
+            MalformedURLException {
+        if (TextUtils.isEmpty(spec)) {
+            throw new ParseException("Empty probe spec", 0 /* errorOffset */);
+        }
+
+        String[] splits = TextUtils.split(spec, REGEX_SEPARATOR);
+        if (splits.length != 3) {
+            throw new ParseException("Probe spec does not have 3 parts", 0 /* errorOffset */);
+        }
+
+        final int statusRegexPos = splits[0].length() + REGEX_SEPARATOR.length();
+        final int locationRegexPos = statusRegexPos + splits[1].length() + REGEX_SEPARATOR.length();
+        final Pattern statusRegex = parsePatternIfNonEmpty(splits[1], statusRegexPos);
+        final Pattern locationRegex = parsePatternIfNonEmpty(splits[2], locationRegexPos);
+
+        return new RegexMatchProbeSpec(spec, new URL(splits[0]), statusRegex, locationRegex);
+    }
+
+    @Nullable
+    private static Pattern parsePatternIfNonEmpty(String pattern, int pos) throws ParseException {
+        if (TextUtils.isEmpty(pattern)) {
+            return null;
+        }
+        try {
+            return Pattern.compile(pattern);
+        } catch (PatternSyntaxException e) {
+            throw new ParseException(
+                    String.format("Invalid status pattern [%s]: %s", pattern, e),
+                    pos /* errorOffset */);
+        }
+    }
+
+    /**
+     * Parse a {@link CaptivePortalProbeSpec} from a {@link String}, or return a fallback spec
+     * based on the status code of the provided URL if the spec cannot be parsed.
+     */
+    @Nullable
+    public static CaptivePortalProbeSpec parseSpecOrNull(@Nullable String spec) {
+        if (spec != null) {
+            try {
+                return parseSpec(spec);
+            } catch (ParseException | MalformedURLException e) {
+                Log.e(TAG, "Invalid probe spec: " + spec, e);
+                // Fall through
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Parse a config String to build an array of {@link CaptivePortalProbeSpec}.
+     *
+     * <p>Each spec is separated by @@,@@ and follows the format for {@link #parseSpec(String)}.
+     * <p>This method does not throw but ignores any entry that could not be parsed.
+     */
+    public static CaptivePortalProbeSpec[] parseCaptivePortalProbeSpecs(String settingsVal) {
+        List<CaptivePortalProbeSpec> specs = new ArrayList<>();
+        if (settingsVal != null) {
+            for (String spec : TextUtils.split(settingsVal, SPEC_SEPARATOR)) {
+                try {
+                    specs.add(parseSpec(spec));
+                } catch (ParseException | MalformedURLException e) {
+                    Log.e(TAG, "Invalid probe spec: " + spec, e);
+                }
+            }
+        }
+
+        if (specs.isEmpty()) {
+            Log.e(TAG, String.format("could not create any validation spec from %s", settingsVal));
+        }
+        return specs.toArray(new CaptivePortalProbeSpec[specs.size()]);
+    }
+
+    /**
+     * Get the probe result from HTTP status and location header.
+     */
+    public abstract CaptivePortalProbeResult getResult(int status, @Nullable String locationHeader);
+
+    public String getEncodedSpec() {
+        return mEncodedSpec;
+    }
+
+    public URL getUrl() {
+        return mUrl;
+    }
+
+    /**
+     * Implementation of {@link CaptivePortalProbeSpec} that is based on configurable regular
+     * expressions for the HTTP status code and location header (if any). Matches indicate that
+     * the page is not a portal.
+     * This probe cannot fail: it always returns SUCCESS_CODE or PORTAL_CODE
+     */
+    private static class RegexMatchProbeSpec extends CaptivePortalProbeSpec {
+        @Nullable
+        final Pattern mStatusRegex;
+        @Nullable
+        final Pattern mLocationHeaderRegex;
+
+        RegexMatchProbeSpec(
+                String spec, URL url, Pattern statusRegex, Pattern locationHeaderRegex) {
+            super(spec, url);
+            mStatusRegex = statusRegex;
+            mLocationHeaderRegex = locationHeaderRegex;
+        }
+
+        @Override
+        public CaptivePortalProbeResult getResult(int status, String locationHeader) {
+            final boolean statusMatch = safeMatch(String.valueOf(status), mStatusRegex);
+            final boolean locationMatch = safeMatch(locationHeader, mLocationHeaderRegex);
+            final int returnCode = statusMatch && locationMatch ? SUCCESS_CODE : PORTAL_CODE;
+            return new CaptivePortalProbeResult(
+                    returnCode, locationHeader, getUrl().toString(), this);
+        }
+    }
+
+    private static boolean safeMatch(@Nullable String value, @Nullable Pattern pattern) {
+        // No value is a match ("no location header" passes the location rule for non-redirects)
+        return pattern == null || TextUtils.isEmpty(value) || pattern.matcher(value).matches();
+    }
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 619ec23..221abed 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -245,8 +245,10 @@
      * New in version 31:
      *   - New cellular network types.
      *   - Deferred job metrics.
+     * New in version 32:
+     *   - Ambient display properly output in data dump.
      */
-    static final int CHECKIN_VERSION = 31;
+    static final int CHECKIN_VERSION = 32;
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 5e23932..3017f25 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -45,6 +45,7 @@
             in String[] disallowedPackages);
     UserInfo createRestrictedProfile(String name, int parentUserHandle);
     void setUserEnabled(int userHandle);
+    void setUserAdmin(int userId);
     void evictCredentialEncryptionKey(int userHandle);
     boolean removeUser(int userHandle);
     boolean removeUserEvenWhenDisallowed(int userHandle);
diff --git a/core/java/android/os/RemoteCallback.java b/core/java/android/os/RemoteCallback.java
index 7dbcb95..5914739 100644
--- a/core/java/android/os/RemoteCallback.java
+++ b/core/java/android/os/RemoteCallback.java
@@ -19,11 +19,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 
 /**
  * @hide
  */
 @SystemApi
+@TestApi
 public final class RemoteCallback implements Parcelable {
 
     public interface OnResultListener {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 11afd21..b591851 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2087,12 +2087,33 @@
      * Also ephemeral users can be disabled to indicate that their removal is in progress and they
      * shouldn't be re-entered. Therefore ephemeral users should not be re-enabled once disabled.
      *
-     * @param userHandle the id of the profile to enable
+     * @param userId the id of the profile to enable
      * @hide
      */
-    public void setUserEnabled(@UserIdInt int userHandle) {
+    public void setUserEnabled(@UserIdInt int userId) {
         try {
-            mService.setUserEnabled(userHandle);
+            mService.setUserEnabled(userId);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Assigns admin privileges to the user, if such a user exists.
+     *
+     * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} and
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permissions.
+     *
+     * @param userHandle the id of the user to become admin
+     * @hide
+     */
+    @RequiresPermission(allOf = {
+            Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+            Manifest.permission.MANAGE_USERS
+    })
+    public void setUserAdmin(@UserIdInt int userHandle) {
+        try {
+            mService.setUserAdmin(userHandle);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 4d238c0..ff5502f 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.Nullable;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.hardware.vibrator.V1_0.EffectStrength;
 import android.hardware.vibrator.V1_2.Effect;
@@ -275,7 +276,12 @@
             if (uris[i] == null) {
                 continue;
             }
-            if (Uri.parse(uris[i]).equals(uri)) {
+            ContentResolver cr = context.getContentResolver();
+            Uri mappedUri = cr.uncanonicalize(Uri.parse(uris[i]));
+            if (mappedUri == null) {
+                continue;
+            }
+            if (mappedUri.equals(uri)) {
                 return get(RINGTONES[i]);
             }
         }
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 576ea52..8d4c3c3 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -407,8 +407,12 @@
      * {@link #TYPE_EMULATED} or {@link #TYPE_PUBLIC}.
      */
     public @Nullable Intent buildBrowseIntent() {
+        return buildBrowseIntentForUser(UserHandle.myUserId());
+    }
+
+    public @Nullable Intent buildBrowseIntentForUser(int userId) {
         final Uri uri;
-        if (type == VolumeInfo.TYPE_PUBLIC && mountUserId == UserHandle.myUserId()) {
+        if (type == VolumeInfo.TYPE_PUBLIC && mountUserId == userId) {
             uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY, fsUuid);
         } else if (type == VolumeInfo.TYPE_EMULATED && isPrimary()) {
             uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7bf3af1..0510418 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -23,6 +23,7 @@
 import static android.provider.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR;
 import static android.provider.SettingsValidators.LOCALE_VALIDATOR;
 import static android.provider.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
+import static android.provider.SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR;
 import static android.provider.SettingsValidators.PACKAGE_NAME_VALIDATOR;
 import static android.provider.SettingsValidators.URI_VALIDATOR;
 
@@ -3114,10 +3115,10 @@
 
         private static final Validator FONT_SCALE_VALIDATOR = new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 try {
                     return Float.parseFloat(value) >= 0;
-                } catch (NumberFormatException e) {
+                } catch (NumberFormatException | NullPointerException e) {
                     return false;
                 }
             }
@@ -3655,11 +3656,11 @@
         /** @hide */
         public static final Validator DATE_FORMAT_VALIDATOR = new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 try {
                     new SimpleDateFormat(value);
                     return true;
-                } catch (IllegalArgumentException e) {
+                } catch (IllegalArgumentException | NullPointerException e) {
                     return false;
                 }
             }
@@ -4066,7 +4067,7 @@
         /** @hide */
         public static final Validator EGG_MODE_VALIDATOR = new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 try {
                     return Long.parseLong(value) >= 0;
                 } catch (NumberFormatException e) {
@@ -5452,7 +5453,8 @@
         @TestApi
         public static final String AUTOFILL_SERVICE = "autofill_service";
 
-        private static final Validator AUTOFILL_SERVICE_VALIDATOR = COMPONENT_NAME_VALIDATOR;
+        private static final Validator AUTOFILL_SERVICE_VALIDATOR =
+                NULLABLE_COMPONENT_NAME_VALIDATOR;
 
         /**
          * Boolean indicating if Autofill supports field classification.
@@ -5950,7 +5952,7 @@
                 "accessibility_shortcut_target_service";
 
         private static final Validator ACCESSIBILITY_SHORTCUT_TARGET_SERVICE_VALIDATOR =
-                COMPONENT_NAME_VALIDATOR;
+                NULLABLE_COMPONENT_NAME_VALIDATOR;
 
         /**
          * Setting specifying the accessibility service or feature to be toggled via the
@@ -5965,7 +5967,7 @@
         private static final Validator ACCESSIBILITY_BUTTON_TARGET_COMPONENT_VALIDATOR =
                 new Validator() {
                     @Override
-                    public boolean validate(String value) {
+                    public boolean validate(@Nullable String value) {
                         // technically either ComponentName or class name, but there's proper value
                         // validation at callsites, so allow any non-null string
                         return value != null;
@@ -6482,7 +6484,7 @@
 
         private static final Validator TTS_DEFAULT_LOCALE_VALIDATOR = new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 if (value == null || value.length() == 0) {
                     return false;
                 }
@@ -7112,6 +7114,35 @@
         public static final String UI_NIGHT_MODE = "ui_night_mode";
 
         /**
+         * The current device UI theme mode effect SystemUI and Launcher.<br/>
+         * <b>Values:</b><br/>
+         * 0 - The mode that theme will controlled by wallpaper color.<br/>
+         * 1 - The mode that will always light theme.<br/>
+         * 2 - The mode that will always dark theme.<br/>
+         *
+         * @hide
+         */
+        public static final String THEME_MODE = "theme_mode";
+
+        /**
+         * THEME_MODE value for wallpaper mode.
+         * @hide
+         */
+        public static final int THEME_MODE_WALLPAPER = 0;
+
+        /**
+         * THEME_MODE value for light theme mode.
+         * @hide
+         */
+        public static final int THEME_MODE_LIGHT = 1;
+
+        /**
+         * THEME_MODE value for dark theme mode.
+         * @hide
+         */
+        public static final int THEME_MODE_DARK = 2;
+
+        /**
          * Whether screensavers are enabled.
          * @hide
          */
@@ -7720,7 +7751,7 @@
 
         private static final Validator QS_TILES_VALIDATOR = new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 if (value == null) {
                     return false;
                 }
@@ -7779,7 +7810,7 @@
 
         private static final Validator QS_AUTO_ADDED_TILES_VALIDATOR = new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 if (value == null) {
                     return false;
                 }
@@ -8653,7 +8684,7 @@
 
         private static final Validator STAY_ON_WHILE_PLUGGED_IN_VALIDATOR = new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 try {
                     int val = Integer.parseInt(value);
                     return (val == 0)
@@ -9687,7 +9718,7 @@
 
         private static final Validator USE_OPEN_WIFI_PACKAGE_VALIDATOR = new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 return (value == null) || PACKAGE_NAME_VALIDATOR.validate(value);
             }
         };
@@ -10251,6 +10282,15 @@
                 "captive_portal_other_fallback_urls";
 
         /**
+         * A list of captive portal detection specifications used in addition to the fallback URLs.
+         * Each spec has the format url@@/@@statusCodeRegex@@/@@contentRegex. Specs are separated
+         * by "@@,@@".
+         * @hide
+         */
+        public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS =
+                "captive_portal_fallback_probe_specs";
+
+        /**
          * Whether to use HTTPS for network validation. This is enabled by default and the setting
          * needs to be set to 0 to disable it. This setting is a misnomer because captive portals
          * don't actually use HTTPS, but it's consistent with the other settings.
@@ -11382,7 +11422,7 @@
         private static final Validator ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS_VALIDATOR =
                 new Validator() {
             @Override
-            public boolean validate(String value) {
+            public boolean validate(@Nullable String value) {
                 try {
                     String[] surroundFormats = TextUtils.split(value, ",");
                     for (String format : surroundFormats) {
@@ -11564,6 +11604,13 @@
         /** @hide */ public static final int EMULATE_DISPLAY_CUTOUT_ON = 1;
 
         /**
+         * A colon separated list of keys for Settings Slices.
+         *
+         * @hide
+         */
+        public static final String BLOCKED_SLICES = "blocked_slices";
+
+        /**
          * Defines global zen mode.  ZEN_MODE_OFF, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
          * or ZEN_MODE_NO_INTERRUPTIONS.
          *
diff --git a/core/java/android/provider/SettingsValidators.java b/core/java/android/provider/SettingsValidators.java
index c878bba..25e77867 100644
--- a/core/java/android/provider/SettingsValidators.java
+++ b/core/java/android/provider/SettingsValidators.java
@@ -16,6 +16,7 @@
 
 package android.provider;
 
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.net.Uri;
 
@@ -36,14 +37,14 @@
 
     public static final Validator ANY_STRING_VALIDATOR = new Validator() {
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             return true;
         }
     };
 
     public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() {
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             try {
                 return Integer.parseInt(value) >= 0;
             } catch (NumberFormatException e) {
@@ -54,7 +55,7 @@
 
     public static final Validator ANY_INTEGER_VALIDATOR = new Validator() {
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             try {
                 Integer.parseInt(value);
                 return true;
@@ -66,7 +67,7 @@
 
     public static final Validator URI_VALIDATOR = new Validator() {
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             try {
                 Uri.decode(value);
                 return true;
@@ -76,16 +77,31 @@
         }
     };
 
+    /**
+     * Does not allow a setting to have a null {@link ComponentName}. Use {@link
+     * SettingsValidators#NULLABLE_COMPONENT_NAME_VALIDATOR} instead if a setting can have a
+     * nullable {@link ComponentName}.
+     */
     public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() {
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             return value != null && ComponentName.unflattenFromString(value) != null;
         }
     };
 
+    /**
+     * Allows a setting to have a null {@link ComponentName}.
+     */
+    public static final Validator NULLABLE_COMPONENT_NAME_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(@Nullable String value) {
+            return value == null || COMPONENT_NAME_VALIDATOR.validate(value);
+        }
+    };
+
     public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() {
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             return value != null && isStringPackageName(value);
         }
 
@@ -122,7 +138,7 @@
         private static final int MAX_IPV6_LENGTH = 45;
 
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             if (value == null) {
                 return false;
             }
@@ -132,7 +148,7 @@
 
     public static final Validator LOCALE_VALIDATOR = new Validator() {
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             if (value == null) {
                 return false;
             }
@@ -147,7 +163,11 @@
     };
 
     public interface Validator {
-        boolean validate(String value);
+        /**
+         * Returns whether the input value is valid. Subclasses should handle the case where the
+         * input value is {@code null}.
+         */
+        boolean validate(@Nullable String value);
     }
 
     public static final class DiscreteValueValidator implements Validator {
@@ -158,7 +178,7 @@
         }
 
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             return ArrayUtils.contains(mValues, value);
         }
     }
@@ -173,7 +193,7 @@
         }
 
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             try {
                 final int intValue = Integer.parseInt(value);
                 return intValue >= mMin && intValue <= mMax;
@@ -193,11 +213,11 @@
         }
 
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             try {
                 final float floatValue = Float.parseFloat(value);
                 return floatValue >= mMin && floatValue <= mMax;
-            } catch (NumberFormatException e) {
+            } catch (NumberFormatException | NullPointerException e) {
                 return false;
             }
         }
@@ -211,7 +231,7 @@
         }
 
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             if (value == null) {
                 return false;
             }
@@ -233,7 +253,7 @@
         }
 
         @Override
-        public boolean validate(String value) {
+        public boolean validate(@Nullable String value) {
             if (value == null) {
                 return false;
             }
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
index 537065d..1d5c6f1 100644
--- a/core/java/android/webkit/SslErrorHandler.java
+++ b/core/java/android/webkit/SslErrorHandler.java
@@ -36,6 +36,10 @@
 
     /**
      * Proceed with the SSL certificate.
+     * <p>
+     * It is not recommended to proceed past SSL errors and this method should
+     * generally not be used; see {@link WebViewClient#onReceivedSslError} for
+     * more information.
      */
     public void proceed() {}
 
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4aa1c4a..95fe963 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -113,6 +113,20 @@
      * the new WebView as an argument. If the host application chooses not to
      * honor the request, it should return {@code false} from this method. The default
      * implementation of this method does nothing and hence returns {@code false}.
+     * <p>
+     * Applications should typically not allow windows to be created when the
+     * {@code isUserGesture} flag is false, as this may be an unwanted popup.
+     * <p>
+     * Applications should be careful how they display the new window: don't simply
+     * overlay it over the existing WebView as this may mislead the user about which
+     * site they are viewing. If your application displays the URL of the main page,
+     * make sure to also display the URL of the new window in a similar fashion. If
+     * your application does not display URLs, consider disallowing the creation of
+     * new windows entirely.
+     * <p class="note"><b>Note:</b> There is no trustworthy way to tell which page
+     * requested the new window: the request might originate from a third-party iframe
+     * inside the WebView.
+     *
      * @param view The WebView from which the request for a new window
      *             originated.
      * @param isDialog {@code true} if the new window should be a dialog, rather than
@@ -149,6 +163,11 @@
      * from the view system if necessary. At this point, WebCore has stopped
      * any loading in this window and has removed any cross-scripting ability
      * in javascript.
+     * <p>
+     * As with {@link #onCreateWindow}, the application should ensure that any
+     * URL or security indicator displayed is updated so that the user can tell
+     * that the page they were interacting with has been closed.
+     *
      * @param window The WebView that needs to be closed.
      */
     public void onCloseWindow(WebView window) {}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 10748ac..d7f1d6e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1019,11 +1019,21 @@
      * If {@code null}, defaults to 'text/html'.
      * <p>
      * The 'data' scheme URL formed by this method uses the default US-ASCII
-     * charset. If you need need to set a different charset, you should form a
+     * charset. If you need to set a different charset, you should form a
      * 'data' scheme URL which explicitly specifies a charset parameter in the
      * mediatype portion of the URL and call {@link #loadUrl(String)} instead.
      * Note that the charset obtained from the mediatype portion of a data URL
      * always overrides that specified in the HTML or XML document itself.
+     * <p>
+     * Content loaded using this method will have a {@code window.origin} value
+     * of {@code "null"}. This must not be considered to be a trusted origin
+     * by the application or by any JavaScript code running inside the WebView
+     * (for example, event sources in DOM event handlers or web messages),
+     * because malicious content can also create frames with a null origin. If
+     * you need to identify the main frame's origin in a trustworthy way, you
+     * should use {@link #loadDataWithBaseURL(String,String,String,String,String)
+     * loadDataWithBaseURL()} with a valid HTTP or HTTPS base URL to set the
+     * origin.
      *
      * @param data a String of data in the given encoding
      * @param mimeType the MIME type of the data, e.g. 'text/html'.
@@ -1057,6 +1067,15 @@
      * <p>
      * Note that the baseUrl is sent in the 'Referer' HTTP header when
      * requesting subresources (images, etc.) of the page loaded using this method.
+     * <p>
+     * If a valid HTTP or HTTPS base URL is not specified in {@code baseUrl}, then
+     * content loaded using this method will have a {@code window.origin} value
+     * of {@code "null"}. This must not be considered to be a trusted origin
+     * by the application or by any JavaScript code running inside the WebView
+     * (for example, event sources in DOM event handlers or web messages),
+     * because malicious content can also create frames with a null origin. If
+     * you need to identify the main frame's origin in a trustworthy way, you
+     * should use a valid HTTP or HTTPS base URL to set the origin.
      *
      * @param baseUrl the URL to use as the page's base URL. If {@code null} defaults to
      *                'about:blank'.
@@ -2056,6 +2075,13 @@
      * <p>
      * A target origin can be set as a wildcard ("*"). However this is not recommended.
      * See the page above for security issues.
+     * <p>
+     * Content loaded via {@link #loadData(String,String,String)} will not have a
+     * valid origin, and thus cannot be sent messages securely. If you need to send
+     * messages using this function, you should use
+     * {@link #loadDataWithBaseURL(String,String,String,String,String)} with a valid
+     * HTTP or HTTPS {@code baseUrl} to define a valid origin that can be used for
+     * messaging.
      *
      * @param message the WebMessage
      * @param targetOrigin the target origin.
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 6df1655..f686b66 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -368,6 +368,15 @@
      * handler.proceed(). Note that the decision may be retained for use in
      * response to future SSL errors. The default behavior is to cancel the
      * load.
+     * <p>
+     * Applications are advised not to prompt the user about SSL errors, as
+     * the user is unlikely to be able to make an informed security decision
+     * and WebView does not provide any UI for showing the details of the
+     * error in a meaningful way.
+     * <p>
+     * Application overrides of this method may display custom error pages or
+     * silently log issues, but it is strongly recommended to always call
+     * handler.cancel() and never allow proceeding past errors.
      *
      * @param view The WebView that is initiating the callback.
      * @param handler An SslErrorHandler object that will handle the user's
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 8f1f1ab..d22b1e6 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -284,7 +284,12 @@
             @Nullable SelectionResult result) {
         final Layout layout = mTextView.getLayout();
 
-        final Runnable onAnimationEndCallback = () -> startSelectionActionMode(result);
+        final Runnable onAnimationEndCallback = () -> {
+            if (result.mStart >= 0 && result.mEnd <= getText(mTextView).length()
+                    && result.mStart <= result.mEnd) {
+                startSelectionActionMode(result);
+            }
+        };
         // TODO do not trigger the animation if the change included only non-printable characters
         final boolean didSelectionChange =
                 result != null && (mTextView.getSelectionStart() != result.mStart
@@ -636,7 +641,7 @@
                             mSelectionStart, mSelectionEnd,
                             SelectionEvent.ACTION_ABANDON, null /* classification */);
                     mSelectionStart = mSelectionEnd = -1;
-                    mTextView.getTextClassificationSession().destroy();
+                    mLogger.endTextClassificationSession();
                     mIsPending = false;
                 }
             }
@@ -702,8 +707,10 @@
                 mTokenIterator.setText(mText);
                 mStartIndex = index;
                 mClassificationSession = classificationSession;
-                mClassificationSession.onSelectionEvent(
-                        SelectionEvent.createSelectionStartedEvent(invocationMethod, 0));
+                if (hasActiveClassificationSession()) {
+                    mClassificationSession.onSelectionEvent(
+                            SelectionEvent.createSelectionStartedEvent(invocationMethod, 0));
+                }
             } catch (Exception e) {
                 // Avoid crashes due to logging.
                 Log.e(LOG_TAG, "" + e.getMessage(), e);
@@ -713,23 +720,19 @@
         public void logSelectionModified(int start, int end,
                 @Nullable TextClassification classification, @Nullable TextSelection selection) {
             try {
-                Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
-                Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
-                int[] wordIndices = getWordDelta(start, end);
-                if (selection != null) {
-                    if (mClassificationSession != null) {
+                if (hasActiveClassificationSession()) {
+                    Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
+                    Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
+                    int[] wordIndices = getWordDelta(start, end);
+                    if (selection != null) {
                         mClassificationSession.onSelectionEvent(
                                 SelectionEvent.createSelectionModifiedEvent(
                                         wordIndices[0], wordIndices[1], selection));
-                    }
-                } else if (classification != null) {
-                    if (mClassificationSession != null) {
+                    } else if (classification != null) {
                         mClassificationSession.onSelectionEvent(
                                 SelectionEvent.createSelectionModifiedEvent(
                                         wordIndices[0], wordIndices[1], classification));
-                    }
-                } else {
-                    if (mClassificationSession != null) {
+                    } else {
                         mClassificationSession.onSelectionEvent(
                                 SelectionEvent.createSelectionModifiedEvent(
                                         wordIndices[0], wordIndices[1]));
@@ -746,21 +749,23 @@
                 @SelectionEvent.ActionType int action,
                 @Nullable TextClassification classification) {
             try {
-                Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
-                Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
-                int[] wordIndices = getWordDelta(start, end);
-                if (classification != null) {
-                    if (mClassificationSession != null) {
+                if (hasActiveClassificationSession()) {
+                    Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
+                    Preconditions.checkArgumentInRange(end, start, mText.length(), "end");
+                    int[] wordIndices = getWordDelta(start, end);
+                    if (classification != null) {
                         mClassificationSession.onSelectionEvent(
                                 SelectionEvent.createSelectionActionEvent(
-                                        wordIndices[0], wordIndices[1], action, classification));
-                    }
-                } else {
-                    if (mClassificationSession != null) {
+                                        wordIndices[0], wordIndices[1], action,
+                                        classification));
+                    } else {
                         mClassificationSession.onSelectionEvent(
                                 SelectionEvent.createSelectionActionEvent(
                                         wordIndices[0], wordIndices[1], action));
                     }
+                    if (SelectionEvent.isTerminal(action)) {
+                        endTextClassificationSession();
+                    }
                 }
             } catch (Exception e) {
                 // Avoid crashes due to logging.
@@ -772,6 +777,16 @@
             return mEditTextLogger;
         }
 
+        public void endTextClassificationSession() {
+            if (hasActiveClassificationSession()) {
+                mClassificationSession.destroy();
+            }
+        }
+
+        private boolean hasActiveClassificationSession() {
+            return mClassificationSession != null && !mClassificationSession.isDestroyed();
+        }
+
         private int[] getWordDelta(int start, int end) {
             int[] wordIndices = new int[2];
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 48775ad..a57d154 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11527,12 +11527,9 @@
                 } else {
                     widgetType = TextClassifier.WIDGET_TYPE_UNSELECTABLE_TEXTVIEW;
                 }
-                // TODO: Tagged this widgetType with a * so it we can monitor if it reports
-                // SelectionEvents exactly as the older Logger does. Remove once investigations
-                // are complete.
                 final TextClassificationContext textClassificationContext =
                         new TextClassificationContext.Builder(
-                                mContext.getPackageName(), "*" + widgetType)
+                                mContext.getPackageName(), widgetType)
                                 .build();
                 if (mTextClassifier != null) {
                     mTextClassificationSession = tcm.createTextClassificationSession(
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 97043c7..571878d 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@
 import android.animation.ObjectAnimator;
 import android.annotation.NonNull;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.usage.UsageStatsManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -1022,6 +1023,11 @@
 
         @Override
         public void onListRebuilt() {
+            // don't support direct share on low ram devices
+            if (ActivityManager.isLowRamDeviceStatic()) {
+                return;
+            }
+
             if (mServiceTargets != null) {
                 pruneServiceTargets();
             }
diff --git a/core/java/com/android/internal/app/ColorDisplayController.java b/core/java/com/android/internal/app/ColorDisplayController.java
index 6cc964b..ba6cf26 100644
--- a/core/java/com/android/internal/app/ColorDisplayController.java
+++ b/core/java/com/android/internal/app/ColorDisplayController.java
@@ -335,7 +335,7 @@
         if (colorTemperature == -1) {
             if (DEBUG) {
                 Slog.d(TAG, "Using default value for setting: "
-                    + Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE);
+                        + Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE);
             }
             colorTemperature = getDefaultColorTemperature();
         }
@@ -358,7 +358,7 @@
      */
     public boolean setColorTemperature(int colorTemperature) {
         return Secure.putIntForUser(mContext.getContentResolver(),
-            Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, colorTemperature, mUserId);
+                Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, colorTemperature, mUserId);
     }
 
     /**
@@ -367,10 +367,10 @@
      * See com.android.server.display.DisplayTransformManager.
      */
     private @ColorMode int getCurrentColorModeFromSystemProperties() {
-        int displayColorSetting = SystemProperties.getInt("persist.sys.sf.native_mode", 0);
+        final int displayColorSetting = SystemProperties.getInt("persist.sys.sf.native_mode", 0);
         if (displayColorSetting == 0) {
             return "1.0".equals(SystemProperties.get("persist.sys.sf.color_saturation"))
-                ? COLOR_MODE_NATURAL : COLOR_MODE_BOOSTED;
+                    ? COLOR_MODE_NATURAL : COLOR_MODE_BOOSTED;
         } else if (displayColorSetting == 1) {
             return COLOR_MODE_SATURATED;
         } else if (displayColorSetting == 2) {
@@ -381,16 +381,13 @@
     }
 
     private boolean isColorModeAvailable(@ColorMode int colorMode) {
-        // SATURATED is always allowed
-        if (colorMode == COLOR_MODE_SATURATED) {
-            return true;
-        }
-
         final int[] availableColorModes = mContext.getResources().getIntArray(
                 R.array.config_availableColorModes);
-        for (int mode : availableColorModes) {
-            if (mode == colorMode) {
-                return true;
+        if (availableColorModes != null) {
+            for (int mode : availableColorModes) {
+                if (mode == colorMode) {
+                    return true;
+                }
             }
         }
         return false;
@@ -401,14 +398,18 @@
      */
     public int getColorMode() {
         if (getAccessibilityTransformActivated()) {
-            return COLOR_MODE_SATURATED;
+            if (isColorModeAvailable(COLOR_MODE_SATURATED)) {
+                return COLOR_MODE_SATURATED;
+            } else if (isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
+                return COLOR_MODE_AUTOMATIC;
+            }
         }
 
         int colorMode = System.getIntForUser(mContext.getContentResolver(),
-            System.DISPLAY_COLOR_MODE, -1, mUserId);
+                System.DISPLAY_COLOR_MODE, -1, mUserId);
         if (colorMode == -1) {
-            // There still might be a legacy system property controlling color mode that we need to
-            // respect.
+            // There might be a system property controlling color mode that we need to respect; if
+            // not, this will set a suitable default.
             colorMode = getCurrentColorModeFromSystemProperties();
         }
 
@@ -418,10 +419,13 @@
             if (colorMode == COLOR_MODE_BOOSTED && isColorModeAvailable(COLOR_MODE_NATURAL)) {
                 colorMode = COLOR_MODE_NATURAL;
             } else if (colorMode == COLOR_MODE_SATURATED
-                && isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
+                    && isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
                 colorMode = COLOR_MODE_AUTOMATIC;
-            } else {
+            } else if (colorMode == COLOR_MODE_AUTOMATIC
+                    && isColorModeAvailable(COLOR_MODE_SATURATED)) {
                 colorMode = COLOR_MODE_SATURATED;
+            } else {
+                colorMode = -1;
             }
         }
 
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 1811800c..26fb6b64 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -59,8 +59,11 @@
     }
 
     public boolean pulseOnPickupAvailable() {
-        return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup)
-                && ambientDisplayAvailable();
+        return dozePulsePickupSensorAvailable() && ambientDisplayAvailable();
+    }
+
+    public boolean dozePulsePickupSensorAvailable() {
+        return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup);
     }
 
     public boolean pulseOnPickupCanBeModified(int user) {
@@ -73,7 +76,11 @@
     }
 
     public boolean pulseOnDoubleTapAvailable() {
-        return !TextUtils.isEmpty(doubleTapSensorType()) && ambientDisplayAvailable();
+        return doubleTapSensorAvailable() && ambientDisplayAvailable();
+    }
+
+    public boolean doubleTapSensorAvailable() {
+        return !TextUtils.isEmpty(doubleTapSensorType());
     }
 
     public String doubleTapSensorType() {
@@ -115,7 +122,7 @@
         return boolSettingDefaultOff(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, user);
     }
 
-    private boolean ambientDisplayAvailable() {
+    public boolean ambientDisplayAvailable() {
         return !TextUtils.isEmpty(ambientDisplayComponent());
     }
 
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 7116f3a..d135040 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -207,6 +207,8 @@
                 mAvatarView.setTranslationY(0.0f);
                 mSenderName.setAlpha(1.0f);
                 mSenderName.setTranslationY(0.0f);
+                mIsolatedMessage = null;
+                mMessages = null;
                 sInstancePool.release(MessagingGroup.this);
             }
         };
@@ -267,6 +269,11 @@
 
     @Override
     public int getMeasuredType() {
+        if (mIsolatedMessage != null) {
+            // We only want to show one group if we have an inline image, so let's return shortened
+            // to avoid displaying the other ones.
+            return MEASURED_SHORTENED;
+        }
         boolean hasNormal = false;
         for (int i = mMessageContainer.getChildCount() - 1; i >= 0; i--) {
             View child = mMessageContainer.getChildAt(i);
@@ -292,9 +299,6 @@
                 }
             }
         }
-        if (mMessageContainer.getChildCount() == 0 && mIsolatedMessage != null) {
-            return mIsolatedMessage.getMeasuredType();
-        }
         return MEASURED_NORMAL;
     }
 
diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java
index 9048f87..c7ea781 100644
--- a/core/java/com/android/internal/widget/NotificationActionListLayout.java
+++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java
@@ -206,7 +206,17 @@
         final boolean centerAligned = (mGravity & Gravity.CENTER_HORIZONTAL) != 0;
 
         int childTop;
-        int childLeft = centerAligned ? left + (right - left) / 2 - mTotalWidth / 2 : 0;
+        int childLeft;
+        if (centerAligned) {
+            childLeft = mPaddingLeft + left + (right - left) / 2 - mTotalWidth / 2;
+        } else {
+            childLeft = mPaddingLeft;
+            int absoluteGravity = Gravity.getAbsoluteGravity(Gravity.START, getLayoutDirection());
+            if (absoluteGravity == Gravity.RIGHT) {
+                childLeft += right - left - mTotalWidth;
+            }
+        }
+
 
         // Where bottom of child should go
         final int height = bottom - top;
@@ -216,18 +226,6 @@
 
         final int count = getChildCount();
 
-        final int layoutDirection = getLayoutDirection();
-        switch (Gravity.getAbsoluteGravity(Gravity.START, layoutDirection)) {
-            case Gravity.RIGHT:
-                childLeft += mPaddingLeft + right - left - mTotalWidth;
-                break;
-
-            case Gravity.LEFT:
-            default:
-                childLeft += mPaddingLeft;
-                break;
-        }
-
         int start = 0;
         int dir = 1;
         //In case of RTL, start drawing from the last child.
diff --git a/core/res/res/drawable/ic_camera.xml b/core/res/res/drawable/ic_camera.xml
index 2921a68..7074531 100644
--- a/core/res/res/drawable/ic_camera.xml
+++ b/core/res/res/drawable/ic_camera.xml
@@ -19,9 +19,6 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"
-        android:fillColor="#FFFFFF"/>
-    <path
-        android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M20,5h-3.17L15,3H9L7.17,5H4C2.9,5 2,5.9 2,7v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM20,19H4V7h16V19zM12,9c-2.21,0 -4,1.79 -4,4c0,2.21 1.79,4 4,4s4,-1.79 4,-4C16,10.79 14.21,9 12,9z"/>
 </vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_mic.xml b/core/res/res/drawable/ic_mic.xml
index 3212330..29389fa 100644
--- a/core/res/res/drawable/ic_mic.xml
+++ b/core/res/res/drawable/ic_mic.xml
@@ -19,6 +19,9 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3,5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"
-        android:fillColor="#FFFFFF"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V5z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z"/>
 </vector>
\ No newline at end of file
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 946b0e6..cb26a1a 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -89,7 +89,7 @@
     <string name="EmergencyCallWarningSummary" msgid="1899692069750260619">"Շտապ կանչերը հասանելի չեն Wi‑Fi-ի միջոցով"</string>
     <string name="notification_channel_network_alert" msgid="4427736684338074967">"Ծանուցումներ"</string>
     <string name="notification_channel_call_forward" msgid="2419697808481833249">"Զանգի վերահասցեավորում"</string>
-    <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Շտապ հետկանչի ռեժիմ"</string>
+    <string name="notification_channel_emergency_callback" msgid="6686166232265733921">"Շտապ հետզանգի ռեժիմ"</string>
     <string name="notification_channel_mobile_data_status" msgid="4575131690860945836">"Բջջային ինտերնետի կարգավիճակը"</string>
     <string name="notification_channel_sms" msgid="3441746047346135073">"SMS հաղորդագրություններ"</string>
     <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Ձայնային փոստի հաղորդագրություններ"</string>
@@ -657,7 +657,7 @@
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"Տան ֆաքս"</string>
     <string name="phoneTypePager" msgid="7582359955394921732">"Փեյջեր"</string>
     <string name="phoneTypeOther" msgid="1544425847868765990">"Այլ"</string>
-    <string name="phoneTypeCallback" msgid="2712175203065678206">"Ետզանգ"</string>
+    <string name="phoneTypeCallback" msgid="2712175203065678206">"Հետզանգ"</string>
     <string name="phoneTypeCar" msgid="8738360689616716982">"Մեքենա"</string>
     <string name="phoneTypeCompanyMain" msgid="540434356461478916">"Ընկերության հիմնական"</string>
     <string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2e8c7f9..471170b 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -55,7 +55,7 @@
     <!-- Width of the navigation bar when it is placed vertically on the screen in car mode -->
     <dimen name="navigation_bar_width_car_mode">96dp</dimen>
     <!-- Height of notification icons in the status bar -->
-    <dimen name="status_bar_icon_size">24dip</dimen>
+    <dimen name="status_bar_icon_size">22dip</dimen>
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 5b7fc6e..fc00f1b 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -132,6 +132,7 @@
                     Settings.Global.BLE_SCAN_LOW_LATENCY_WINDOW_MS,
                     Settings.Global.BLE_SCAN_LOW_LATENCY_INTERVAL_MS,
                     Settings.Global.BLE_SCAN_BACKGROUND_MODE,
+                    Settings.Global.BLOCKED_SLICES,
                     Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT,
                     Settings.Global.BLOCKING_HELPER_STREAK_LIMIT,
                     Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
@@ -155,6 +156,7 @@
                     Settings.Global.CAPTIVE_PORTAL_HTTP_URL,
                     Settings.Global.CAPTIVE_PORTAL_MODE,
                     Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS,
+                    Settings.Global.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS,
                     Settings.Global.CAPTIVE_PORTAL_SERVER,
                     Settings.Global.CAPTIVE_PORTAL_USE_HTTPS,
                     Settings.Global.CAPTIVE_PORTAL_USER_AGENT,
@@ -591,6 +593,7 @@
                  Settings.Secure.SHOW_ROTATION_SUGGESTIONS,
                  Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate?
                  Settings.Secure.SMS_DEFAULT_APPLICATION,
+                 Settings.Secure.THEME_MODE,
                  Settings.Secure.TRUST_AGENTS_INITIALIZED,
                  Settings.Secure.TV_INPUT_CUSTOM_LABELS,
                  Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
diff --git a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
index c4d5b0c..8909293 100644
--- a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
@@ -48,6 +48,11 @@
     }
 
     @Test
+    public void testNonNegativeIntegerValidator_onNullValue_returnsFalse() {
+        assertFalse(SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR.validate(null));
+    }
+
+    @Test
     public void testAnyIntegerValidator() {
         assertTrue(SettingsValidators.ANY_INTEGER_VALIDATOR.validate("1"));
         assertTrue(SettingsValidators.ANY_INTEGER_VALIDATOR.validate("0"));
@@ -56,6 +61,16 @@
     }
 
     @Test
+    public void testAnyIntegerValidator_onNullValue_returnsFalse() {
+        assertFalse(SettingsValidators.ANY_INTEGER_VALIDATOR.validate(null));
+    }
+
+    @Test
+    public void testUriValidator_onNullValue_returnsTrue() {
+        assertTrue(SettingsValidators.URI_VALIDATOR.validate(null));
+    }
+
+    @Test
     public void testComponentNameValidator() {
         assertTrue(SettingsValidators.COMPONENT_NAME_VALIDATOR.validate(
                 "android/com.android.internal.backup.LocalTransport"));
@@ -63,11 +78,33 @@
     }
 
     @Test
-    public void testComponentNameValidator_onNullValue_doesNotThrow() {
+    public void testComponentNameValidator_onNullValue_returnsFalse() {
         assertFalse(SettingsValidators.COMPONENT_NAME_VALIDATOR.validate(null));
     }
 
     @Test
+    public void testLenientIpAddressValidator_onNullValue_returnsFalse() {
+        assertFalse(SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR.validate(null));
+    }
+
+    @Test
+    public void testNullableComponentNameValidator_onValidComponentName_returnsTrue() {
+        assertTrue(SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR.validate(
+                "android/com.android.internal.backup.LocalTransport"));
+    }
+
+    @Test
+    public void testNullableComponentNameValidator_onInvalidComponentName_returnsFalse() {
+        assertFalse(SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR.validate(
+                "rectangle"));
+    }
+
+    @Test
+    public void testNullableComponentNameValidator_onNullValue_returnsTrue() {
+        assertTrue(SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR.validate(null));
+    }
+
+    @Test
     public void testLocaleValidator() {
         assertTrue(SettingsValidators.LOCALE_VALIDATOR.validate("en_US"));
         assertTrue(SettingsValidators.LOCALE_VALIDATOR.validate("es"));
@@ -75,6 +112,11 @@
     }
 
     @Test
+    public void testLocaleValidator_onNullValue_returnsFalse() {
+        assertFalse(SettingsValidators.LOCALE_VALIDATOR.validate(null));
+    }
+
+    @Test
     public void testPackageNameValidator() {
         assertTrue(SettingsValidators.PACKAGE_NAME_VALIDATOR.validate(
                 "com.google.android"));
@@ -84,6 +126,11 @@
     }
 
     @Test
+    public void testPackageNameValidator_onNullValue_returnsFalse() {
+        assertFalse(SettingsValidators.PACKAGE_NAME_VALIDATOR.validate(null));
+    }
+
+    @Test
     public void testDiscreteValueValidator() {
         String[] beerTypes = new String[]{"Ale", "American IPA", "Stout"};
         Validator v = new SettingsValidators.DiscreteValueValidator(beerTypes);
@@ -94,6 +141,14 @@
     }
 
     @Test
+    public void testDiscreteValueValidator_onNullValue_returnsFalse() {
+        String[] discreteTypes = new String[]{"Type1", "Type2"};
+        Validator v = new SettingsValidators.DiscreteValueValidator(discreteTypes);
+
+        assertFalse(v.validate(null));
+    }
+
+    @Test
     public void testInclusiveIntegerRangeValidator() {
         Validator v = new SettingsValidators.InclusiveIntegerRangeValidator(0, 5);
         assertTrue(v.validate("0"));
@@ -104,6 +159,13 @@
     }
 
     @Test
+    public void testInclusiveIntegerRangeValidator_onNullValue_returnsFalse() {
+        Validator v = new SettingsValidators.InclusiveIntegerRangeValidator(0, 5);
+
+        assertFalse(v.validate(null));
+    }
+
+    @Test
     public void testInclusiveFloatRangeValidator() {
         Validator v = new SettingsValidators.InclusiveFloatRangeValidator(0.0f, 5.0f);
         assertTrue(v.validate("0.0"));
@@ -114,6 +176,13 @@
     }
 
     @Test
+    public void testInclusiveFloatRangeValidator_onNullValue_returnsFalse() {
+        Validator v = new SettingsValidators.InclusiveFloatRangeValidator(0.0f, 5.0f);
+
+        assertFalse(v.validate(null));
+    }
+
+    @Test
     public void testComponentNameListValidator() {
         Validator v = new SettingsValidators.ComponentNameListValidator(",");
         assertTrue(v.validate("android/com.android.internal.backup.LocalTransport,"
@@ -122,12 +191,30 @@
     }
 
     @Test
+    public void testComponentNameListValidator_onNullValue_returnsFalse() {
+        Validator v = new SettingsValidators.ComponentNameListValidator(",");
+
+        assertFalse(v.validate(null));
+    }
+
+    @Test
     public void testPackageNameListValidator() {
         Validator v = new SettingsValidators.PackageNameListValidator(",");
         assertTrue(v.validate("com.android.internal.backup.LocalTransport,com.google.android.gms"));
         assertFalse(v.validate("5com.android.internal.backup.LocalTransport,android"));
     }
 
+    @Test
+    public void testPackageNameListValidator_onNullValue_returnsFalse() {
+        Validator v = new SettingsValidators.PackageNameListValidator(",");
+
+        assertFalse(v.validate(null));
+    }
+
+    @Test
+    public void dateFormatValidator_onNullValue_returnsFalse() {
+        assertFalse(Settings.System.DATE_FORMAT_VALIDATOR.validate(null));
+    }
 
     @Test
     public void ensureAllBackedUpSystemSettingsHaveValidators() {
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index bcb7cf3..70dc618 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -46,6 +46,7 @@
 import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
 import static android.widget.espresso.TextViewAssertions.hasSelection;
 
+import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
@@ -77,6 +78,7 @@
 import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.textclassifier.SelectionEvent;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassifier;
 import android.view.textclassifier.TextLinks;
@@ -90,6 +92,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Tests the TextView widget from an Activity
  */
@@ -978,6 +983,30 @@
     }
 
     @Test
+    public void testSelectionMetricsLogger_noAbandonAfterCopy() throws Throwable {
+        final List<SelectionEvent> selectionEvents = new ArrayList<>();
+        final TextClassifier classifier = new TextClassifier() {
+            @Override
+            public void onSelectionEvent(SelectionEvent event) {
+                selectionEvents.add(event);
+            }
+        };
+        final TextView textView = mActivity.findViewById(R.id.textview);
+        mActivityRule.runOnUiThread(() -> textView.setTextClassifier(classifier));
+        mInstrumentation.waitForIdleSync();
+        final String text = "andyroid@android.com";
+
+        onView(withId(R.id.textview)).perform(replaceText(text));
+        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('@')));
+        sleepForFloatingToolbarPopup();
+        clickFloatingToolbarItem(mActivity.getString(com.android.internal.R.string.copy));
+        mInstrumentation.waitForIdleSync();
+
+        final SelectionEvent lastEvent = selectionEvents.get(selectionEvents.size() - 1);
+        assertEquals(SelectionEvent.ACTION_COPY, lastEvent.getEventType());
+    }
+
+    @Test
     public void testPastePlainText_menuAction() {
         initializeClipboardWithText(TextStyle.STYLED);
 
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 007cddd..b644cc3 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -458,7 +458,7 @@
 
     // The chunk must be at least the size of the string pool header.
     if (size < sizeof(ResStringPool_header)) {
-        LOG_ALWAYS_FATAL("Bad string block: data size %zu is too small to be a string block", size);
+        ALOGW("Bad string block: data size %zu is too small to be a string block", size);
         return (mError=BAD_TYPE);
     }
 
@@ -468,7 +468,7 @@
     if (validate_chunk(reinterpret_cast<const ResChunk_header*>(data), sizeof(ResStringPool_header),
                        reinterpret_cast<const uint8_t*>(data) + size,
                        "ResStringPool_header") != NO_ERROR) {
-        LOG_ALWAYS_FATAL("Bad string block: malformed block dimensions");
+        ALOGW("Bad string block: malformed block dimensions");
         return (mError=BAD_TYPE);
     }
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3057501..0c38c38 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3939,6 +3939,7 @@
      * @param device Bluetooth device connected/disconnected
      * @param state  new connection state (BluetoothProfile.STATE_xxx)
      * @param profile profile for the A2DP device
+     * @param a2dpVolume New volume for the connecting device. Does nothing if disconnecting.
      * (either {@link android.bluetooth.BluetoothProfile.A2DP} or
      * {@link android.bluetooth.BluetoothProfile.A2DP_SINK})
      * @param suppressNoisyIntent if true the
@@ -3948,12 +3949,13 @@
      * {@hide}
      */
     public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
-                BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent) {
+                BluetoothDevice device, int state, int profile,
+                boolean suppressNoisyIntent, int a2dpVolume) {
         final IAudioService service = getService();
         int delay = 0;
         try {
             delay = service.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device,
-                state, profile, suppressNoisyIntent);
+                state, profile, suppressNoisyIntent, a2dpVolume);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -4717,7 +4719,7 @@
                 NativeEventHandlerDelegate delegate =
                         new NativeEventHandlerDelegate(callback, handler);
                 mDeviceCallbacks.put(callback, delegate);
-                broadcastDeviceListChange(delegate.getHandler());
+                broadcastDeviceListChange_sync(delegate.getHandler());
             }
         }
     }
@@ -4836,9 +4838,9 @@
 
     /**
      * Internal method to compute and generate add/remove messages and then send to any
-     * registered callbacks.
+     * registered callbacks. Must be called synchronized on mDeviceCallbacks.
      */
-    private void broadcastDeviceListChange(Handler handler) {
+    private void broadcastDeviceListChange_sync(Handler handler) {
         int status;
 
         // Get the new current set of ports
@@ -4860,20 +4862,18 @@
             AudioDeviceInfo[] removed_devices =
                     calcListDeltas(current_ports, mPreviousPorts, GET_DEVICES_ALL);
             if (added_devices.length != 0 || removed_devices.length != 0) {
-                synchronized (mDeviceCallbacks) {
-                    for (int i = 0; i < mDeviceCallbacks.size(); i++) {
-                        handler = mDeviceCallbacks.valueAt(i).getHandler();
-                        if (handler != null) {
-                            if (removed_devices.length != 0) {
-                                handler.sendMessage(Message.obtain(handler,
-                                                                   MSG_DEVICES_DEVICES_REMOVED,
-                                                                   removed_devices));
-                            }
-                            if (added_devices.length != 0) {
-                                handler.sendMessage(Message.obtain(handler,
-                                                                   MSG_DEVICES_DEVICES_ADDED,
-                                                                   added_devices));
-                            }
+                for (int i = 0; i < mDeviceCallbacks.size(); i++) {
+                    handler = mDeviceCallbacks.valueAt(i).getHandler();
+                    if (handler != null) {
+                        if (removed_devices.length != 0) {
+                            handler.sendMessage(Message.obtain(handler,
+                                    MSG_DEVICES_DEVICES_REMOVED,
+                                    removed_devices));
+                        }
+                        if (added_devices.length != 0) {
+                            handler.sendMessage(Message.obtain(handler,
+                                    MSG_DEVICES_DEVICES_ADDED,
+                                    added_devices));
                         }
                     }
                 }
@@ -4889,7 +4889,9 @@
     private class OnAmPortUpdateListener implements AudioManager.OnAudioPortUpdateListener {
         static final String TAG = "OnAmPortUpdateListener";
         public void onAudioPortListUpdate(AudioPort[] portList) {
-            broadcastDeviceListChange(null);
+            synchronized (mDeviceCallbacks) {
+                broadcastDeviceListChange_sync(null);
+            }
         }
 
         /**
@@ -4903,7 +4905,9 @@
          * Callback method called when the mediaserver dies
          */
         public void onServiceDied() {
-            broadcastDeviceListChange(null);
+            synchronized (mDeviceCallbacks) {
+                broadcastDeviceListChange_sync(null);
+            }
         }
     }
 
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 4af8850..569db16 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -211,7 +211,7 @@
     oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
 
     int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(in BluetoothDevice device,
-            int state, int profile, boolean suppressNoisyIntent);
+            int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
 
     oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,
             in IAudioPolicyCallback pcb);
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 9828275..a768dd3 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -207,8 +207,9 @@
      * after  {@link Image#close Image.close()} has been called.
      * </p>
      * @return the HardwareBuffer associated with this Image or null if this Image doesn't support
-     * this feature (e.g. {@link android.media.ImageWriter ImageWriter} or
-     * {@link android.media.MediaCodec MediaCodec} don't).
+     * this feature. (Unsupported use cases include Image instances obtained through
+     * {@link android.media.MediaCodec MediaCodec}, and on versions prior to Android P,
+     * {@link android.media.ImageWriter ImageWriter}).
      */
     @Nullable
     public HardwareBuffer getHardwareBuffer() {
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index 397768a..4c0153f 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -20,6 +20,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.hardware.camera2.utils.SurfaceUtils;
+import android.hardware.HardwareBuffer;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -58,12 +59,17 @@
  * </p>
  * <p>
  * If the application already has an Image from {@link ImageReader}, the
- * application can directly queue this Image into ImageWriter (via
- * {@link #queueInputImage}), potentially with zero buffer copies. For the
- * {@link ImageFormat#PRIVATE PRIVATE} format Images produced by
- * {@link ImageReader}, this is the only way to send Image data to ImageWriter,
- * as the Image data aren't accessible by the application.
+ * application can directly queue this Image into the ImageWriter (via
+ * {@link #queueInputImage}), potentially with zero buffer copies. This
+ * even works if the image format of the ImageWriter is
+ * {@link ImageFormat#PRIVATE PRIVATE}, and prior to Android P is the only
+ * way to enqueue images into such an ImageWriter. Starting in Android P
+ * private images may also be accessed through their hardware buffers
+ * (when available) through the {@link Image#getHardwareBuffer()} method.
+ * Attempting to access the planes of a private image, will return an
+ * empty array.
  * </p>
+ * <p>
  * Once new input Images are queued into an ImageWriter, it's up to the
  * downstream components (e.g. {@link ImageReader} or
  * {@link android.hardware.camera2.CameraDevice}) to consume the Images. If the
@@ -257,29 +263,26 @@
      * <p>
      * If the format of ImageWriter is {@link ImageFormat#PRIVATE PRIVATE} (
      * {@link ImageWriter#getFormat()} == {@link ImageFormat#PRIVATE}), the
-     * image buffer is inaccessible to the application, and calling this method
-     * will result in an {@link IllegalStateException}. Instead, the application
-     * should acquire images from some other component (e.g. an
+     * image buffer is accessible to the application only through the hardware
+     * buffer obtained through {@link Image#getHardwareBuffer()}. (On Android
+     * versions prior to P, dequeueing private buffers will cause an
+     * {@link IllegalStateException} to be thrown). Alternatively,
+     * the application can acquire images from some other component (e.g. an
      * {@link ImageReader}), and queue them directly to this ImageWriter via the
      * {@link ImageWriter#queueInputImage queueInputImage()} method.
      * </p>
      *
      * @return The next available input Image from this ImageWriter.
      * @throws IllegalStateException if {@code maxImages} Images are currently
-     *             dequeued, or the ImageWriter format is
-     *             {@link ImageFormat#PRIVATE PRIVATE}, or the input
-     *             {@link android.view.Surface Surface} has been abandoned by the
-     *             consumer component that provided the {@link android.view.Surface Surface}.
+     *             dequeued, or the input {@link android.view.Surface Surface}
+     *             has been abandoned by the consumer component that provided
+     *             the {@link android.view.Surface Surface}. Prior to Android
+     *             P, throws if the ImageWriter format is
+     *             {@link ImageFormat#PRIVATE PRIVATE}.
      * @see #queueInputImage
      * @see Image#close
      */
     public Image dequeueInputImage() {
-        if (mWriterFormat == ImageFormat.PRIVATE) {
-            throw new IllegalStateException(
-                    "PRIVATE format ImageWriter doesn't support this operation since the images are"
-                            + " inaccessible to the application!");
-        }
-
         if (mDequeuedImages.size() >= mMaxImages) {
             throw new IllegalStateException("Already dequeued max number of Images " + mMaxImages);
         }
@@ -743,6 +746,13 @@
         }
 
         @Override
+        public HardwareBuffer getHardwareBuffer() {
+            throwISEIfImageIsInvalid();
+
+            return nativeGetHardwareBuffer();
+        }
+
+        @Override
         public Plane[] getPlanes() {
             throwISEIfImageIsInvalid();
 
@@ -863,6 +873,8 @@
         private synchronized native int nativeGetHeight();
 
         private synchronized native int nativeGetFormat();
+
+        private synchronized native HardwareBuffer nativeGetHardwareBuffer();
     }
 
     // Native implemented ImageWriter methods.
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 392a1eb..ada91be 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2848,8 +2848,12 @@
                     mInbandTrackIndices.set(i);
                 }
 
+                if (tracks[i] == null) {
+                    Log.w(TAG, "unexpected NULL track at index " + i);
+                }
                 // newly appeared inband track
-                if (tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
+                if (tracks[i] != null
+                        && tracks[i].getTrackType() == TrackInfo.MEDIA_TRACK_TYPE_SUBTITLE) {
                     SubtitleTrack track = mSubtitleController.addTrack(
                             tracks[i].getFormat());
                     mIndexTrackPairs.add(Pair.create(i, track));
diff --git a/media/java/android/media/audiofx/DynamicsProcessing.java b/media/java/android/media/audiofx/DynamicsProcessing.java
index 4c17ae1..1c3cff9 100644
--- a/media/java/android/media/audiofx/DynamicsProcessing.java
+++ b/media/java/android/media/audiofx/DynamicsProcessing.java
@@ -279,25 +279,24 @@
     private static final boolean PREEQ_DEFAULT_ENABLED = true;
     private static final boolean POSTEQ_DEFAULT_ENABLED = true;
 
-
     private static final boolean MBC_DEFAULT_ENABLED = true;
-    private static final float MBC_DEFAULT_ATTACK_TIME = 50; // ms
-    private static final float MBC_DEFAULT_RELEASE_TIME = 120; // ms
-    private static final float MBC_DEFAULT_RATIO = 2; // 1:N
-    private static final float MBC_DEFAULT_THRESHOLD = -30; // dB
+    private static final float MBC_DEFAULT_ATTACK_TIME = 3; // ms
+    private static final float MBC_DEFAULT_RELEASE_TIME = 80; // ms
+    private static final float MBC_DEFAULT_RATIO = 1; // N:1
+    private static final float MBC_DEFAULT_THRESHOLD = -45; // dB
     private static final float MBC_DEFAULT_KNEE_WIDTH = 0; // dB
-    private static final float MBC_DEFAULT_NOISE_GATE_THRESHOLD = -80; // dB
-    private static final float MBC_DEFAULT_EXPANDER_RATIO = 1.5f; // N:1
+    private static final float MBC_DEFAULT_NOISE_GATE_THRESHOLD = -90; // dB
+    private static final float MBC_DEFAULT_EXPANDER_RATIO = 1; // 1:N
     private static final float MBC_DEFAULT_PRE_GAIN = 0; // dB
-    private static final float MBC_DEFAULT_POST_GAIN = 10; // dB
+    private static final float MBC_DEFAULT_POST_GAIN = 0; // dB
 
     private static final boolean LIMITER_DEFAULT_ENABLED = true;
     private static final int LIMITER_DEFAULT_LINK_GROUP = 0;//;
-    private static final float LIMITER_DEFAULT_ATTACK_TIME = 50; // ms
-    private static final float LIMITER_DEFAULT_RELEASE_TIME = 120; // ms
-    private static final float LIMITER_DEFAULT_RATIO = 2; // 1:N
-    private static final float LIMITER_DEFAULT_THRESHOLD = -30; // dB
-    private static final float LIMITER_DEFAULT_POST_GAIN = 10; // dB
+    private static final float LIMITER_DEFAULT_ATTACK_TIME = 1; // ms
+    private static final float LIMITER_DEFAULT_RELEASE_TIME = 60; // ms
+    private static final float LIMITER_DEFAULT_RATIO = 10; // N:1
+    private static final float LIMITER_DEFAULT_THRESHOLD = -2; // dB
+    private static final float LIMITER_DEFAULT_POST_GAIN = 0; // dB
 
     private static final float DEFAULT_MIN_FREQUENCY = 220; // Hz
     private static final float DEFAULT_MAX_FREQUENCY = 20000; // Hz
@@ -540,13 +539,14 @@
          * band number, thus band 0 cutoffFrequency <= band 1 cutoffFrequency, and so on.
          * @param attackTime Attack Time for compressor in milliseconds (ms)
          * @param releaseTime Release Time for compressor in milliseconds (ms)
-         * @param ratio Compressor ratio (1:N)
+         * @param ratio Compressor ratio (N:1) (input:output)
          * @param threshold Compressor threshold measured in decibels (dB) from 0 dB Full Scale
          * (dBFS).
          * @param kneeWidth Width in decibels (dB) around compressor threshold point.
          * @param noiseGateThreshold Noise gate threshold in decibels (dB) from 0 dB Full Scale
          * (dBFS).
-         * @param expanderRatio Expander ratio (N:1) for signals below the Noise Gate Threshold.
+         * @param expanderRatio Expander ratio (1:N) (input:output) for signals below the Noise Gate
+         * Threshold.
          * @param preGain Gain applied to the signal BEFORE the compression.
          * @param postGain Gain applied to the signal AFTER compression.
          */
@@ -618,13 +618,13 @@
          */
         public void setReleaseTime(float releaseTime) { mReleaseTime = releaseTime; }
         /**
-         * gets the compressor ratio (1:N)
-         * @return compressor ratio (1:N)
+         * gets the compressor ratio (N:1)
+         * @return compressor ratio (N:1)
          */
         public float getRatio() { return mRatio; }
         /**
-         * sets compressor ratio (1:N)
-         * @param ratio desired for the compressor (1:N)
+         * sets compressor ratio (N:1)
+         * @param ratio desired for the compressor (N:1)
          */
         public void setRatio(float ratio) { mRatio = ratio; }
         /**
@@ -670,13 +670,13 @@
         public void setNoiseGateThreshold(float noiseGateThreshold) {
             mNoiseGateThreshold = noiseGateThreshold; }
         /**
-         * gets Expander ratio (N:1) for signals below the Noise Gate Threshold.
-         * @return Expander ratio (N:1)
+         * gets Expander ratio (1:N) for signals below the Noise Gate Threshold.
+         * @return Expander ratio (1:N)
          */
         public float getExpanderRatio() { return mExpanderRatio; }
         /**
-         * sets Expander ratio (N:1) for signals below the Noise Gate Threshold.
-         * @param expanderRatio desired expander ratio (N:1)
+         * sets Expander ratio (1:N) for signals below the Noise Gate Threshold.
+         * @param expanderRatio desired expander ratio (1:N)
          */
         public void setExpanderRatio(float expanderRatio) { mExpanderRatio = expanderRatio; }
         /**
@@ -909,7 +909,7 @@
          * same linkGroup index will react together.
          * @param attackTime Attack Time for limiter compressor in milliseconds (ms)
          * @param releaseTime Release Time for limiter compressor in milliseconds (ms)
-         * @param ratio Limiter Compressor ratio (1:N)
+         * @param ratio Limiter Compressor ratio (N:1) (input:output)
          * @param threshold Limiter Compressor threshold measured in decibels (dB) from 0 dB Full
          * Scale (dBFS).
          * @param postGain Gain applied to the signal AFTER compression.
@@ -985,13 +985,13 @@
          */
         public void setReleaseTime(float releaseTime) { mReleaseTime = releaseTime; }
         /**
-         * gets the limiter compressor ratio (1:N)
-         * @return limiter compressor ratio (1:N)
+         * gets the limiter compressor ratio (N:1)
+         * @return limiter compressor ratio (N:1)
          */
         public float getRatio() { return mRatio; }
         /**
-         * sets limiter compressor ratio (1:N)
-         * @param ratio desired for the limiter compressor (1:N)
+         * sets limiter compressor ratio (N:1)
+         * @param ratio desired for the limiter compressor (N:1)
          */
         public void setRatio(float ratio) { mRatio = ratio; }
         /**
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index 9634c7f..626338d 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -17,6 +17,7 @@
 
 import android.content.Intent;
 import android.media.Rating;
+import android.media.session.ISessionControllerCallback;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -25,33 +26,46 @@
  * @hide
  */
 oneway interface ISessionCallback {
-    void onCommand(String packageName, int pid, int uid, String command, in Bundle args,
-            in ResultReceiver cb);
+    void onCommand(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            String command, in Bundle args, in ResultReceiver cb);
     void onMediaButton(String packageName, int pid, int uid, in Intent mediaButtonIntent,
             int sequenceNumber, in ResultReceiver cb);
+    void onMediaButtonFromController(String packageName, int pid, int uid,
+            ISessionControllerCallback caller, in Intent mediaButtonIntent);
 
     // These callbacks are for the TransportPerformer
-    void onPrepare(String packageName, int pid, int uid);
-    void onPrepareFromMediaId(String packageName, int pid, int uid, String mediaId,
-            in Bundle extras);
-    void onPrepareFromSearch(String packageName, int pid, int uid, String query, in Bundle extras);
-    void onPrepareFromUri(String packageName, int pid, int uid, in Uri uri, in Bundle extras);
-    void onPlay(String packageName, int pid, int uid);
-    void onPlayFromMediaId(String packageName, int pid, int uid, String mediaId, in Bundle extras);
-    void onPlayFromSearch(String packageName, int pid, int uid, String query, in Bundle extras);
-    void onPlayFromUri(String packageName, int pid, int uid, in Uri uri, in Bundle extras);
-    void onSkipToTrack(String packageName, int pid, int uid, long id);
-    void onPause(String packageName, int pid, int uid);
-    void onStop(String packageName, int pid, int uid);
-    void onNext(String packageName, int pid, int uid);
-    void onPrevious(String packageName, int pid, int uid);
-    void onFastForward(String packageName, int pid, int uid);
-    void onRewind(String packageName, int pid, int uid);
-    void onSeekTo(String packageName, int pid, int uid, long pos);
-    void onRate(String packageName, int pid, int uid, in Rating rating);
-    void onCustomAction(String packageName, int pid, int uid, String action, in Bundle args);
+    void onPrepare(String packageName, int pid, int uid, ISessionControllerCallback caller);
+    void onPrepareFromMediaId(String packageName, int pid, int uid,
+            ISessionControllerCallback caller, String mediaId, in Bundle extras);
+    void onPrepareFromSearch(String packageName, int pid, int uid,
+            ISessionControllerCallback caller, String query, in Bundle extras);
+    void onPrepareFromUri(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            in Uri uri, in Bundle extras);
+    void onPlay(String packageName, int pid, int uid, ISessionControllerCallback caller);
+    void onPlayFromMediaId(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            String mediaId, in Bundle extras);
+    void onPlayFromSearch(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            String query, in Bundle extras);
+    void onPlayFromUri(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            in Uri uri, in Bundle extras);
+    void onSkipToTrack(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            long id);
+    void onPause(String packageName, int pid, int uid, ISessionControllerCallback caller);
+    void onStop(String packageName, int pid, int uid, ISessionControllerCallback caller);
+    void onNext(String packageName, int pid, int uid, ISessionControllerCallback caller);
+    void onPrevious(String packageName, int pid, int uid, ISessionControllerCallback caller);
+    void onFastForward(String packageName, int pid, int uid, ISessionControllerCallback caller);
+    void onRewind(String packageName, int pid, int uid, ISessionControllerCallback caller);
+    void onSeekTo(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            long pos);
+    void onRate(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            in Rating rating);
+    void onCustomAction(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            String action, in Bundle args);
 
     // These callbacks are for volume handling
-    void onAdjustVolume(String packageName, int pid, int uid, int direction);
-    void onSetVolumeTo(String packageName, int pid, int uid, int value);
+    void onAdjustVolume(String packageName, int pid, int uid, ISessionControllerCallback caller,
+            int direction);
+    void onSetVolumeTo(String packageName, int pid, int uid,
+            ISessionControllerCallback caller, int value);
 }
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index b4f52f9..861a8ce 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -32,42 +32,53 @@
 import java.util.List;
 
 /**
- * Interface to a MediaSession in the system.
+ * Interface to MediaSessionRecord in the system.
  * @hide
  */
 interface ISessionController {
-    void sendCommand(String packageName, String command, in Bundle args, in ResultReceiver cb);
-    boolean sendMediaButton(String packageName, boolean asSystemService, in KeyEvent mediaButton);
-    void registerCallbackListener(in ISessionControllerCallback cb);
-    void unregisterCallbackListener(in ISessionControllerCallback cb);
+    void sendCommand(String packageName, ISessionControllerCallback caller,
+            String command, in Bundle args, in ResultReceiver cb);
+    boolean sendMediaButton(String packageName, ISessionControllerCallback caller,
+            boolean asSystemService, in KeyEvent mediaButton);
+    void registerCallbackListener(String packageName, ISessionControllerCallback cb);
+    void unregisterCallbackListener(ISessionControllerCallback cb);
     boolean isTransportControlEnabled();
     String getPackageName();
     String getTag();
     PendingIntent getLaunchPendingIntent();
     long getFlags();
     ParcelableVolumeInfo getVolumeAttributes();
-    void adjustVolume(String packageName, boolean asSystemService, int direction, int flags);
-    void setVolumeTo(String packageName, int value, int flags);
+    void adjustVolume(String packageName, ISessionControllerCallback caller,
+            boolean asSystemService, int direction, int flags);
+    void setVolumeTo(String packageName, ISessionControllerCallback caller,
+            int value, int flags);
 
     // These commands are for the TransportControls
-    void prepare(String packageName);
-    void prepareFromMediaId(String packageName, String mediaId, in Bundle extras);
-    void prepareFromSearch(String packageName, String string, in Bundle extras);
-    void prepareFromUri(String packageName, in Uri uri, in Bundle extras);
-    void play(String packageName);
-    void playFromMediaId(String packageName, String mediaId, in Bundle extras);
-    void playFromSearch(String packageName, String string, in Bundle extras);
-    void playFromUri(String packageName, in Uri uri, in Bundle extras);
-    void skipToQueueItem(String packageName, long id);
-    void pause(String packageName);
-    void stop(String packageName);
-    void next(String packageName);
-    void previous(String packageName);
-    void fastForward(String packageName);
-    void rewind(String packageName);
-    void seekTo(String packageName, long pos);
-    void rate(String packageName, in Rating rating);
-    void sendCustomAction(String packageName, String action, in Bundle args);
+    void prepare(String packageName, ISessionControllerCallback caller);
+    void prepareFromMediaId(String packageName, ISessionControllerCallback caller,
+            String mediaId, in Bundle extras);
+    void prepareFromSearch(String packageName, ISessionControllerCallback caller,
+            String string, in Bundle extras);
+    void prepareFromUri(String packageName, ISessionControllerCallback caller,
+            in Uri uri, in Bundle extras);
+    void play(String packageName, ISessionControllerCallback caller);
+    void playFromMediaId(String packageName, ISessionControllerCallback caller,
+            String mediaId, in Bundle extras);
+    void playFromSearch(String packageName, ISessionControllerCallback caller,
+            String string, in Bundle extras);
+    void playFromUri(String packageName, ISessionControllerCallback caller,
+            in Uri uri, in Bundle extras);
+    void skipToQueueItem(String packageName, ISessionControllerCallback caller, long id);
+    void pause(String packageName, ISessionControllerCallback caller);
+    void stop(String packageName, ISessionControllerCallback caller);
+    void next(String packageName, ISessionControllerCallback caller);
+    void previous(String packageName, ISessionControllerCallback caller);
+    void fastForward(String packageName, ISessionControllerCallback caller);
+    void rewind(String packageName, ISessionControllerCallback caller);
+    void seekTo(String packageName, ISessionControllerCallback caller, long pos);
+    void rate(String packageName, ISessionControllerCallback caller, in Rating rating);
+    void sendCustomAction(String packageName, ISessionControllerCallback caller,
+            String action, in Bundle args);
     MediaMetadata getMetadata();
     PlaybackState getPlaybackState();
     ParceledListSlice getQueue();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 8c34a31..de22fa3 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -126,7 +126,7 @@
      * @return true if the event was sent to the session, false otherwise.
      */
     public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) {
-        return dispatchMediButtonEventInternal(false, keyEvent);
+        return dispatchMediaButtonEventInternal(false, keyEvent);
     }
 
     /**
@@ -142,10 +142,10 @@
      * @hide
      */
     public boolean dispatchMediaButtonEventAsSystemService(@NonNull KeyEvent keyEvent) {
-        return dispatchMediButtonEventInternal(true, keyEvent);
+        return dispatchMediaButtonEventInternal(true, keyEvent);
     }
 
-    private boolean dispatchMediButtonEventInternal(boolean asSystemService,
+    private boolean dispatchMediaButtonEventInternal(boolean asSystemService,
             @NonNull KeyEvent keyEvent) {
         if (keyEvent == null) {
             throw new IllegalArgumentException("KeyEvent may not be null");
@@ -154,8 +154,8 @@
             return false;
         }
         try {
-            return mSessionBinder.sendMediaButton(mContext.getPackageName(), asSystemService,
-                    keyEvent);
+            return mSessionBinder.sendMediaButton(mContext.getPackageName(), mCbStub,
+                    asSystemService, keyEvent);
         } catch (RemoteException e) {
             // System is dead. =(
         }
@@ -189,7 +189,7 @@
                         break;
                 }
                 try {
-                    mSessionBinder.adjustVolume(mContext.getPackageName(), true, direction,
+                    mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, true, direction,
                             AudioManager.FLAG_SHOW_UI);
                 } catch (RemoteException e) {
                     Log.wtf(TAG, "Error calling adjustVolumeBy", e);
@@ -200,7 +200,7 @@
                 final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
                         | AudioManager.FLAG_FROM_KEY;
                 try {
-                    mSessionBinder.adjustVolume(mContext.getPackageName(), true, 0, flags);
+                    mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, true, 0, flags);
                 } catch (RemoteException e) {
                     Log.wtf(TAG, "Error calling adjustVolumeBy", e);
                 }
@@ -369,7 +369,7 @@
      */
     public void setVolumeTo(int value, int flags) {
         try {
-            mSessionBinder.setVolumeTo(mContext.getPackageName(), value, flags);
+            mSessionBinder.setVolumeTo(mContext.getPackageName(), mCbStub, value, flags);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling setVolumeTo.", e);
         }
@@ -390,7 +390,8 @@
      */
     public void adjustVolume(int direction, int flags) {
         try {
-            mSessionBinder.adjustVolume(mContext.getPackageName(), false, direction, flags);
+            mSessionBinder.adjustVolume(mContext.getPackageName(), mCbStub, false, direction,
+                    flags);
         } catch (RemoteException e) {
             Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
         }
@@ -456,7 +457,7 @@
             throw new IllegalArgumentException("command cannot be null or empty");
         }
         try {
-            mSessionBinder.sendCommand(mContext.getPackageName(), command, args, cb);
+            mSessionBinder.sendCommand(mContext.getPackageName(), mCbStub, command, args, cb);
         } catch (RemoteException e) {
             Log.d(TAG, "Dead object in sendCommand.", e);
         }
@@ -521,7 +522,7 @@
 
         if (!mCbRegistered) {
             try {
-                mSessionBinder.registerCallbackListener(mCbStub);
+                mSessionBinder.registerCallbackListener(mContext.getPackageName(), mCbStub);
                 mCbRegistered = true;
             } catch (RemoteException e) {
                 Log.e(TAG, "Dead object in registerCallback", e);
@@ -668,7 +669,7 @@
          */
         public void prepare() {
             try {
-                mSessionBinder.prepare(mContext.getPackageName());
+                mSessionBinder.prepare(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare.", e);
             }
@@ -692,7 +693,8 @@
                         "You must specify a non-empty String for prepareFromMediaId.");
             }
             try {
-                mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mediaId, extras);
+                mSessionBinder.prepareFromMediaId(mContext.getPackageName(), mCbStub, mediaId,
+                        extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + mediaId + ").", e);
             }
@@ -718,7 +720,7 @@
                 query = "";
             }
             try {
-                mSessionBinder.prepareFromSearch(mContext.getPackageName(), query, extras);
+                mSessionBinder.prepareFromSearch(mContext.getPackageName(), mCbStub, query, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + query + ").", e);
             }
@@ -742,7 +744,7 @@
                         "You must specify a non-empty Uri for prepareFromUri.");
             }
             try {
-                mSessionBinder.prepareFromUri(mContext.getPackageName(), uri, extras);
+                mSessionBinder.prepareFromUri(mContext.getPackageName(), mCbStub, uri, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling prepare(" + uri + ").", e);
             }
@@ -753,7 +755,7 @@
          */
         public void play() {
             try {
-                mSessionBinder.play(mContext.getPackageName());
+                mSessionBinder.play(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play.", e);
             }
@@ -772,7 +774,7 @@
                         "You must specify a non-empty String for playFromMediaId.");
             }
             try {
-                mSessionBinder.playFromMediaId(mContext.getPackageName(), mediaId, extras);
+                mSessionBinder.playFromMediaId(mContext.getPackageName(), mCbStub, mediaId, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + mediaId + ").", e);
             }
@@ -794,7 +796,7 @@
                 query = "";
             }
             try {
-                mSessionBinder.playFromSearch(mContext.getPackageName(), query, extras);
+                mSessionBinder.playFromSearch(mContext.getPackageName(), mCbStub, query, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + query + ").", e);
             }
@@ -813,7 +815,7 @@
                         "You must specify a non-empty Uri for playFromUri.");
             }
             try {
-                mSessionBinder.playFromUri(mContext.getPackageName(), uri, extras);
+                mSessionBinder.playFromUri(mContext.getPackageName(), mCbStub, uri, extras);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling play(" + uri + ").", e);
             }
@@ -825,7 +827,7 @@
          */
         public void skipToQueueItem(long id) {
             try {
-                mSessionBinder.skipToQueueItem(mContext.getPackageName(), id);
+                mSessionBinder.skipToQueueItem(mContext.getPackageName(), mCbStub, id);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e);
             }
@@ -837,7 +839,7 @@
          */
         public void pause() {
             try {
-                mSessionBinder.pause(mContext.getPackageName());
+                mSessionBinder.pause(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling pause.", e);
             }
@@ -849,7 +851,7 @@
          */
         public void stop() {
             try {
-                mSessionBinder.stop(mContext.getPackageName());
+                mSessionBinder.stop(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling stop.", e);
             }
@@ -862,7 +864,7 @@
          */
         public void seekTo(long pos) {
             try {
-                mSessionBinder.seekTo(mContext.getPackageName(), pos);
+                mSessionBinder.seekTo(mContext.getPackageName(), mCbStub, pos);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling seekTo.", e);
             }
@@ -874,7 +876,7 @@
          */
         public void fastForward() {
             try {
-                mSessionBinder.fastForward(mContext.getPackageName());
+                mSessionBinder.fastForward(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling fastForward.", e);
             }
@@ -885,7 +887,7 @@
          */
         public void skipToNext() {
             try {
-                mSessionBinder.next(mContext.getPackageName());
+                mSessionBinder.next(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling next.", e);
             }
@@ -897,7 +899,7 @@
          */
         public void rewind() {
             try {
-                mSessionBinder.rewind(mContext.getPackageName());
+                mSessionBinder.rewind(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling rewind.", e);
             }
@@ -908,7 +910,7 @@
          */
         public void skipToPrevious() {
             try {
-                mSessionBinder.previous(mContext.getPackageName());
+                mSessionBinder.previous(mContext.getPackageName(), mCbStub);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling previous.", e);
             }
@@ -923,7 +925,7 @@
          */
         public void setRating(Rating rating) {
             try {
-                mSessionBinder.rate(mContext.getPackageName(), rating);
+                mSessionBinder.rate(mContext.getPackageName(), mCbStub, rating);
             } catch (RemoteException e) {
                 Log.wtf(TAG, "Error calling rate.", e);
             }
@@ -937,7 +939,7 @@
          *             custom action.
          */
         public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction,
-                    @Nullable Bundle args) {
+                @Nullable Bundle args) {
             if (customAction == null) {
                 throw new IllegalArgumentException("CustomAction cannot be null.");
             }
@@ -958,7 +960,7 @@
                 throw new IllegalArgumentException("CustomAction cannot be null.");
             }
             try {
-                mSessionBinder.sendCustomAction(mContext.getPackageName(), action, args);
+                mSessionBinder.sendCustomAction(mContext.getPackageName(), mCbStub, action, args);
             } catch (RemoteException e) {
                 Log.d(TAG, "Dead object in sendCustomAction.", e);
             }
@@ -1124,8 +1126,8 @@
         public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) {
             MediaController controller = mController.get();
             if (controller != null) {
-                PlaybackInfo info = new PlaybackInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType,
-                        pvi.maxVolume, pvi.currentVolume);
+                PlaybackInfo info = new PlaybackInfo(pvi.volumeType, pvi.audioAttrs,
+                        pvi.controlType, pvi.maxVolume, pvi.currentVolume);
                 controller.postMessage(MSG_UPDATE_VOLUME, info, null);
             }
         }
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 6f4f20e..fad7e3f 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -43,6 +43,7 @@
 import android.service.media.MediaBrowserService;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 import android.view.KeyEvent;
 import android.view.ViewConfiguration;
 
@@ -122,15 +123,6 @@
             FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
     public @interface SessionFlags { }
 
-    private static final String EXTRA_KEY_CALLING_PACKAGE =
-            "android.media.session.extra.CALLING_PACKAGE";
-    private static final String EXTRA_KEY_CALLING_PID =
-            "android.media.session.extra.CALLING_PID";
-    private static final String EXTRA_KEY_CALLING_UID =
-            "android.media.session.extra.CALLING_UID";
-    private static final String EXTRA_KEY_ORIGINAL_BUNDLE =
-            "android.media.session.extra.ORIGINAL_BUNDLE";
-
     private final Object mLock = new Object();
     private final int mMaxBitmapSize;
 
@@ -529,15 +521,11 @@
      * @see MediaSessionManager#isTrustedForMediaControl(RemoteUserInfo)
      */
     public final @NonNull RemoteUserInfo getCurrentControllerInfo() {
-        return createRemoteUserInfo(getCurrentData());
-    }
-
-    private @NonNull Bundle getCurrentData() {
-        if (mCallback == null || mCallback.mCurrentData == null) {
+        if (mCallback == null || mCallback.mCurrentControllerInfo == null) {
             throw new IllegalStateException(
                     "This should be called inside of MediaSession.Callback methods");
         }
-        return mCallback.mCurrentData;
+        return mCallback.mCurrentControllerInfo;
     }
 
     /**
@@ -568,161 +556,122 @@
      * @hide
      */
     public String getCallingPackage() {
-        if (mCallback != null) {
-            return createRemoteUserInfo(mCallback.mCurrentData).getPackageName();
+        if (mCallback != null && mCallback.mCurrentControllerInfo != null) {
+            return mCallback.mCurrentControllerInfo.getPackageName();
         }
         return null;
     }
 
-    private void dispatchPrepare(Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PREPARE, null, extras);
+    private void dispatchPrepare(RemoteUserInfo caller) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PREPARE, null, null);
     }
 
-    private void dispatchPrepareFromMediaId(String mediaId, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras);
+    private void dispatchPrepareFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_MEDIA_ID, mediaId, extras);
     }
 
-    private void dispatchPrepareFromSearch(String query, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras);
+    private void dispatchPrepareFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_SEARCH, query, extras);
     }
 
-    private void dispatchPrepareFromUri(Uri uri, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PREPARE_URI, uri, extras);
+    private void dispatchPrepareFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PREPARE_URI, uri, extras);
     }
 
-    private void dispatchPlay(Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PLAY, null, extras);
+    private void dispatchPlay(RemoteUserInfo caller) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PLAY, null, null);
     }
 
-    private void dispatchPlayFromMediaId(String mediaId, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras);
+    private void dispatchPlayFromMediaId(RemoteUserInfo caller, String mediaId, Bundle extras) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras);
     }
 
-    private void dispatchPlayFromSearch(String query, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras);
+    private void dispatchPlayFromSearch(RemoteUserInfo caller, String query, Bundle extras) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PLAY_SEARCH, query, extras);
     }
 
-    private void dispatchPlayFromUri(Uri uri, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PLAY_URI, uri, extras);
+    private void dispatchPlayFromUri(RemoteUserInfo caller, Uri uri, Bundle extras) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PLAY_URI, uri, extras);
     }
 
-    private void dispatchSkipToItem(long id, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_SKIP_TO_ITEM, id, extras);
+    private void dispatchSkipToItem(RemoteUserInfo caller, long id) {
+        postToCallback(caller, CallbackMessageHandler.MSG_SKIP_TO_ITEM, id, null);
     }
 
-    private void dispatchPause(Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PAUSE, null, extras);
+    private void dispatchPause(RemoteUserInfo caller) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PAUSE, null, null);
     }
 
-    private void dispatchStop(Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_STOP, null, extras);
+    private void dispatchStop(RemoteUserInfo caller) {
+        postToCallback(caller, CallbackMessageHandler.MSG_STOP, null, null);
     }
 
-    private void dispatchNext(Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_NEXT, null, extras);
+    private void dispatchNext(RemoteUserInfo caller) {
+        postToCallback(caller, CallbackMessageHandler.MSG_NEXT, null, null);
     }
 
-    private void dispatchPrevious(Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_PREVIOUS, null, extras);
+    private void dispatchPrevious(RemoteUserInfo caller) {
+        postToCallback(caller, CallbackMessageHandler.MSG_PREVIOUS, null, null);
     }
 
-    private void dispatchFastForward(Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_FAST_FORWARD, null, extras);
+    private void dispatchFastForward(RemoteUserInfo caller) {
+        postToCallback(caller, CallbackMessageHandler.MSG_FAST_FORWARD, null, null);
     }
 
-    private void dispatchRewind(Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_REWIND, null, extras);
+    private void dispatchRewind(RemoteUserInfo caller) {
+        postToCallback(caller, CallbackMessageHandler.MSG_REWIND, null, null);
     }
 
-    private void dispatchSeekTo(long pos, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_SEEK_TO, pos, extras);
+    private void dispatchSeekTo(RemoteUserInfo caller, long pos) {
+        postToCallback(caller, CallbackMessageHandler.MSG_SEEK_TO, pos, null);
     }
 
-    private void dispatchRate(Rating rating, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_RATE, rating, extras);
+    private void dispatchRate(RemoteUserInfo caller, Rating rating) {
+        postToCallback(caller, CallbackMessageHandler.MSG_RATE, rating, null);
     }
 
-    private void dispatchCustomAction(String action, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_CUSTOM_ACTION, action, extras);
+    private void dispatchCustomAction(RemoteUserInfo caller, String action, Bundle args) {
+        postToCallback(caller, CallbackMessageHandler.MSG_CUSTOM_ACTION, action, args);
     }
 
-    private void dispatchMediaButton(Intent mediaButtonIntent, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent, extras);
+    private void dispatchMediaButton(RemoteUserInfo caller, Intent mediaButtonIntent) {
+        postToCallback(caller, CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent, null);
     }
 
-    private void dispatchAdjustVolume(int direction, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_ADJUST_VOLUME, direction, extras);
+    private void dispatchMediaButtonDelayed(RemoteUserInfo info, Intent mediaButtonIntent,
+            long delay) {
+        postToCallbackDelayed(info, CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
+                mediaButtonIntent, null, delay);
     }
 
-    private void dispatchSetVolumeTo(int volume, Bundle extras) {
-        postToCallback(CallbackMessageHandler.MSG_SET_VOLUME, volume, extras);
+    private void dispatchAdjustVolume(RemoteUserInfo caller, int direction) {
+        postToCallback(caller, CallbackMessageHandler.MSG_ADJUST_VOLUME, direction, null);
     }
 
-    private void postCommand(String command, Bundle args, ResultReceiver resultCb, Bundle extras) {
+    private void dispatchSetVolumeTo(RemoteUserInfo caller, int volume) {
+        postToCallback(caller, CallbackMessageHandler.MSG_SET_VOLUME, volume, null);
+    }
+
+    private void dispatchCommand(RemoteUserInfo caller, String command, Bundle args,
+            ResultReceiver resultCb) {
         Command cmd = new Command(command, args, resultCb);
-        postToCallback(CallbackMessageHandler.MSG_COMMAND, cmd, extras);
+        postToCallback(caller, CallbackMessageHandler.MSG_COMMAND, cmd, null);
     }
 
-    private void postToCallback(int what, Object obj, Bundle extras) {
+    private void postToCallback(RemoteUserInfo caller, int what, Object obj, Bundle data) {
+        postToCallbackDelayed(caller, what, obj, data, 0);
+    }
+
+    private void postToCallbackDelayed(RemoteUserInfo caller, int what, Object obj, Bundle data,
+            long delay) {
         synchronized (mLock) {
             if (mCallback != null) {
-                mCallback.post(what, obj, extras);
+                mCallback.post(caller, what, obj, data, delay);
             }
         }
     }
 
     /**
-     * Creates the extra bundle that includes the caller information.
-     *
-     * @return An extraBundle that contains caller information
-     */
-    private static Bundle createExtraBundle(String packageName, int pid, int uid) {
-        return createExtraBundle(packageName, pid, uid, null);
-    }
-
-    /**
-     * Creates the extra bundle that includes the caller information.
-     *
-     * @param originalBundle bundle
-     * @return An extraBundle that contains caller information
-     */
-    private static Bundle createExtraBundle(String packageName, int pid, int uid,
-            Bundle originalBundle) {
-        Bundle bundle = new Bundle();
-        bundle.putString(EXTRA_KEY_CALLING_PACKAGE, packageName);
-        bundle.putInt(EXTRA_KEY_CALLING_PID, pid);
-        bundle.putInt(EXTRA_KEY_CALLING_UID, uid);
-        if (originalBundle != null) {
-            bundle.putBundle(EXTRA_KEY_ORIGINAL_BUNDLE, originalBundle);
-        }
-        return bundle;
-    }
-
-    /**
-     * Creates the {@link RemoteUserInfo} from the extra bundle created by
-     * {@link #createExtraBundle}.
-     *
-     * @param extraBundle that previously created by createExtraBundle()
-     * @return a RemoteUserInfo
-     */
-    private static RemoteUserInfo createRemoteUserInfo(Bundle extraBundle) {
-        return new RemoteUserInfo(
-                extraBundle.getString(EXTRA_KEY_CALLING_PACKAGE),
-                extraBundle.getInt(EXTRA_KEY_CALLING_PID, INVALID_PID),
-                extraBundle.getInt(EXTRA_KEY_CALLING_UID, INVALID_UID));
-    }
-
-    /**
-     * Gets the original bundle from the extra bundle created by {@link #createExtraBundle}.
-     *
-     * @param extraBundle that previously created by createExtraBundle()
-     * @return a Bundle
-     */
-    private static Bundle getOriginalBundle(Bundle extraBundle) {
-        return extraBundle.getBundle(EXTRA_KEY_ORIGINAL_BUNDLE);
-    }
-
-    /**
      * Return true if this is considered an active playback state.
      *
      * @hide
@@ -872,10 +821,9 @@
                                 }
                             } else {
                                 mMediaPlayPauseKeyPending = true;
-                                mHandler.postDelayed(CallbackMessageHandler
-                                                .MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
-                                        mSession.getCurrentData(),
-                                        ViewConfiguration.getDoubleTapTimeout());
+                                mSession.dispatchMediaButtonDelayed(
+                                        mSession.getCurrentControllerInfo(),
+                                        mediaButtonIntent, ViewConfiguration.getDoubleTapTimeout());
                             }
                             return true;
                         default:
@@ -1109,12 +1057,19 @@
             mMediaSession = new WeakReference<>(session);
         }
 
+        private static RemoteUserInfo createRemoteUserInfo(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
+            return new RemoteUserInfo(packageName, pid, uid,
+                    caller != null ? caller.asBinder() : null);
+        }
+
         @Override
-        public void onCommand(String packageName, int pid, int uid, String command, Bundle args,
-                ResultReceiver cb) {
+        public void onCommand(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String command, Bundle args, ResultReceiver cb) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.postCommand(command, args, cb, createExtraBundle(packageName, pid, uid));
+                session.dispatchCommand(createRemoteUserInfo(packageName, pid, uid, caller),
+                        command, args, cb);
             }
         }
 
@@ -1124,8 +1079,8 @@
             MediaSession session = mMediaSession.get();
             try {
                 if (session != null) {
-                    session.dispatchMediaButton(
-                            mediaButtonIntent, createExtraBundle(packageName, pid, uid));
+                    session.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid, null),
+                            mediaButtonIntent);
                 }
             } finally {
                 if (cb != null) {
@@ -1135,173 +1090,205 @@
         }
 
         @Override
-        public void onPrepare(String packageName, int pid, int uid) {
+        public void onMediaButtonFromController(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, Intent mediaButtonIntent) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPrepare(createExtraBundle(packageName, pid, uid));
+                session.dispatchMediaButton(createRemoteUserInfo(packageName, pid, uid, caller),
+                        mediaButtonIntent);
             }
         }
 
         @Override
-        public void onPrepareFromMediaId(String packageName, int pid, int uid, String mediaId,
+        public void onPrepare(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
+            MediaSession session = mMediaSession.get();
+            if (session != null) {
+                session.dispatchPrepare(createRemoteUserInfo(packageName, pid, uid, caller));
+            }
+        }
+
+        @Override
+        public void onPrepareFromMediaId(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String mediaId,
                 Bundle extras) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
                 session.dispatchPrepareFromMediaId(
-                        mediaId, createExtraBundle(packageName, pid, uid, extras));
+                        createRemoteUserInfo(packageName, pid, uid, caller), mediaId, extras);
             }
         }
 
         @Override
-        public void onPrepareFromSearch(String packageName, int pid, int uid, String query,
+        public void onPrepareFromSearch(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String query,
                 Bundle extras) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
                 session.dispatchPrepareFromSearch(
-                        query, createExtraBundle(packageName, pid, uid, extras));
+                        createRemoteUserInfo(packageName, pid, uid, caller), query, extras);
             }
         }
 
         @Override
-        public void onPrepareFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
+        public void onPrepareFromUri(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, Uri uri, Bundle extras) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPrepareFromUri(uri,
-                        createExtraBundle(packageName, pid, uid, extras));
+                session.dispatchPrepareFromUri(createRemoteUserInfo(packageName, pid, uid, caller),
+                        uri, extras);
             }
         }
 
         @Override
-        public void onPlay(String packageName, int pid, int uid) {
+        public void onPlay(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPlay(createExtraBundle(packageName, pid, uid));
+                session.dispatchPlay(createRemoteUserInfo(packageName, pid, uid, caller));
             }
         }
 
         @Override
-        public void onPlayFromMediaId(String packageName, int pid, int uid, String mediaId,
+        public void onPlayFromMediaId(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String mediaId,
                 Bundle extras) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPlayFromMediaId(
-                        mediaId, createExtraBundle(packageName, pid, uid, extras));
+                session.dispatchPlayFromMediaId(createRemoteUserInfo(packageName, pid, uid, caller),
+                        mediaId, extras);
             }
         }
 
         @Override
-        public void onPlayFromSearch(String packageName, int pid, int uid, String query,
+        public void onPlayFromSearch(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String query,
                 Bundle extras) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPlayFromSearch(query, createExtraBundle(packageName, pid, uid,
-                        extras));
+                session.dispatchPlayFromSearch(createRemoteUserInfo(packageName, pid, uid, caller),
+                        query, extras);
             }
         }
 
         @Override
-        public void onPlayFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
+        public void onPlayFromUri(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, Uri uri, Bundle extras) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPlayFromUri(uri, createExtraBundle(packageName, pid, uid, extras));
+                session.dispatchPlayFromUri(createRemoteUserInfo(packageName, pid, uid, caller),
+                        uri, extras);
             }
         }
 
         @Override
-        public void onSkipToTrack(String packageName, int pid, int uid, long id) {
+        public void onSkipToTrack(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, long id) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchSkipToItem(id, createExtraBundle(packageName, pid, uid));
+                session.dispatchSkipToItem(createRemoteUserInfo(packageName, pid, uid, caller), id);
             }
         }
 
         @Override
-        public void onPause(String packageName, int pid, int uid) {
+        public void onPause(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPause(createExtraBundle(packageName, pid, uid));
+                session.dispatchPause(createRemoteUserInfo(packageName, pid, uid, caller));
             }
         }
 
         @Override
-        public void onStop(String packageName, int pid, int uid) {
+        public void onStop(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchStop(createExtraBundle(packageName, pid, uid));
+                session.dispatchStop(createRemoteUserInfo(packageName, pid, uid, caller));
             }
         }
 
         @Override
-        public void onNext(String packageName, int pid, int uid) {
+        public void onNext(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchNext(createExtraBundle(packageName, pid, uid));
+                session.dispatchNext(createRemoteUserInfo(packageName, pid, uid, caller));
             }
         }
 
         @Override
-        public void onPrevious(String packageName, int pid, int uid) {
+        public void onPrevious(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchPrevious(createExtraBundle(packageName, pid, uid));
+                session.dispatchPrevious(createRemoteUserInfo(packageName, pid, uid, caller));
             }
         }
 
         @Override
-        public void onFastForward(String packageName, int pid, int uid) {
+        public void onFastForward(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchFastForward(createExtraBundle(packageName, pid, uid));
+                session.dispatchFastForward(createRemoteUserInfo(packageName, pid, uid, caller));
             }
         }
 
         @Override
-        public void onRewind(String packageName, int pid, int uid) {
+        public void onRewind(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchRewind(createExtraBundle(packageName, pid, uid));
+                session.dispatchRewind(createRemoteUserInfo(packageName, pid, uid, caller));
             }
         }
 
         @Override
-        public void onSeekTo(String packageName, int pid, int uid, long pos) {
+        public void onSeekTo(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, long pos) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchSeekTo(pos, createExtraBundle(packageName, pid, uid));
+                session.dispatchSeekTo(createRemoteUserInfo(packageName, pid, uid, caller), pos);
             }
         }
 
         @Override
-        public void onRate(String packageName, int pid, int uid, Rating rating) {
+        public void onRate(String packageName, int pid, int uid, ISessionControllerCallback caller,
+                Rating rating) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchRate(rating, createExtraBundle(packageName, pid, uid));
+                session.dispatchRate(createRemoteUserInfo(packageName, pid, uid, caller), rating);
             }
         }
 
         @Override
-        public void onCustomAction(String packageName, int pid, int uid, String action,
-                Bundle args) {
+        public void onCustomAction(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String action, Bundle args) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchCustomAction(
-                        action, createExtraBundle(packageName, pid, uid, args));
+                session.dispatchCustomAction(createRemoteUserInfo(packageName, pid, uid, caller),
+                        action, args);
             }
         }
 
         @Override
-        public void onAdjustVolume(String packageName, int pid, int uid, int direction) {
+        public void onAdjustVolume(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, int direction) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchAdjustVolume(direction, createExtraBundle(packageName, pid, uid));
+                session.dispatchAdjustVolume(createRemoteUserInfo(packageName, pid, uid, caller),
+                        direction);
             }
         }
 
         @Override
-        public void onSetVolumeTo(String packageName, int pid, int uid, int value) {
+        public void onSetVolumeTo(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, int value) {
             MediaSession session = mMediaSession.get();
             if (session != null) {
-                session.dispatchSetVolumeTo(value, createExtraBundle(packageName, pid, uid));
+                session.dispatchSetVolumeTo(createRemoteUserInfo(packageName, pid, uid, caller),
+                        value);
             }
         }
     }
@@ -1424,7 +1411,6 @@
     }
 
     private class CallbackMessageHandler extends Handler {
-
         private static final int MSG_COMMAND = 1;
         private static final int MSG_MEDIA_BUTTON = 2;
         private static final int MSG_PREPARE = 3;
@@ -1450,7 +1436,7 @@
         private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 23;
 
         private MediaSession.Callback mCallback;
-        private Bundle mCurrentData;
+        private RemoteUserInfo mCurrentControllerInfo;
 
         public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
             super(looper, null, true);
@@ -1458,60 +1444,58 @@
             mCallback.mHandler = this;
         }
 
-        public void post(int what, Object obj, Bundle data) {
-            Message msg = obtainMessage(what, obj);
+        public void post(RemoteUserInfo caller, int what, Object obj, Bundle data, long delayMs) {
+            Pair<RemoteUserInfo, Object> objWithCaller = Pair.create(caller, obj);
+            Message msg = obtainMessage(what, objWithCaller);
             msg.setData(data);
-            msg.sendToTarget();
-        }
-
-        public void postDelayed(int what, Bundle data, long delayMs) {
-            Message msg = obtainMessage(what);
-            msg.setData(data);
-            sendMessageDelayed(msg, delayMs);
+            if (delayMs > 0) {
+                sendMessageDelayed(msg, delayMs);
+            } else {
+                sendMessage(msg);
+            }
         }
 
         @Override
         public void handleMessage(Message msg) {
-            VolumeProvider vp;
-            Bundle data = msg.getData();
-            Bundle originalBundle = getOriginalBundle(data);
+            mCurrentControllerInfo = ((Pair<RemoteUserInfo, Object>) msg.obj).first;
 
-            mCurrentData = data;
+            VolumeProvider vp;
+            Object obj = ((Pair<RemoteUserInfo, Object>) msg.obj).second;
 
             switch (msg.what) {
                 case MSG_COMMAND:
-                    Command cmd = (Command) msg.obj;
+                    Command cmd = (Command) obj;
                     mCallback.onCommand(cmd.command, cmd.extras, cmd.stub);
                     break;
                 case MSG_MEDIA_BUTTON:
-                    mCallback.onMediaButtonEvent((Intent) msg.obj);
+                    mCallback.onMediaButtonEvent((Intent) obj);
                     break;
                 case MSG_PREPARE:
                     mCallback.onPrepare();
                     break;
                 case MSG_PREPARE_MEDIA_ID:
-                    mCallback.onPrepareFromMediaId((String) msg.obj, originalBundle);
+                    mCallback.onPrepareFromMediaId((String) obj, msg.getData());
                     break;
                 case MSG_PREPARE_SEARCH:
-                    mCallback.onPrepareFromSearch((String) msg.obj, originalBundle);
+                    mCallback.onPrepareFromSearch((String) obj, msg.getData());
                     break;
                 case MSG_PREPARE_URI:
-                    mCallback.onPrepareFromUri((Uri) msg.obj, originalBundle);
+                    mCallback.onPrepareFromUri((Uri) obj, msg.getData());
                     break;
                 case MSG_PLAY:
                     mCallback.onPlay();
                     break;
                 case MSG_PLAY_MEDIA_ID:
-                    mCallback.onPlayFromMediaId((String) msg.obj, originalBundle);
+                    mCallback.onPlayFromMediaId((String) obj, msg.getData());
                     break;
                 case MSG_PLAY_SEARCH:
-                    mCallback.onPlayFromSearch((String) msg.obj, originalBundle);
+                    mCallback.onPlayFromSearch((String) obj, msg.getData());
                     break;
                 case MSG_PLAY_URI:
-                    mCallback.onPlayFromUri((Uri) msg.obj, originalBundle);
+                    mCallback.onPlayFromUri((Uri) obj, msg.getData());
                     break;
                 case MSG_SKIP_TO_ITEM:
-                    mCallback.onSkipToQueueItem((Long) msg.obj);
+                    mCallback.onSkipToQueueItem((Long) obj);
                     break;
                 case MSG_PAUSE:
                     mCallback.onPause();
@@ -1532,20 +1516,20 @@
                     mCallback.onRewind();
                     break;
                 case MSG_SEEK_TO:
-                    mCallback.onSeekTo((Long) msg.obj);
+                    mCallback.onSeekTo((Long) obj);
                     break;
                 case MSG_RATE:
-                    mCallback.onSetRating((Rating) msg.obj);
+                    mCallback.onSetRating((Rating) obj);
                     break;
                 case MSG_CUSTOM_ACTION:
-                    mCallback.onCustomAction((String) msg.obj, originalBundle);
+                    mCallback.onCustomAction((String) obj, msg.getData());
                     break;
                 case MSG_ADJUST_VOLUME:
                     synchronized (mLock) {
                         vp = mVolumeProvider;
                     }
                     if (vp != null) {
-                        vp.onAdjustVolume((int) msg.obj);
+                        vp.onAdjustVolume((int) obj);
                     }
                     break;
                 case MSG_SET_VOLUME:
@@ -1553,14 +1537,14 @@
                         vp = mVolumeProvider;
                     }
                     if (vp != null) {
-                        vp.onSetVolumeTo((int) msg.obj);
+                        vp.onSetVolumeTo((int) obj);
                     }
                     break;
                 case MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT:
                     mCallback.handleMediaPlayPauseKeySingleTapIfPending();
                     break;
             }
-            mCurrentData = null;
+            mCurrentControllerInfo = null;
         }
     }
 }
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index f54bfc1..3f0b6c5 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -30,6 +30,7 @@
 import android.media.MediaSession2;
 import android.media.MediaSessionService2;
 import android.media.SessionToken2;
+import android.media.browse.MediaBrowser;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -818,19 +819,31 @@
 
     /**
      * Information of a remote user of {@link MediaSession} or {@link MediaBrowserService}.
-     * This can be used to decide whether the remote user is trusted app.
+     * This can be used to decide whether the remote user is trusted app, and also differentiate
+     * caller of {@link MediaSession} and {@link MediaBrowserService} callbacks.
+     * <p>
+     * See {@link #equals(Object)} to take a look at how it differentiate media controller.
      *
      * @see #isTrustedForMediaControl(RemoteUserInfo)
      */
     public static final class RemoteUserInfo {
-        private String mPackageName;
-        private int mPid;
-        private int mUid;
+        private final String mPackageName;
+        private final int mPid;
+        private final int mUid;
+        private final IBinder mCallerBinder;
 
-        public RemoteUserInfo(String packageName, int pid, int uid) {
+        public RemoteUserInfo(@NonNull String packageName, int pid, int uid) {
+            this(packageName, pid, uid, null);
+        }
+
+        /**
+         * @hide
+         */
+        public RemoteUserInfo(String packageName, int pid, int uid, IBinder callerBinder) {
             mPackageName = packageName;
             mPid = pid;
             mUid = uid;
+            mCallerBinder = callerBinder;
         }
 
         /**
@@ -854,15 +867,29 @@
             return mUid;
         }
 
+        /**
+         * Returns equality of two RemoteUserInfo. Two RemoteUserInfos are the same only if they're
+         * sent to the same controller (either {@link MediaController} or
+         * {@link MediaBrowser}. If it's not nor one of them is triggered by the key presses, they
+         * would be considered as different one.
+         * <p>
+         * If you only want to compare the caller's package, compare them with the
+         * {@link #getPackageName()}, {@link #getPid()}, and/or {@link #getUid()} directly.
+         *
+         * @param obj the reference object with which to compare.
+         * @return {@code true} if equals, {@code false} otherwise
+         */
         @Override
         public boolean equals(Object obj) {
             if (!(obj instanceof RemoteUserInfo)) {
                 return false;
             }
+            if (this == obj) {
+                return true;
+            }
             RemoteUserInfo otherUserInfo = (RemoteUserInfo) obj;
-            return TextUtils.equals(mPackageName, otherUserInfo.mPackageName)
-                    && mPid == otherUserInfo.mPid
-                    && mUid == otherUserInfo.mUid;
+            return (mCallerBinder == null || otherUserInfo.mCallerBinder == null) ? false
+                    : mCallerBinder.equals(otherUserInfo.mCallerBinder);
         }
 
         @Override
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 11659e4..f8f7a90 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -25,11 +25,14 @@
 #include <gui/Surface.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <private/android/AHardwareBufferHelpers.h>
 #include <jni.h>
 #include <nativehelper/JNIHelp.h>
 
 #include <stdint.h>
 #include <inttypes.h>
+#include <android/hardware_buffer_jni.h>
 
 #define IMAGE_BUFFER_JNI_ID           "mNativeBuffer"
 #define IMAGE_FORMAT_UNKNOWN          0 // This is the same value as ImageFormat#UNKNOWN.
@@ -701,6 +704,20 @@
     return static_cast<jint>(publicFmt);
 }
 
+static jobject Image_getHardwareBuffer(JNIEnv* env, jobject thiz) {
+    GraphicBuffer* buffer;
+    Image_getNativeContext(env, thiz, &buffer, NULL);
+    if (buffer == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+                "Image is not initialized");
+        return NULL;
+    }
+    AHardwareBuffer* b = AHardwareBuffer_from_GraphicBuffer(buffer);
+    // don't user the public AHardwareBuffer_toHardwareBuffer() because this would force us
+    // to link against libandroid.so
+    return android_hardware_HardwareBuffer_createFromAHardwareBuffer(env, b);
+}
+
 static void Image_setFenceFd(JNIEnv* env, jobject thiz, int fenceFd) {
     ALOGV("%s:", __FUNCTION__);
     env->SetIntField(thiz, gSurfaceImageClassInfo.mNativeFenceFd, reinterpret_cast<jint>(fenceFd));
@@ -818,10 +835,12 @@
 
 static JNINativeMethod gImageMethods[] = {
     {"nativeCreatePlanes",      "(II)[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;",
-                                                              (void*)Image_createSurfacePlanes },
-    {"nativeGetWidth",         "()I",                         (void*)Image_getWidth },
-    {"nativeGetHeight",        "()I",                         (void*)Image_getHeight },
-    {"nativeGetFormat",        "()I",                         (void*)Image_getFormat },
+                                                               (void*)Image_createSurfacePlanes },
+    {"nativeGetWidth",          "()I",                         (void*)Image_getWidth },
+    {"nativeGetHeight",         "()I",                         (void*)Image_getHeight },
+    {"nativeGetFormat",         "()I",                         (void*)Image_getFormat },
+    {"nativeGetHardwareBuffer", "()Landroid/hardware/HardwareBuffer;",
+                                                               (void*)Image_getHardwareBuffer },
 };
 
 int register_android_media_ImageWriter(JNIEnv *env) {
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 91c04fa..3630005 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -16,6 +16,9 @@
 
 package com.android.captiveportallogin;
 
+import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
+import static android.net.captiveportal.CaptivePortalProbeSpec.HTTP_LOCATION_HEADER_NAME;
+
 import android.app.Activity;
 import android.app.LoadedApk;
 import android.content.Context;
@@ -29,6 +32,7 @@
 import android.net.NetworkRequest;
 import android.net.Proxy;
 import android.net.Uri;
+import android.net.captiveportal.CaptivePortalProbeSpec;
 import android.net.dns.ResolvUtil;
 import android.net.http.SslError;
 import android.net.wifi.WifiInfo;
@@ -85,6 +89,7 @@
     };
 
     private URL mUrl;
+    private CaptivePortalProbeSpec mProbeSpec;
     private String mUserAgent;
     private Network mNetwork;
     private CaptivePortal mCaptivePortal;
@@ -118,6 +123,14 @@
             Log.d(TAG, String.format("onCreate for %s", mUrl.toString()));
         }
 
+        final String spec = getIntent().getStringExtra(EXTRA_CAPTIVE_PORTAL_PROBE_SPEC);
+        try {
+            mProbeSpec = CaptivePortalProbeSpec.parseSpecOrNull(spec);
+        } catch (Exception e) {
+            // Make extra sure that invalid configurations do not cause crashes
+            mProbeSpec = null;
+        }
+
         // Also initializes proxy system properties.
         mCm.bindProcessToNetwork(mNetwork);
         mCm.setProcessDefaultNetworkForHostResolution(
@@ -329,6 +342,7 @@
                 }
                 HttpURLConnection urlConnection = null;
                 int httpResponseCode = 500;
+                String locationHeader = null;
                 try {
                     urlConnection = (HttpURLConnection) network.openConnection(mUrl);
                     urlConnection.setInstanceFollowRedirects(false);
@@ -343,6 +357,7 @@
 
                     urlConnection.getInputStream();
                     httpResponseCode = urlConnection.getResponseCode();
+                    locationHeader = urlConnection.getHeaderField(HTTP_LOCATION_HEADER_NAME);
                     if (DBG) {
                         Log.d(TAG, "probe at " + mUrl +
                                 " ret=" + httpResponseCode +
@@ -353,13 +368,20 @@
                 } finally {
                     if (urlConnection != null) urlConnection.disconnect();
                 }
-                if (httpResponseCode == 204) {
+                if (isDismissed(httpResponseCode, locationHeader, mProbeSpec)) {
                     done(Result.DISMISSED);
                 }
             }
         }).start();
     }
 
+    private static boolean isDismissed(
+            int httpResponseCode, String locationHeader, CaptivePortalProbeSpec probeSpec) {
+        return (probeSpec != null)
+                ? probeSpec.getResult(httpResponseCode, locationHeader).isSuccessful()
+                : (httpResponseCode == 204);
+    }
+
     private class MyWebViewClient extends WebViewClient {
         private static final String INTERNAL_ASSETS = "file:///android_asset/";
 
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index d0973f0..b8353eeb 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"সংযোগৰ ক্ষমতা অনুযায়ী সৰ্বোত্তম"</item>
     <item msgid="364670732877872677">"উত্তম প্ৰচেষ্টা (অভিযোজিত বিট ৰেইট)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", সক্ৰিয়"</item>
+    <item msgid="8962366465966010158">", সক্ৰিয় (মিডিয়া)"</item>
+    <item msgid="4046665544396189228">", সক্ৰিয় (ফ\'ন)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"অফ কৰক"</item>
     <item msgid="1593289376502312923">"৬৪কে."</item>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index e186bb4..6340034 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"সংযোগের গুণমানের জন্য অপটিমাইজ করা হয়েছে"</item>
     <item msgid="364670732877872677">"সেরা প্রচেষ্টা (অ্যাডাপ্টিভ বিট রেট)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", চালু আছে"</item>
+    <item msgid="8962366465966010158">", চালু আছে (মিডিয়া)"</item>
+    <item msgid="4046665544396189228">", চালু আছে (ফোন)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"বন্ধ আছে"</item>
     <item msgid="1593289376502312923">"৬৪K"</item>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 30a9339..ecf5525 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"કનેક્શનની ગુણવત્તા માટે ઓપ્ટિમાઇઝ કર્યું"</item>
     <item msgid="364670732877872677">"ઉત્તમ પ્રયાસ (અનુકૂલનશીલ બિટ રેટ)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", સક્રિય"</item>
+    <item msgid="8962366465966010158">", સક્રિય (મીડિયા)"</item>
+    <item msgid="4046665544396189228">", સક્રિય (ફોન)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"બંધ"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 0e34b77..d1d0157 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -140,9 +140,9 @@
   </string-array>
   <string-array name="bluetooth_audio_active_device_summaries">
     <item msgid="4862957058729193940"></item>
-    <item msgid="6481691720774549651">"चालू है"</item>
-    <item msgid="8962366465966010158">"चालू है (सिर्फ़ मीडिया के लिए)"</item>
-    <item msgid="4046665544396189228">"चालू है (सिर्फ़ फ़ोन के लिए)"</item>
+    <item msgid="6481691720774549651">", चालू है"</item>
+    <item msgid="8962366465966010158">", चालू है (सिर्फ़ मीडिया के लिए)"</item>
+    <item msgid="4046665544396189228">", चालू है (सिर्फ़ फ़ोन के लिए)"</item>
   </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"बंद"</item>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 3aef4ce..b073371 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"Fínstillt fyrir gæði tengingar"</item>
     <item msgid="364670732877872677">"Bestu mögulegu gæði (breytilegur bitahraði)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", virkt"</item>
+    <item msgid="8962366465966010158">", virkt (hljóð- og myndefni)"</item>
+    <item msgid="4046665544396189228">", virkt (sími)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Slökkt"</item>
     <item msgid="1593289376502312923">"64 k"</item>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 037c23f..8b6b8ca 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"אופטימיזציה להשגת איכות חיבור מרבית"</item>
     <item msgid="364670732877872677">"האיכות הטובה ביותר (קצב העברת נתונים מותאם)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", פעיל"</item>
+    <item msgid="8962366465966010158">", פעיל (מדיה)"</item>
+    <item msgid="4046665544396189228">", פעיל (טלפון)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"כבוי"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index a66af95..75d5dcb 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"ಸಂಪರ್ಕ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗಿದೆ"</item>
     <item msgid="364670732877872677">"ಅತ್ಯುತ್ತಮ ಪ್ರಯತ್ನ (ಹೊಂದಿಸಬಹುದಾದ ಬಿಟ್ ಪ್ರಮಾಣ)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">"ಸಕ್ರಿಯ"</item>
+    <item msgid="8962366465966010158">", ಸಕ್ರಿಯ (ಮಾಧ್ಯಮ)"</item>
+    <item msgid="4046665544396189228">", ಸಕ್ರಿಯ (ಫೋನ್)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ಆಫ್"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 74689e3..3337913 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"കണക്ഷൻ നിലവാരമുയർത്താൻ ഒപ്‌റ്റിമൈസ് ചെയ്‌തു"</item>
     <item msgid="364670732877872677">"മികച്ച സംവിധാനം (അനുയോജ്യമായ ബിറ്റ് റേറ്റ്)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", സജീവം"</item>
+    <item msgid="8962366465966010158">", സജീവ (മീഡിയ)"</item>
+    <item msgid="4046665544396189228">", സജീവമായ (ഫോൺ)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ഓഫ്"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 841e564..f5bf2ea 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"कनेक्शन गुणवत्तेसाठी ऑप्टिमाइझ केले"</item>
     <item msgid="364670732877872677">"सर्वोत्तम प्रयत्न (अनुकूल बिट रेट)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", अॅक्टिव्ह"</item>
+    <item msgid="8962366465966010158">", अॅक्टिव्ह (मीडिया)"</item>
+    <item msgid="4046665544396189228">", अॅक्टिव्ह (फोन)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"बंद"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 95a26d2..4ed55cc 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"जडानको गुणस्तर सुधार्न अनुकूलन गरिएको"</item>
     <item msgid="364670732877872677">"उत्कृष्ट प्रयास (अनुकूलनीय बिट दर)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", सक्रिय"</item>
+    <item msgid="8962366465966010158">", सक्रिय (मिडिया)"</item>
+    <item msgid="4046665544396189228">", सक्रिय (फोन)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"निष्क्रिय गर्नुहोस्"</item>
     <item msgid="1593289376502312923">"६४के"</item>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 9da5d6e..18de8f9 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"ସଂଯୋଗର ଗୁଣବତ୍ତା ପାଇଁ ଅନୁକୂଳିତ"</item>
     <item msgid="364670732877872677">"ସର୍ବୋତ୍ତମ ପ୍ରୟାସ (ଅନୁକୂଳ ବିଟ୍‌ ରେଟ୍‌)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", ସକ୍ରିୟ"</item>
+    <item msgid="8962366465966010158">", ସକ୍ରିୟ (ମିଡିଆ)"</item>
+    <item msgid="4046665544396189228">", ସକ୍ରିୟ (ଫୋନ୍)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ଅଫ୍"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 2b3b919..ddb40ce 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"కనెక్షన్ నాణ్యత కోసం అనుకూలీకరించబడింది"</item>
     <item msgid="364670732877872677">"ఉత్తమ కృషి (అనుకూల బిట్ రేట్)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">", సక్రియంగా ఉంది"</item>
+    <item msgid="8962366465966010158">", (మీడియా) సక్రియంగా ఉంది"</item>
+    <item msgid="4046665544396189228">", (ఫోన్) సక్రియంగా ఉంది"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ఆఫ్"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 6e2f904..c6eadd98 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -138,9 +138,12 @@
     <item msgid="4681409244565426925">"کنکشن کے معیار کیلئے بہتر بنایا گيا"</item>
     <item msgid="364670732877872677">"بہترین کوشش (اڈاپٹیو بٹ ریٹ)"</item>
   </string-array>
-    <!-- no translation found for bluetooth_audio_active_device_summaries:1 (6481691720774549651) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:2 (8962366465966010158) -->
-    <!-- no translation found for bluetooth_audio_active_device_summaries:3 (4046665544396189228) -->
+  <string-array name="bluetooth_audio_active_device_summaries">
+    <item msgid="4862957058729193940"></item>
+    <item msgid="6481691720774549651">"، فعال"</item>
+    <item msgid="8962366465966010158">"، فعال (میڈیا)"</item>
+    <item msgid="4046665544396189228">"، فعال (فون)"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"آف"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 4e9e566..0b58c9d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -505,5 +505,6 @@
                 callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
             }
         }
+        mDeviceManager.onProfileConnectionStateChanged(device, state, bluetoothProfile);
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 15f6983..e9d96ae 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -19,6 +19,7 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.util.Log;
 
@@ -323,16 +324,31 @@
             if (cachedDevice.getHiSyncId() == hiSyncId) {
                 if (firstMatchedIndex != -1) {
                     /* Found the second one */
-                    mCachedDevices.remove(i);
-                    mHearingAidDevicesNotAddedInCache.add(cachedDevice);
+                    int indexToRemoveFromUi;
+                    CachedBluetoothDevice deviceToRemoveFromUi;
+
                     // Since the hiSyncIds have been updated for a connected pair of hearing aids,
                     // we remove the entry of one the hearing aids from the UI. Unless the
-                    // hiSyncId get updated, the system does not know its a hearing aid, so we add
+                    // hiSyncId get updated, the system does not know it is a hearing aid, so we add
                     // both the hearing aids as separate entries in the UI first, then remove one
-                    // of them after the hiSyncId is populated.
-                    log("onHiSyncIdChanged: removed device=" + cachedDevice + ", with hiSyncId="
-                        + hiSyncId);
-                    mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
+                    // of them after the hiSyncId is populated. We will choose the device that
+                    // is not connected to be removed.
+                    if (cachedDevice.isConnected()) {
+                        indexToRemoveFromUi = firstMatchedIndex;
+                        deviceToRemoveFromUi = mCachedDevices.get(firstMatchedIndex);
+                        mCachedDevicesMapForHearingAids.put(hiSyncId, cachedDevice);
+                    } else {
+                        indexToRemoveFromUi = i;
+                        deviceToRemoveFromUi = cachedDevice;
+                        mCachedDevicesMapForHearingAids.put(hiSyncId,
+                                                            mCachedDevices.get(firstMatchedIndex));
+                    }
+
+                    mCachedDevices.remove(indexToRemoveFromUi);
+                    mHearingAidDevicesNotAddedInCache.add(deviceToRemoveFromUi);
+                    log("onHiSyncIdChanged: removed from UI device=" + deviceToRemoveFromUi
+                        + ", with hiSyncId=" + hiSyncId);
+                    mBtManager.getEventManager().dispatchDeviceRemoved(deviceToRemoveFromUi);
                     break;
                 } else {
                     mCachedDevicesMapForHearingAids.put(hiSyncId, cachedDevice);
@@ -342,6 +358,72 @@
         }
     }
 
+    private CachedBluetoothDevice getHearingAidOtherDevice(CachedBluetoothDevice thisDevice,
+                                                           long hiSyncId) {
+        if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+            return null;
+        }
+
+        // Searched the lists for the other side device with the matching hiSyncId.
+        for (CachedBluetoothDevice notCachedDevice : mHearingAidDevicesNotAddedInCache) {
+            if ((hiSyncId == notCachedDevice.getHiSyncId()) &&
+                (!Objects.equals(notCachedDevice, thisDevice))) {
+                return notCachedDevice;
+            }
+        }
+
+        CachedBluetoothDevice cachedDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
+        if (!Objects.equals(cachedDevice, thisDevice)) {
+            return cachedDevice;
+        }
+        return null;
+    }
+
+    private void hearingAidSwitchDisplayDevice(CachedBluetoothDevice toDisplayDevice,
+                                           CachedBluetoothDevice toHideDevice, long hiSyncId)
+    {
+        log("hearingAidSwitchDisplayDevice: toDisplayDevice=" + toDisplayDevice
+            + ", toHideDevice=" + toHideDevice);
+
+        // Remove the "toHideDevice" device from the UI.
+        mHearingAidDevicesNotAddedInCache.add(toHideDevice);
+        mCachedDevices.remove(toHideDevice);
+        mBtManager.getEventManager().dispatchDeviceRemoved(toHideDevice);
+
+        // Add the "toDisplayDevice" device to the UI.
+        mHearingAidDevicesNotAddedInCache.remove(toDisplayDevice);
+        mCachedDevices.add(toDisplayDevice);
+        mCachedDevicesMapForHearingAids.put(hiSyncId, toDisplayDevice);
+        mBtManager.getEventManager().dispatchDeviceAdded(toDisplayDevice);
+    }
+
+    public synchronized void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice,
+                                                             int state, int bluetoothProfile) {
+        if (bluetoothProfile == BluetoothProfile.HEARING_AID
+            && cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
+            && cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
+
+            long hiSyncId = cachedDevice.getHiSyncId();
+
+            CachedBluetoothDevice otherDevice = getHearingAidOtherDevice(cachedDevice, hiSyncId);
+            if (otherDevice == null) {
+                // no other side device. Nothing to do.
+                return;
+            }
+
+            if (state == BluetoothProfile.STATE_CONNECTED &&
+                mHearingAidDevicesNotAddedInCache.contains(cachedDevice)) {
+                hearingAidSwitchDisplayDevice(cachedDevice, otherDevice, hiSyncId);
+            } else if (state == BluetoothProfile.STATE_DISCONNECTED
+                       && otherDevice.isConnected()) {
+                CachedBluetoothDevice mapDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
+                if ((mapDevice != null) && (Objects.equals(cachedDevice, mapDevice))) {
+                    hearingAidSwitchDisplayDevice(otherDevice, cachedDevice, hiSyncId);
+                }
+            }
+        }
+    }
+
     public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) {
         final long hiSyncId = device.getHiSyncId();
 
@@ -353,9 +435,16 @@
                 // TODO: Look for more cleanups on unpairing the device.
                 mHearingAidDevicesNotAddedInCache.remove(i);
                 if (device == cachedDevice) continue;
+                log("onDeviceUnpaired: Unpair device=" + cachedDevice);
                 cachedDevice.unpair();
             }
         }
+
+        CachedBluetoothDevice mappedDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
+        if ((mappedDevice != null) && (!Objects.equals(device, mappedDevice))) {
+            log("onDeviceUnpaired: Unpair mapped device=" + mappedDevice);
+            mappedDevice.unpair();
+        }
     }
 
     public synchronized void dispatchAudioModeChanged() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index 5b8e1fc..2fc6db0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -57,7 +57,7 @@
     private int mLevel = -1;
     private boolean mCharging;
     private boolean mPowerSaveEnabled;
-    private boolean mPowerSaveAsColorError = true;
+    protected boolean mPowerSaveAsColorError = true;
     private boolean mShowPercent;
 
     private static final boolean SINGLE_DIGIT_PERCENT = false;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
index 466980c..1080690 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
@@ -98,5 +98,8 @@
 
         verify(mBluetoothCallback).onProfileConnectionStateChanged(mCachedBluetoothDevice,
                 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
+
+        verify(mCachedDeviceManager).onProfileConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index bab3cab..16ed85c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -235,7 +235,7 @@
      * Test to verify onHiSyncIdChanged() for hearing aid devices with same HiSyncId.
      */
     @Test
-    public void testOnDeviceAdded_sameHiSyncId_populateInDifferentLists() {
+    public void testOnHiSyncIdChanged_sameHiSyncId_populateInDifferentLists() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
             mLocalProfileManager, mDevice1);
         assertThat(cachedDevice1).isNotNull();
@@ -261,16 +261,53 @@
         assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
         Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
         assertThat(devices).contains(cachedDevice2);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .contains(cachedDevice2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids)
+            .containsKey(HISYNCID1);
+    }
+
+    /**
+     * Test to verify onHiSyncIdChanged() for 2 hearing aid devices with same HiSyncId but one
+     * device is connected and other is disconnected. The connected device should be chosen.
+     */
+    @Test
+    public void testOnHiSyncIdChanged_sameHiSyncIdAndOneConnected_chooseConnectedDevice() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+            mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+            mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+        cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+
+        /* Device 1 is connected and Device 2 is disconnected */
+        when(mHearingAidProfile.getConnectionStatus(mDevice1)).
+            thenReturn(BluetoothProfile.STATE_CONNECTED);
+        when(mHearingAidProfile.getConnectionStatus(mDevice2)).
+            thenReturn(BluetoothProfile.STATE_DISCONNECTED);
+
+        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
+
+        cachedDevice1.setHiSyncId(HISYNCID1);
+        cachedDevice2.setHiSyncId(HISYNCID1);
+        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
+
+        // Only the connected device, device 1, should be visible to UI.
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
+            containsExactly(HISYNCID1, cachedDevice1);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).
+            containsExactly(cachedDevice2);
     }
 
     /**
      * Test to verify onHiSyncIdChanged() for hearing aid devices with different HiSyncId.
      */
     @Test
-    public void testOnDeviceAdded_differentHiSyncId_populateInSameList() {
+    public void testOnHiSyncIdChanged_differentHiSyncId_populateInSameList() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
             mLocalProfileManager, mDevice1);
         assertThat(cachedDevice1).isNotNull();
@@ -303,6 +340,153 @@
     }
 
     /**
+     * Test to verify onProfileConnectionStateChanged() for single hearing aid device connection.
+     */
+    @Test
+    public void testOnProfileConnectionStateChanged_singleDeviceConnected_visible() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+            mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+
+        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
+
+        cachedDevice1.setHiSyncId(HISYNCID1);
+        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
+
+        // Connect the Device 1
+        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
+            BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
+
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
+            containsExactly(HISYNCID1, cachedDevice1);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+
+        // Disconnect the Device 1
+        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
+            BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
+
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
+            containsExactly(HISYNCID1, cachedDevice1);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+    }
+
+    /**
+     * Test to verify onProfileConnectionStateChanged() for two hearing aid devices where both
+     * devices are disconnected and they get connected.
+     */
+    @Test
+    public void testOnProfileConnectionStateChanged_twoDevicesConnected_oneDeviceVisible() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+            mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+            mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+        cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+
+        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
+
+        cachedDevice1.setHiSyncId(HISYNCID1);
+        cachedDevice2.setHiSyncId(HISYNCID1);
+        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
+
+        // There should be one cached device but can be either one.
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
+
+        // Connect the Device 1
+        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
+            BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
+
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
+            containsExactly(HISYNCID1, cachedDevice1);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice2);
+        assertThat(mCachedDeviceManager.mCachedDevices).contains(cachedDevice1);
+
+        when(mHearingAidProfile.getConnectionStatus(mDevice1)).
+            thenReturn(BluetoothProfile.STATE_CONNECTED);
+        when(mHearingAidProfile.getConnectionStatus(mDevice2)).
+            thenReturn(BluetoothProfile.STATE_DISCONNECTED);
+
+        // Connect the Device 2
+        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice2,
+            BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
+
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
+        assertThat(mCachedDeviceManager.mCachedDevices).hasSize(1);
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
+    }
+
+    /**
+     * Test to verify onProfileConnectionStateChanged() for two hearing aid devices where both
+     * devices are connected and they get disconnected.
+     */
+    @Test
+    public void testOnProfileConnectionStateChanged_twoDevicesDisconnected_oneDeviceVisible() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+            mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+            mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+        cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mHearingAidProfile.getConnectionStatus(mDevice1)).
+            thenReturn(BluetoothProfile.STATE_CONNECTED);
+        when(mHearingAidProfile.getConnectionStatus(mDevice2)).
+            thenReturn(BluetoothProfile.STATE_CONNECTED);
+
+        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
+
+        cachedDevice1.setHiSyncId(HISYNCID1);
+        cachedDevice2.setHiSyncId(HISYNCID1);
+        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
+
+        /* Disconnect the Device 1 */
+        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
+            BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
+
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice2);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
+        assertThat(mCachedDeviceManager.mCachedDevices).contains(cachedDevice2);
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids)
+            .containsExactly(HISYNCID1, cachedDevice2);
+
+        when(mHearingAidProfile.getConnectionStatus(mDevice1)).
+            thenReturn(BluetoothProfile.STATE_DISCONNECTED);
+        when(mHearingAidProfile.getConnectionStatus(mDevice2)).
+            thenReturn(BluetoothProfile.STATE_CONNECTED);
+
+        /* Disconnect the Device 2 */
+        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice2,
+            BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
+
+        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
+        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
+        assertThat(mCachedDeviceManager.mCachedDevices).hasSize(1);
+        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
+    }
+
+    /**
      * Test to verify OnDeviceUnpaired() for a paired hearing Aid device pair.
      */
     @Test
diff --git a/packages/Shell/res/values-hy/strings.xml b/packages/Shell/res/values-hy/strings.xml
index cd57e76..95b6131 100644
--- a/packages/Shell/res/values-hy/strings.xml
+++ b/packages/Shell/res/values-hy/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Ընտրեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Հպեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Հպեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"Վրիպակի զեկույցները պարունակում են տվյալներ համակարգի տարբեր մատյանի ֆայլերից և կարող են ներառել տեղեկություններ, որոնք դուք գաղտնի եք համարում (օրինակ՝ հավելվածի օգտագործման կամ տեղադրության մասին): Վրիպակի զեկույցները տրամադրեք միայն վստահելի մարդկանց և հավելվածներին:"</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"Վրիպակի զեկույցները պարունակում են տվյալներ համակարգի տարբեր մատյաններից և կարող են ներառել տեղեկություններ, որոնք դուք գաղտնի եք համարում (օրինակ՝ հավելվածի օգտագործման կամ տեղադրության մասին): Վրիպակի զեկույցները տրամադրեք միայն վստահելի մարդկանց և հավելվածներին:"</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Այլևս ցույց չտալ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"Վրիպակների հաշվետվություններ"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"Հնարավոր չէ կարդալ վրիպակների զեկույցի ֆայլը"</string>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index db03ed2..dfa4bf9 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -28,7 +28,7 @@
     android:clipToPadding="false"
     android:orientation="vertical"
     android:layout_centerHorizontal="true">
-    <com.android.systemui.statusbar.AlphaOptimizedTextView
+    <view class="com.android.keyguard.KeyguardSliceView$TitleView"
               android:id="@+id/title"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
deleted file mode 100644
index aa9f6d4..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 0a6074b..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 151caea..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png
deleted file mode 100644
index 64bc40a..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step.png
deleted file mode 100644
index d7f9449..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png
deleted file mode 100644
index 7c65703..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index eea819a..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index 504ceb7..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked.png
deleted file mode 100755
index 0622ddc..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index fb44f22a..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
deleted file mode 100644
index 613afce..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index a665e23..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index 8e7d8cb..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index 456a68f..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
deleted file mode 100644
index 72b2b21..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index 4f65660..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
deleted file mode 100644
index eb80426..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index c57face..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked.png
deleted file mode 100755
index c03ad20..0000000
--- a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index bbaab44..0000000
--- a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index fb854ec..0000000
--- a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index 75d184a..0000000
--- a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked.png
deleted file mode 100755
index bfe2b4a..0000000
--- a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index dba0040..0000000
--- a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index 9e0af28..0000000
--- a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index 7c00bd5d..0000000
--- a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked.png
deleted file mode 100755
index 5ed0ee8..0000000
--- a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 2b64b80..0000000
--- a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index 81b4466..0000000
--- a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index 724aa9e..0000000
--- a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked.png
deleted file mode 100755
index d181162..0000000
--- a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 151a3c0..0000000
--- a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index 7ba0d1b..0000000
--- a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index a175ccb..0000000
--- a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land/ic_sysbar_docked.png
deleted file mode 100755
index 236b70a..0000000
--- a/packages/SystemUI/res/drawable-land/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png
deleted file mode 100644
index 3456a97..0000000
--- a/packages/SystemUI/res/drawable-land/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
deleted file mode 100644
index 2fcfdde..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index 45ce1d4..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index 6da0c9e..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
deleted file mode 100644
index 48708a5..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index 71e8959..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index bb7ae26..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back.png
deleted file mode 100644
index 74f9256..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index c3aea46..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-hdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back.png
deleted file mode 100644
index 4de10b6..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 470b3e2..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-mdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png
deleted file mode 100644
index 965d2f5..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index e7137c6..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back.png
deleted file mode 100644
index a123262..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 03dec15..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back.png
deleted file mode 100644
index 0a95ddd..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index e1ca853..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw900dp-xxxhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
deleted file mode 100644
index 3d73184..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index 32b9ded..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index ed1949c7..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
deleted file mode 100644
index 786935d..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index 2d62a80..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index a52e5b1..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
deleted file mode 100644
index 34a11df..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 5383215..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 1c1e78c..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png
deleted file mode 100644
index 3a22912b..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step.png
deleted file mode 100644
index d888869..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png
deleted file mode 100644
index dc3b25c..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index d4e5a94..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index 0e693f7..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked.png
deleted file mode 100755
index 93d1905..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index c7e4731..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
deleted file mode 100644
index 7c25fc5..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index d2949f3..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index 0757799..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index 4f07ec1..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
deleted file mode 100644
index 35e7af4..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index 06e4c26..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
deleted file mode 100644
index 1ee9cf5..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index 1c855c4..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back.png
deleted file mode 100644
index 1e2c751..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 0520c49..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index fac2da8..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime_dark.png
deleted file mode 100644
index 3dc2b88..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_back_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked.png
deleted file mode 100644
index 63739b9..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 2ba5d5b..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home.png
deleted file mode 100644
index bb24c8b..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index 62dc2d9..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu.png
deleted file mode 100644
index 711fd7a5..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index e718b7a..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent.png
deleted file mode 100644
index bbb00a0..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index 469800a..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-hdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked.png
deleted file mode 100644
index 43f77c0..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 42863c6..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-hdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked.png
deleted file mode 100644
index 872af09..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index d9ec9d5..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-mdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked.png
deleted file mode 100644
index ea7ac93..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 8ee4e43..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-xhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked.png
deleted file mode 100644
index fe07f81..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index dfa8a97..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-xxhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked.png
deleted file mode 100644
index 4193b21..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index d23abc7..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-land-xxxhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back.png
deleted file mode 100644
index 56c2638..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 8e56e9c..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index c3aa434..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime_dark.png
deleted file mode 100644
index 28a1465..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_back_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked.png
deleted file mode 100644
index 41a7209..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 0fc9677..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home.png
deleted file mode 100644
index faaef60..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index 7b81eee..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu.png
deleted file mode 100644
index c8e40d0..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index a6483452..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent.png
deleted file mode 100644
index 2612485..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index 7f74521..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-mdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png
deleted file mode 100644
index 3b831a3..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 8c99455..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 3c37782..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked.png
deleted file mode 100644
index b2baa09..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index b78dc9c..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png
deleted file mode 100644
index 37590a5..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index 3a208aa..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu.png
deleted file mode 100644
index 4940d5c..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index 625ba45..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png
deleted file mode 100644
index 7ad2a29..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index 604397e..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xhdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 274e5df..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 6fb19ae..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked.png
deleted file mode 100644
index 49d2c3a..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index ac16895..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home.png
deleted file mode 100644
index 216f2c7..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index e69a037..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_ime_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_ime_dark.png
deleted file mode 100644
index 65a4354..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu.png
deleted file mode 100644
index a8c2786..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index 8bddcd9..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent.png
deleted file mode 100644
index ca35888..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index 38c5959..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxhdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back.png
deleted file mode 100644
index 4d23956..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index c6d7c98..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 74abc31..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime_dark.png
deleted file mode 100644
index 06c52aa..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_back_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked.png
deleted file mode 100644
index 89bed92..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 7660997..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home.png
deleted file mode 100644
index 8d4f5f3..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index 0d9ecc2..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu.png
deleted file mode 100644
index 83e96a2..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index d6bb8b1..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent.png
deleted file mode 100644
index 636c0c1..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index 298ef3a..0000000
--- a/packages/SystemUI/res/drawable-sw900dp-xxxhdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
deleted file mode 100644
index 987aac5..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index 371a84d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 433e5a74..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png
deleted file mode 100644
index 360ed77..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png
deleted file mode 100644
index ba5b457..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png
deleted file mode 100644
index a55ea1d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index 407ef28..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index 39cfbf2..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked.png
deleted file mode 100755
index 73ddde8..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 96cecc9..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
deleted file mode 100644
index 0e2a14d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index 9ff9825..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index a7fd3a69..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index f2a1255..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
deleted file mode 100644
index 69a018d..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index e505f5e..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
deleted file mode 100644
index f810704..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index 472c55b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
deleted file mode 100644
index be03cbe..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index c04d650..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index b6b1615..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png
deleted file mode 100644
index 0f6d206..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png
deleted file mode 100644
index 5a7eec6..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png
deleted file mode 100644
index f7abb54..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index a1f44dc..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index 175a9ae..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked.png
deleted file mode 100755
index 1e84732..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 58bf920..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
deleted file mode 100644
index f16aa48..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index f47533ec..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index 0fb93ca..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index 1052940..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
deleted file mode 100644
index a37ca5d..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index f299d97..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
deleted file mode 100644
index 109aeed..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index 84d6dc8..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back.png
deleted file mode 100644
index a059704..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png
deleted file mode 100644
index d813bc7..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 8f00a64..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png
deleted file mode 100644
index 30e8782..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png
deleted file mode 100644
index d13c730..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png
deleted file mode 100644
index 31c602e..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png
deleted file mode 100644
index ddbcb07..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png
deleted file mode 100644
index ce91fcbb..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked.png
deleted file mode 100755
index ee3ffde..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png
deleted file mode 100644
index 83fc662..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home.png
deleted file mode 100644
index 194d39f..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png
deleted file mode 100644
index 71101a1..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png
deleted file mode 100644
index c606a58..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png
deleted file mode 100644
index c2a5fef..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_quick_step_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png
deleted file mode 100644
index 4a477ad..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_menu_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent.png
deleted file mode 100644
index 046d850..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png
deleted file mode 100644
index bc24c00..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_dark.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_device_thermostat_24.xml b/packages/SystemUI/res/drawable/ic_device_thermostat_24.xml
index 1972f6e..90948dbc 100644
--- a/packages/SystemUI/res/drawable/ic_device_thermostat_24.xml
+++ b/packages/SystemUI/res/drawable/ic_device_thermostat_24.xml
@@ -21,5 +21,5 @@
         android:tint="?attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M15,13L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v8c-1.21,0.91 -2,2.37 -2,4 0,2.76 2.24,5 5,5s5,-2.24 5,-5c0,-1.63 -0.79,-3.09 -2,-4zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1h-1v1h1v2h-1v1h1v2h-2L11,5z"/>
+        android:pathData="M18,9h-5v2h5M21,5h-8v2h8M12,18.97c0.62,-0.83 1,-1.85 1,-2.97c0,-1.63 -0.79,-3.09 -2,-4V6c0,-1.66 -1.34,-3 -3,-3C6.34,3 5,4.34 5,6v6c-1.21,0.91 -2,2.37 -2,4c0,1.12 0.38,2.14 1,2.97V19h0.02c0.91,1.21 2.35,2 3.98,2s3.06,-0.79 3.98,-2H12V18.97zM6.2,13.6L7,13v-1V6c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6v1l0.8,0.6c0.75,0.57 1.2,1.46 1.2,2.4H5C5,15.06 5.45,14.16 6.2,13.6z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_mic_26dp.xml b/packages/SystemUI/res/drawable/ic_mic_26dp.xml
index 15c97b3..1160c90 100644
--- a/packages/SystemUI/res/drawable/ic_mic_26dp.xml
+++ b/packages/SystemUI/res/drawable/ic_mic_26dp.xml
@@ -20,5 +20,8 @@
         android:viewportHeight="24.0">
     <path
         android:fillColor="#FF000000"
-        android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM18.08,11c-0.42,0 -0.77,0.3 -0.83,0.71 -0.37,2.61 -2.72,4.39 -5.25,4.39s-4.88,-1.77 -5.25,-4.39a0.839,0.839 0,0 0,-0.83 -0.71c-0.52,0 -0.92,0.46 -0.85,0.97 0.46,2.96 2.96,5.3 5.93,5.75v2.43c0,0.47 0.38,0.85 0.85,0.85h0.31c0.47,0 0.85,-0.38 0.85,-0.85v-2.43c2.96,-0.43 5.47,-2.78 5.93,-5.75a0.87,0.87 0,0 0,-0.86 -0.97z"/>
+        android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V5z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_person.xml b/packages/SystemUI/res/drawable/ic_person.xml
index 101911f..1ee9401 100644
--- a/packages/SystemUI/res/drawable/ic_person.xml
+++ b/packages/SystemUI/res/drawable/ic_person.xml
@@ -16,9 +16,9 @@
 <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">
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
     <path
-        android:fillColor="#ffffffff"
-        android:pathData="M24 24c4.42 0 8,-3.59 8,-8 0,-4.42,-3.58,-8,-8,-8s-8 3.58,-8 8c0 4.41 3.58 8 8 8zm0 4c-5.33 0,-16 2.67,-16 8v4h32v-4c0,-5.33,-10.67,-8,-16,-8z"/>
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12,6c1.1,0 2,0.9 2,2s-0.9,2 -2,2s-2,-0.9 -2,-2S10.9,6 12,6M12,15c2.7,0 5.8,1.29 6,2v1H6l0,-0.99C6.2,16.29 9.3,15 12,15M12,4C9.79,4 8,5.79 8,8s1.79,4 4,4s4,-1.79 4,-4S14.21,4 12,4L12,4zM12,13c-2.67,0 -8,1.34 -8,4v3h16v-3C20,14.34 14.67,13 12,13L12,13z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
index fba45d1..9c24c2c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
@@ -18,44 +18,9 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="48dp"
     android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48">
-    <group
-        android:name="device"
-        android:translateX="24"
-        android:translateY="24" >
-        <group
-            android:name="device_pivot"
-            android:translateX="-24.15"
-            android:translateY="-24.25" >
-            <group
-                android:name="device_0"
-                android:translateX="24.14999"
-                android:translateY="24.25" >
-                <path
-                    android:name="device_merged"
-                    android:pathData="M -3.5,-20.5 c -1.19999694824,-1.19999694824 -3.10000610352,-1.19999694824 -4.19999694824,0.0 c 0.0,0.0 -12.8000030518,12.6999969482 -12.8000030518,12.6999969482 c -1.19999694824,1.19999694824 -1.19999694824,3.10000610352 0.0,4.19999694824 c 0.0,0.0 24.0,24.0000152588 24.0,24.0000152588 c 1.19999694824,1.19999694824 3.10000610352,1.19999694824 4.19999694824,0.0 c 0.0,0.0 12.6999969482,-12.700012207 12.6999969482,-12.700012207 c 1.20001220703,-1.19999694824 1.20001220703,-3.09999084473 0.0,-4.19999694824 c 0.0,0.0 -23.8999938965,-24.0 -23.8999938965,-24.0 Z M 2.84999084473,15.5500183105 c 0.0,0.0 -18.6000061035,-18.5000457764 -18.6000061035,-18.5000457764 c 0.0,0.0 12.5999908447,-12.8000030518 12.5999908447,-12.8000030518 c 0.0,0.0 18.6000213623,18.5000457764 18.6000213623,18.5000457764 c 0.0,0.0 -12.6000061035,12.8000030518 -12.6000061035,12.8000030518 Z"
-                    android:fillColor="#FFFFFFFF" />
-            </group>
-        </group>
-    </group>
-    <group
-        android:name="arrows"
-        android:translateX="24"
-        android:translateY="24" >
-        <group
-            android:name="arrows_pivot"
-            android:translateX="-24.0798"
-            android:translateY="-24.23" >
-            <group
-                android:name="arrows_0"
-                android:translateX="12.2505"
-                android:translateY="37.2145" >
-                <path
-                    android:name="bottom_merged"
-                    android:pathData="M 20.7395019531,-31.9844970703 c 6.23999023438,2.83999633789 10.6999969482,8.7200012207 11.8399963379,15.7799987793 c 0.119995117188,0.699996948242 0.740005493164,1.2200012207 1.46099853516,1.2200012207 c 0.919998168945,0.0 1.6190032959,-0.84001159668 1.47900390625,-1.74000549316 c -1.75900268555,-10.3800048828 -9.75900268555,-19.1199951172 -22.5800018311,-20.1600036621 c -0.919998168945,-0.0800018310547 -1.43899536133,1.04000854492 -0.800003051758,1.70001220703 c 0.0,0.0 5.12100219727,5.11999511719 5.12100219727,5.11999511719 c 0.378997802734,0.380004882812 0.97900390625,0.380004882812 1.37899780273,0.020004272461 c 0.0,0.0 2.10000610352,-1.94000244141 2.10000610352,-1.94000244141 Z M 2.73950195312,6.01550292969 c -6.26000976562,-2.83999633789 -10.7200012207,-8.76000976562 -11.8399963379,-15.8600006104 c -0.118011474609,-0.667007446289 -0.702011108398,-1.15100097656 -1.38000488281,-1.13999938965 c -0.860000610352,0.0 -1.52000427246,0.759994506836 -1.38000488281,1.61999511719 c 1.54000854492,10.4000091553 9.5,19.2200012207 22.4199981689,20.2799987793 c 0.920013427734,0.0800018310547 1.44100952148,-1.03999328613 0.800003051758,-1.69999694824 c 0.0,0.0 -5.11999511719,-5.11999511719 -5.11999511719,-5.11999511719 c -0.380004882812,-0.376007080078 -0.988998413086,-0.385009765625 -1.38000488281,-0.0200042724609 c 0.0,0.0 -2.11999511719,1.94000244141 -2.11999511719,1.94000244141 Z"
-                    android:fillColor="#FFFFFFFF" />
-            </group>
-        </group>
-    </group>
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.72,23H11C5.49,23 1,18.51 1,13h2c0,3.78 2.63,6.95 6.15,7.79L8.13,19L9.87,18L12.72,23zM13,1h-1.72l2.85,5L15.87,5l-1.02,-1.79C18.37,4.05 21,7.22 21,11h2C23,5.49 18.51,1 13,1zM10.23,6L18,13.76L13.77,18L6,10.24L10.23,6C10.23,6 10.23,6 10.23,6M10.23,4C9.72,4 9.21,4.2 8.82,4.59L4.59,8.82c-0.78,0.78 -0.78,2.04 0,2.82l7.77,7.77c0.39,0.39 0.9,0.59 1.41,0.59c0.51,0 1.02,-0.2 1.41,-0.59l4.24,-4.24c0.78,-0.78 0.78,-2.04 0,-2.82l-7.77,-7.77C11.26,4.2 10.75,4 10.23,4L10.23,4z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml b/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml
index 736a04a..b20e158 100644
--- a/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_branded_vpn.xml
@@ -20,5 +20,8 @@
         android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
-        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"/>
+        android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h6v-3h2V9H12.09zM20,13h-2v3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H20V13z"/>
+    <path
+        android:fillColor="#4DFFFFFF"
+        android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
index 5dcd9f7..22e12cc 100644
--- a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
@@ -16,14 +16,12 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="32dp"
         android:height="32dp"
-        android:viewportWidth="18.4"
-        android:viewportHeight="18.4">
-
-    <group
-        android:translateX="0.7"
-        android:translateY="1.0">
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M13.91,11.84L5.14,3.08l1.81,-1.81h5.41c0.85,0 1.54,0.69 1.54,1.54l0.01,9.03zM15.06,14.95L2.54,2.44c-0.28,-0.28 -0.71,-0.28 -0.99,0s-0.28,0.71 0,0.98l1.53,1.53v8.67c0,0.85 0.69,1.54 1.54,1.54h7.74c0.27,0 0.52,-0.07 0.74,-0.2l0.96,0.96c0.28,0.28 0.71,0.28 0.99,0 0.28,-0.26 0.28,-0.69 0.01,-0.97z"/>
-    </group>
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M10.84,5H17v9.11l2,2V5c0,-1.1 -0.9,-2 -2,-2h-6.99L7.95,5.06l1.41,1.41L10.84,5z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M2.81,2.81L1.39,4.22L5,7.83V19c0,1.1 0.9,2 2,2h10c0.34,0 0.65,-0.1 0.93,-0.24l1.85,1.85l1.41,-1.41L2.81,2.81zM7,19V9.83L16.17,19H7z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_vpn.xml b/packages/SystemUI/res/drawable/ic_qs_vpn.xml
index cf24e12..6567d123 100644
--- a/packages/SystemUI/res/drawable/ic_qs_vpn.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_vpn.xml
@@ -20,5 +20,8 @@
         android:viewportHeight="24.0">
     <path
         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"/>
+        android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h6v-3h2V9H12.09zM20,13h-2v3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H20V13z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_sim.xml b/packages/SystemUI/res/drawable/ic_sim.xml
index 983c1d0..a9a1902 100644
--- a/packages/SystemUI/res/drawable/ic_sim.xml
+++ b/packages/SystemUI/res/drawable/ic_sim.xml
@@ -19,9 +19,24 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M0 0h24v24H0z"
-        android:fillColor="#00000000"/>
+        android:fillColor="#FF000000"
+        android:pathData="M18,2h-8L4,8v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4C20,2.9 19.1,2 18,2zM18,4v16H6V8.83L10.83,4L18,4L18,4z"/>
     <path
         android:fillColor="#FF000000"
-        android:pathData="M18.0,2.0l-8.0,0.0L4.02,8.0 4.0,20.0c0.0,1.0 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0z"/>
+        android:pathData="M7,17h2v2h-2z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M15,17h2v2h-2z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M7,11h2v4h-2z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11,15h2v4h-2z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11,11h2v2h-2z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M15,11h2v4h-2z"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml
index 1603eba..6fbc404 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_accessibility_button.xml
@@ -14,12 +14,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24"
-        android:viewportHeight="24">
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
     <path
         android:pathData="M20.5,6c-2.61,0.7 -5.67,1 -8.5,1S6.11,6.7 3.5,6L3,8c1.86,0.5 4,0.83 6,1v13h2v-6h2v6h2V9c2,-0.17 4.14,-0.5 6,-1L20.5,6zM12,6c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2s-2,0.9 -2,2S10.9,6 12,6z"
         android:fillColor="?attr/singleToneColor"/>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back.xml b/packages/SystemUI/res/drawable/ic_sysbar_back.xml
new file mode 100644
index 0000000..1448843
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_back.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
+
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M6.49,14.86c-0.66-0.39-0.66-1.34,0-1.73l6.02-3.53l5.89-3.46C19.11,5.73,20,6.26,20,7.1V14v6.9 c0,0.84-0.89,1.37-1.6,0.95l-5.89-3.46L6.49,14.86z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
new file mode 100644
index 0000000..b02a252
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
+
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M17.25,10.15V14v3.85L14,15.95L10.69,14L14,12.05L17.25,10.15 M18.16,7.71c-0.14,0-0.28,0.04-0.42,0.12 l-4.63,2.72l-4.73,2.78c-0.52,0.3-0.52,1.05,0,1.36l4.73,2.78l4.63,2.72c0.13,0.08,0.28,0.12,0.42,0.12c0.44,0,0.84-0.36,0.84-0.86 V14V8.58C19,8.08,18.6,7.71,18.16,7.71L18.16,7.71z" />
+    <path
+        android:pathData="M 0 0 H 28 V 28 H 0 V 0 Z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_docked.xml b/packages/SystemUI/res/drawable/ic_sysbar_docked.xml
new file mode 100644
index 0000000..693835f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_docked.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
+
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M20.5,13h-13C6.67,13,6,12.33,6,11.5v-4C6,6.67,6.67,6,7.5,6h13C21.33,6,22,6.67,22,7.5v4 C22,12.33,21.33,13,20.5,13z" />
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M20.5,22h-13C6.67,22,6,21.33,6,20.5v-4C6,15.67,6.67,15,7.5,15h13c0.83,0,1.5,0.67,1.5,1.5v4 C22,21.33,21.33,22,20.5,22z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_home.xml b/packages/SystemUI/res/drawable/ic_sysbar_home.xml
new file mode 100644
index 0000000..a960af7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_home.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval"
+    android:useLevel="false">
+
+    <solid android:color="?attr/singleToneColor" />
+
+    <size
+        android:height="14dp"
+        android:width="14dp" />
+</shape>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_home_quick_step.xml b/packages/SystemUI/res/drawable/ic_sysbar_home_quick_step.xml
new file mode 100644
index 0000000..ba1236e1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_home_quick_step.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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="28dp"
+     android:height="28dp"
+     android:viewportWidth="28"
+     android:viewportHeight="28">
+
+     <path
+          android:fillColor="?attr/singleToneColor"
+          android:pathData="M23,19H5c-2.76,0-5-2.24-5-5l0,0c0-2.76,2.24-5,5-5h18c2.76,0,5,2.24,5,5l0,0C28,16.76,25.76,19,23,19z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_menu.xml b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
new file mode 100644
index 0000000..5cc1791
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_menu.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
+
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M14,9.5c1.24,0,2.25-1.01,2.25-2.25S15.24,5,14,5s-2.25,1.01-2.25,2.25S12.76,9.5,14,9.5z M14,11.75 c-1.24,0-2.25,1.01-2.25,2.25s1.01,2.25,2.25,2.25s2.25-1.01,2.25-2.25S15.24,11.75,14,11.75z M14,18.5 c-1.24,0-2.25,1.01-2.25,2.25S12.76,23,14,23s2.25-1.01,2.25-2.25S15.24,18.5,14,18.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_recent.xml b/packages/SystemUI/res/drawable/ic_sysbar_recent.xml
new file mode 100644
index 0000000..6b038d1
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_recent.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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="28dp"
+    android:height="28dp"
+    android:viewportWidth="28"
+    android:viewportHeight="28">
+
+    <path
+        android:fillColor="?attr/singleToneColor"
+        android:pathData="M19.9,21.5H8.1c-0.88,0-1.6-0.72-1.6-1.6V8.1c0-0.88,0.72-1.6,1.6-1.6h11.8c0.88,0,1.6,0.72,1.6,1.6v11.8 C21.5,20.78,20.78,21.5,19.9,21.5z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
index 461d62e..6c1ae99 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
@@ -29,7 +29,7 @@
         </vector>
     </aapt:attr>
 
-    <!-- Repeat all animations 3 times but don't fade out at the end -->
+    <!-- Repeat all animations 5 times but don't fade out at the end -->
     <target android:name="root">
         <aapt:attr name="android:animation">
             <set android:ordering="sequentially">
@@ -67,6 +67,34 @@
                                 android:valueFrom="0"
                                 android:valueTo="1"
                                 android:interpolator="@android:anim/linear_interpolator" />
+                <!-- Linear fade out -->
+                <objectAnimator android:propertyName="alpha"
+                                android:duration="100"
+                                android:startOffset="1700"
+                                android:valueFrom="1"
+                                android:valueTo="0"
+                                android:interpolator="@android:anim/linear_interpolator"/>
+                <!-- Linear fade in-->
+                <objectAnimator android:propertyName="alpha"
+                                android:duration="100"
+                                android:startOffset="100"
+                                android:valueFrom="0"
+                                android:valueTo="1"
+                                android:interpolator="@android:anim/linear_interpolator" />
+                <!-- Linear fade out -->
+                <objectAnimator android:propertyName="alpha"
+                                android:duration="100"
+                                android:startOffset="1700"
+                                android:valueFrom="1"
+                                android:valueTo="0"
+                                android:interpolator="@android:anim/linear_interpolator"/>
+                <!-- Linear fade in-->
+                <objectAnimator android:propertyName="alpha"
+                                android:duration="100"
+                                android:startOffset="100"
+                                android:valueFrom="0"
+                                android:valueTo="1"
+                                android:interpolator="@android:anim/linear_interpolator" />
             </set>
         </aapt:attr>
     </target>
@@ -117,6 +145,40 @@
                         <pathInterpolator android:pathData="M 0.0,0.0 c0.408,1.181 0.674,1.08 1.0,1.0"/>
                     </aapt:attr>
                 </objectAnimator>
+
+                <!-- Reset rotation position for fade in -->
+                <objectAnimator android:propertyName="rotation"
+                                android:startOffset="1300"
+                                android:duration="100"
+                                android:valueFrom="?attr/rotateButtonStartAngle"
+                                android:valueTo="?attr/rotateButtonStartAngle"/>
+
+                <!-- Icon rotation with start timing offset after fade in -->
+                <objectAnimator android:propertyName="rotation"
+                                android:duration="600"
+                                android:valueFrom="?attr/rotateButtonStartAngle"
+                                android:valueTo="?attr/rotateButtonEndAngle">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.408,1.181 0.674,1.08 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
+
+                <!-- Reset rotation position for fade in -->
+                <objectAnimator android:propertyName="rotation"
+                                android:startOffset="1300"
+                                android:duration="100"
+                                android:valueFrom="?attr/rotateButtonStartAngle"
+                                android:valueTo="?attr/rotateButtonStartAngle"/>
+
+                <!-- Icon rotation with start timing offset after fade in -->
+                <objectAnimator android:propertyName="rotation"
+                                android:duration="600"
+                                android:valueFrom="?attr/rotateButtonStartAngle"
+                                android:valueTo="?attr/rotateButtonEndAngle">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.408,1.181 0.674,1.08 1.0,1.0"/>
+                    </aapt:attr>
+                </objectAnimator>
             </set>
         </aapt:attr>
     </target>
diff --git a/packages/SystemUI/res/drawable/stat_sys_branded_vpn.xml b/packages/SystemUI/res/drawable/stat_sys_branded_vpn.xml
index a86e5b9..bfae857 100644
--- a/packages/SystemUI/res/drawable/stat_sys_branded_vpn.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_branded_vpn.xml
@@ -20,5 +20,8 @@
         android:viewportHeight="24.0">
     <path
         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"/>
+        android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h6v-3h2V9H12.09zM20,13h-2v3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H20V13z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_no_sims.xml b/packages/SystemUI/res/drawable/stat_sys_no_sims.xml
index faea7d1..5c9be5c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_no_sims.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_no_sims.xml
@@ -19,13 +19,12 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:width="17dp"
     android:height="17dp"
-    android:viewportWidth="18.4"
-    android:viewportHeight="18.4">
-    <group
-        android:translateX="0.7"
-        android:translateY="1.0">
-        <path
-            android:pathData="M13.91,11.84L5.14,3.08l1.81,-1.81h5.41c0.85,0 1.54,0.69 1.54,1.54l0.01,9.03zM15.06,14.95L2.54,2.44c-0.28,-0.28 -0.71,-0.28 -0.99,0s-0.28,0.71 0,0.98l1.53,1.53v8.67c0,0.85 0.69,1.54 1.54,1.54h7.74c0.27,0 0.52,-0.07 0.74,-0.2l0.96,0.96c0.28,0.28 0.71,0.28 0.99,0 0.28,-0.26 0.28,-0.69 0.01,-0.97z"
-            android:fillColor="?attr/backgroundColor"/>
-    </group>
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h6v-3h2V9H12.09zM20,13h-2v3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H20V13z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml b/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
index 66f4fbb..5c9be5c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
@@ -19,13 +19,12 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:width="17dp"
     android:height="17dp"
-    android:viewportWidth="19.0"
-    android:viewportHeight="19.0">
-    <group
-        android:translateX="1.0"
-        android:translateY="1.0">
-        <path
-            android:pathData="M15.46,6.96H9a4.637,4.637 0,0 0,-4.37 -3.09C2.07,3.87 0,5.94 0,8.5s2.07,4.63 4.63,4.63c2.02,0 3.73,-1.29 4.37,-3.09h2.2v1.54a1.54,1.54 0,0 0,3.08 0v-1.54h1.16c0.87,0 1.56,-0.69 1.56,-1.54s-0.69,-1.54 -1.54,-1.54zM4.63,10.04a1.54,1.54 0,1 1,0.001 -3.081,1.54 1.54,0 0,1 -0.001,3.081z"
-            android:fillColor="#FFF"/>
-    </group>
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h6v-3h2V9H12.09zM20,13h-2v3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H20V13z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
 </vector>
diff --git a/packages/SystemUI/res/layout/back.xml b/packages/SystemUI/res/layout/back.xml
index 6843db9..4e8726b 100644
--- a/packages/SystemUI/res/layout/back.xml
+++ b/packages/SystemUI/res/layout/back.xml
@@ -22,10 +22,8 @@
     android:layout_height="match_parent"
     android:layout_weight="0"
     systemui:keyCode="4"
-    android:scaleType="fitCenter"
+    android:scaleType="center"
     android:contentDescription="@string/accessibility_back"
-    android:paddingTop="@dimen/home_padding"
-    android:paddingBottom="@dimen/home_padding"
     android:paddingStart="@dimen/navigation_key_padding"
     android:paddingEnd="@dimen/navigation_key_padding"
     />
diff --git a/packages/SystemUI/res/layout/home.xml b/packages/SystemUI/res/layout/home.xml
index 7b67b79..9586327 100644
--- a/packages/SystemUI/res/layout/home.xml
+++ b/packages/SystemUI/res/layout/home.xml
@@ -21,10 +21,8 @@
     android:layout_height="match_parent"
     android:layout_weight="0"
     systemui:keyCode="3"
-    android:scaleType="fitCenter"
+    android:scaleType="center"
     android:contentDescription="@string/accessibility_home"
-    android:paddingTop="@dimen/home_padding"
-    android:paddingBottom="@dimen/home_padding"
     android:paddingStart="@dimen/navigation_key_padding"
     android:paddingEnd="@dimen/navigation_key_padding"
     />
diff --git a/packages/SystemUI/res/layout/recent_apps.xml b/packages/SystemUI/res/layout/recent_apps.xml
index 6b08cea..870bcf7 100644
--- a/packages/SystemUI/res/layout/recent_apps.xml
+++ b/packages/SystemUI/res/layout/recent_apps.xml
@@ -21,10 +21,8 @@
     android:layout_width="@dimen/navigation_key_width"
     android:layout_height="match_parent"
     android:layout_weight="0"
-    android:scaleType="fitCenter"
+    android:scaleType="center"
     android:contentDescription="@string/accessibility_recent"
-    android:paddingTop="@dimen/home_padding"
-    android:paddingBottom="@dimen/home_padding"
     android:paddingStart="@dimen/navigation_key_padding"
     android:paddingEnd="@dimen/navigation_key_padding"
     />
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index e902c92..b5d48b4 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -42,7 +42,7 @@
             android:singleLine="true"
             android:ellipsize="start"
             android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
-            android:imeOptions="actionSend" />
+            android:imeOptions="actionSend|flagNoExtractUi|flagNoFullscreen" />
 
     <FrameLayout
             android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index cf72d9f..974c80e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Moenie weer wys nie"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Vee alles uit"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Bestuur kennisgewings"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Kennisgewings onderbreek deur Moenie Steur Nie"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Begin nou"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Geen kennisgewings nie"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profiel kan gemonitor word"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 44eebff..612db55 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"ዳግመኛ አታሳይ"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"ሁሉንም አጽዳ"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"ማሳወቂያዎችን ያስተዳድሩ"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"ማሳወቂያዎች በአትረብሽ ባሉበት ቆመዋል"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"አሁን ጀምር"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"ምንም ማሳወቂያ የለም"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"መገለጫ ክትትል ሊደረግበት ይችላል"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 771626b..c975de1 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Daha göstərmə"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Hamısını silin"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Bildirişləri idarə edin"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Bildirişlər \"Narahat Etməyin\" rejimi tərəfindən dayandırıldı"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"İndi başlayın"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Heç bir bildiriş yoxdur"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profil izlənə bilər"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index ee8051e..33a95a6 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -439,8 +439,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj opet"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Očisti sve"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Upravljajte obavještenjima"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Značajka Ne uznemiravaj pauzirala je Obavijesti"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Započni odmah"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Nema obavještenja"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profil može biti nadziran"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 040412d..766b241 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Manage notifications"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do not disturb"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profile may be monitored"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 9b25c7b..306723a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Manage notifications"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do not disturb"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profile may be monitored"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 040412d..766b241 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Manage notifications"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do not disturb"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profile may be monitored"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 040412d..766b241 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Don\'t show again"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Clear all"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Manage notifications"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifications paused by Do not disturb"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Start now"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"No notifications"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profile may be monitored"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 545e15a..11ca904 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎Don\'t show again‎‏‎‎‏‎"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎Clear all‎‏‎‎‏‎"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎Manage notifications‎‏‎‎‏‎"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎Notifications paused by Do Not Disturb‎‏‎‎‏‎"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎Start now‎‏‎‎‏‎"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎No notifications‎‏‎‎‏‎"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎Profile may be monitored‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index d65d6e2..e0d330a 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"دوباره نشان داده نشود"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"پاک کردن همه موارد"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"مدیریت اعلان‌ها"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"اعلان‌ها توسط «مزاحم نشوید» موقتاً متوقف شدند"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"اکنون شروع شود"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"اعلانی موجود نیست"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"شاید نمایه کنترل شود"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 9d47dff..d1980b4 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -438,8 +438,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne plus afficher"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Tout effacer"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Gérer les notifications"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Les notifications sont suspendues par le mode Ne pas déranger"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Commencer"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Aucune notification"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"le profil peut être contrôlé"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 8e131e4..61d72a5 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -439,8 +439,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Ne prikazuj ponovo"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Izbriši sve"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Upravljanje obavijestima"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Značajka Ne uznemiravaj pauzirala je Obavijesti"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Započni sad"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Nema obavijesti"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profil se možda nadzire"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 415d8c9..eb0cf08e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Jangan tampilkan lagi"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Hapus semua"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Kelola notifikasi"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifikasi dijeda oleh mode Jangan Ganggu"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Mulai sekarang"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Tidak ada notifikasi"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profil dapat dipantau"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 41b4860..26b607e 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -438,8 +438,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Non mostrare più"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Cancella tutto"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Gestisci le notifiche"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notifiche messe in pausa in base alla modalità Non disturbare"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Avvia adesso"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Nessuna notifica"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Il profilo potrebbe essere monitorato"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 1c90e95..cc2613b 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -438,8 +438,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"次回から表示しない"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"すべて消去"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"通知を管理する"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"マナーモードにより通知は一時停止中です"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"今すぐ開始"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"通知はありません"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"プロファイルが監視されている可能性があります"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index a602c45..72a897d 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"နောက်ထပ် မပြပါနှင့်"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"အားလုံး ဖယ်ရှားရန်"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"အကြောင်းကြားချက်များကို စီမံရန်"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"အကြောင်းကြားချက်များကို \'မနှောင့်ယှက်ရ\' က ခေတ္တရပ်ထားသည်"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"ယခု စတင်ပါ"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"အကြောင်းကြားချက်များ မရှိ"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"ပရိုဖိုင်ကို စောင့်ကြပ်နိုင်သည်"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 03bee6f..a730586 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Niet opnieuw weergeven"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Alles wissen"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Meldingen beheren"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Meldingen onderbroken door \'Niet storen\'"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Nu starten"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Geen meldingen"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profiel kan worden gecontroleerd"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index f70eecd..074f841 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -438,8 +438,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Não mostrar novamente"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Limpar tudo"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Gerenciar notificações"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificações pausadas pelo modo \"Não perturbe\""</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Iniciar agora"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Sem notificações"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"O perfil pode ser monitorado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index aefd42a..d505ac6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Não mostrar de novo"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Limpar tudo"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Gerir notificações"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificações colocadas em pausa pelo modo Não incomodar."</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Começar agora"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Sem notificações"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"O perfil pode ser monitorizado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index f70eecd..074f841 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -438,8 +438,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Não mostrar novamente"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Limpar tudo"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Gerenciar notificações"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Notificações pausadas pelo modo \"Não perturbe\""</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Iniciar agora"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Sem notificações"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"O perfil pode ser monitorado"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index d3f5ac1..ebfaba6 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"නැවත නොපෙන්වන්න"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"සියල්ල හිස් කරන්න"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"දැනුම් දීම් කළමනාකරණය කරන්න"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"බාධා නොකරන්න මගින් විරාම කරන ලද දැනුම්දීම්"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"දැන් අරඹන්න"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"දැනුම්දීම් නැත"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"ඇතැම් විට පැතිකඩ නිරීක්ෂණය කරන ලදි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 95c0b929..38656ad 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -444,8 +444,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Nabudúce nezobrazovať"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Vymazať všetko"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Spravovať upozornenia"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Upozornenia sú pozastavené režimom Nerušiť"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Spustiť"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Žiadne upozornenia"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profil môže byť monitorovaný"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9645253..5ccfc37 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -444,8 +444,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Tega ne prikaži več"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Izbriši vse"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Upravljanje obvestil"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Prikazovanje obvestil je začasno zaustavljeno z načinom »ne moti«"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Začni zdaj"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Ni obvestil"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profil je morda nadziran"</string>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 923edc8..2dc6525 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -91,7 +91,4 @@
 
     <!-- The offsets the tasks animate from when recents is launched while docking -->
     <dimen name="recents_task_stack_animation_launched_while_docking_offset">192dp</dimen>
-
-    <!-- Home button padding for sizing -->
-    <dimen name="home_padding">0dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 67ba61f..871a250 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -436,8 +436,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Ungabonisi futhi"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Sula konke"</string>
     <string name="manage_notifications_text" msgid="8035284146227267681">"Phatha izaziso"</string>
-    <!-- no translation found for dnd_suppressing_shade_text (1904574852846769301) -->
-    <skip />
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Izaziso zimiswe okwesikhashana ukungaphazamisi"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Qala manje"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Azikho izaziso"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Iphrofayela ingaqashwa"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 3472477..d8607cc 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -104,6 +104,9 @@
     <!-- The color of the navigation bar icons. Need to be in sync with ic_sysbar_* -->
     <color name="navigation_bar_icon_color">#E5FFFFFF</color>
 
+    <!-- The shadow color for light navigation bar icons. -->
+    <color name="nav_key_button_shadow_color">#30000000</color>
+
     <!-- Shadow color for the first pixels around the fake shadow for recents. -->
     <color name="fake_shadow_start_color">#44000000</color>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c1458b2..0024fe4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -34,10 +34,10 @@
     <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
 
     <!-- Height of the battery icon in the status bar. -->
-    <dimen name="status_bar_battery_icon_height">14.5dp</dimen>
+    <dimen name="status_bar_battery_icon_height">13.0dp</dimen>
 
     <!-- Width of the battery icon in the status bar. -->
-    <dimen name="status_bar_battery_icon_width">9.5dp</dimen>
+    <dimen name="status_bar_battery_icon_width">8.5dp</dimen>
 
     <!-- The font size for the clock in the status bar. -->
     <dimen name="status_bar_clock_size">14sp</dimen>
@@ -941,8 +941,10 @@
     <dimen name="nav_quick_scrub_track_edge_padding">42dp</dimen>
     <dimen name="nav_quick_scrub_track_thickness">2dp</dimen>
 
-    <!-- Home button padding for sizing -->
-    <dimen name="home_padding">16dp</dimen>
+    <!-- Navigation bar shadow params. -->
+    <dimen name="nav_key_button_shadow_offset_x">0dp</dimen>
+    <dimen name="nav_key_button_shadow_offset_y">1dp</dimen>
+    <dimen name="nav_key_button_shadow_radius">0.5dp</dimen>
 
     <!-- Smart reply button. Total height 48dp, visible height 32dp. -->
     <dimen name="smart_reply_button_spacing">8dp</dimen>
@@ -960,6 +962,10 @@
             add about 88dp of height to the notifications. -->
     <dimen name="smart_reply_button_max_height">100dp</dimen>
 
+    <!-- The extra height that we allow a notification with a remote input history to be taller than
+         the regular notification, when we have remote input history texts present. -->
+    <dimen name="remote_input_history_extra_height">60dp</dimen>
+
     <!-- Fingerprint Dialog values -->
     <dimen name="fingerprint_dialog_fp_icon_size">64dp</dimen>
     <dimen name="fingerprint_dialog_animation_translation_offset">350dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index c0b10e2..52e1c16 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -47,6 +47,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
+import com.android.systemui.statusbar.AlphaOptimizedTextView;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
@@ -197,6 +198,7 @@
 
             final SliceItem titleItem = rc.getTitleItem();
             button.setText(titleItem == null ? null : titleItem.getText());
+            button.setContentDescription(rc.getContentDescription());
 
             Drawable iconDrawable = null;
             SliceItem icon = SliceQuery.find(item.getSlice(),
@@ -245,7 +247,7 @@
      * @param charSequence Original text.
      * @return Optimal string.
      */
-    private CharSequence findBestLineBreak(CharSequence charSequence) {
+    private static CharSequence findBestLineBreak(CharSequence charSequence) {
         if (TextUtils.isEmpty(charSequence)) {
             return charSequence;
         }
@@ -370,27 +372,6 @@
         mIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.widget_icon_size);
     }
 
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-        // Find best ellipsis strategy for the title.
-        // Done on onMeasure since TextView#getLayout needs a measure pass to calculate its bounds.
-        Layout layout = mTitle.getLayout();
-        if (layout != null) {
-            final int lineCount = layout.getLineCount();
-            if (lineCount > 0) {
-                if (layout.getEllipsisCount(lineCount - 1) == 0) {
-                    CharSequence title = mTitle.getText();
-                    CharSequence bestLineBreak = findBestLineBreak(title);
-                    if (!TextUtils.equals(title, bestLineBreak)) {
-                        mTitle.setText(bestLineBreak);
-                    }
-                }
-            }
-        }
-    }
-
     public void refresh() {
         Slice slice = SliceManager.getInstance(getContext()).bindSlice(mKeyguardSliceUri);
         onChanged(slice);
@@ -553,6 +534,46 @@
         }
     }
 
+    /**
+     * A text view that will split its contents in 2 lines when possible.
+     */
+    static class TitleView extends AlphaOptimizedTextView {
+
+        public TitleView(Context context) {
+            super(context);
+        }
+
+        public TitleView(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public TitleView(Context context, AttributeSet attrs, int defStyleAttr) {
+            super(context, attrs, defStyleAttr);
+        }
+
+        public TitleView(Context context, AttributeSet attrs, int defStyleAttr,
+                int defStyleRes) {
+            super(context, attrs, defStyleAttr, defStyleRes);
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+            Layout layout = getLayout();
+            int lineCount = layout.getLineCount();
+            boolean ellipsizing = layout.getEllipsisCount(lineCount - 1) != 0;
+            if (lineCount > 0 && !ellipsizing) {
+                CharSequence title = getText();
+                CharSequence bestLineBreak = findBestLineBreak(title);
+                if (!TextUtils.equals(title, bestLineBreak)) {
+                    setText(bestLineBreak);
+                    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+                }
+            }
+        }
+    }
+
     private class SliceViewTransitionListener implements LayoutTransition.TransitionListener {
         @Override
         public void startTransition(LayoutTransition transition, ViewGroup container, View view,
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index beb3c53..9c9f021 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -151,7 +151,6 @@
 
     @Override
     public void start() {
-        sDependency = this;
         // TODO: Think about ways to push these creation rules out of Dependency to cut down
         // on imports.
         mProviders.put(TIME_TICK_HANDLER, () -> {
@@ -331,6 +330,8 @@
 
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
+
+        sDependency = this;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index a7163bb..d437555 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -94,6 +94,8 @@
         String OVERVIEW_OPENED_FROM_HOME_COUNT = "OverviewOpenedFromHomeCount";
         String HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING = "HasSeenRecentsSwipeUpOnboarding";
         String HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING = "HasSeenRecentsQuickScrubOnboarding";
+        String DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT =
+                "DismissedRecentsSwipeUpOnboardingCount";
         String HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE =
                 "HasDismissedRecentsQuickScrubOnboardingOnce";
         String SEEN_RINGER_GUIDANCE_COUNT = "RingerGuidanceCount";
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 139215a0..2746a71 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -22,8 +22,8 @@
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 
-import static com.android.systemui.tuner.TunablePadding.FLAG_START;
 import static com.android.systemui.tuner.TunablePadding.FLAG_END;
+import static com.android.systemui.tuner.TunablePadding.FLAG_START;
 
 import android.annotation.Dimension;
 import android.app.Fragment;
@@ -66,6 +66,7 @@
 import com.android.systemui.tuner.TunablePadding;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.leak.RotationUtils;
 
 /**
  * An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
@@ -77,6 +78,9 @@
     private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
             SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
 
+    private DisplayManager mDisplayManager;
+    private DisplayManager.DisplayListener mDisplayListener;
+
     private int mRoundedDefault;
     private int mRoundedDefaultTop;
     private int mRoundedDefaultBottom;
@@ -84,7 +88,7 @@
     private View mBottomOverlay;
     private float mDensity;
     private WindowManager mWindowManager;
-    private boolean mLandscape;
+    private int mRotation;
 
     @Override
     public void start() {
@@ -104,6 +108,28 @@
         if (padding != 0) {
             setupPadding(padding);
         }
+
+        mDisplayListener = new DisplayManager.DisplayListener() {
+            @Override
+            public void onDisplayAdded(int displayId) {
+                // do nothing
+            }
+
+            @Override
+            public void onDisplayRemoved(int displayId) {
+                // do nothing
+            }
+
+            @Override
+            public void onDisplayChanged(int displayId) {
+                updateOrientation();
+            }
+        };
+
+        mRotation = -1;
+        mDisplayManager = (DisplayManager) mContext.getSystemService(
+                Context.DISPLAY_SERVICE);
+        mDisplayManager.registerDisplayListener(mDisplayListener, null);
     }
 
     private void setupDecorations() {
@@ -169,17 +195,22 @@
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
-        boolean newLanscape = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
-        if (newLanscape != mLandscape) {
-            mLandscape = newLanscape;
+        updateOrientation();
+    }
+
+    protected void updateOrientation() {
+        int newRotation = RotationUtils.getExactRotation(mContext);
+        if (newRotation != mRotation) {
+            mRotation = newRotation;
 
             if (mOverlay != null) {
                 updateLayoutParams();
                 updateViews();
             }
-        }
-        if (shouldDrawCutout() && mOverlay == null) {
-            setupDecorations();
+
+            if (shouldDrawCutout() && mOverlay == null) {
+                setupDecorations();
+            }
         }
     }
 
@@ -188,16 +219,28 @@
         View topRight = mOverlay.findViewById(R.id.right);
         View bottomLeft = mBottomOverlay.findViewById(R.id.left);
         View bottomRight = mBottomOverlay.findViewById(R.id.right);
-        if (mLandscape) {
-            // Flip corners
-            View tmp = topRight;
-            topRight = bottomLeft;
-            bottomLeft = tmp;
+
+        if (mRotation == RotationUtils.ROTATION_NONE) {
+            updateView(topLeft, Gravity.TOP | Gravity.LEFT, 0);
+            updateView(topRight, Gravity.TOP | Gravity.RIGHT, 90);
+            updateView(bottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
+            updateView(bottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
+        } else if (mRotation == RotationUtils.ROTATION_LANDSCAPE) {
+            updateView(topLeft, Gravity.TOP | Gravity.LEFT, 0);
+            updateView(topRight, Gravity.BOTTOM | Gravity.LEFT, 270);
+            updateView(bottomLeft, Gravity.TOP | Gravity.RIGHT, 90);;
+            updateView(bottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
+        } else if (mRotation == RotationUtils.ROTATION_UPSIDE_DOWN) {
+            updateView(topLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
+            updateView(topRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
+            updateView(bottomLeft, Gravity.TOP | Gravity.LEFT, 0);
+            updateView(bottomRight, Gravity.TOP | Gravity.RIGHT, 90);
+        } else if (mRotation == RotationUtils.ROTATION_SEASCAPE) {
+            updateView(topLeft, Gravity.BOTTOM | Gravity.RIGHT, 180);
+            updateView(topRight, Gravity.TOP | Gravity.RIGHT, 90);
+            updateView(bottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
+            updateView(bottomRight, Gravity.TOP | Gravity.LEFT, 0);
         }
-        updateView(topLeft, Gravity.TOP | Gravity.LEFT, 0);
-        updateView(topRight, Gravity.TOP | Gravity.RIGHT, 90);
-        updateView(bottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
-        updateView(bottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
 
         updateWindowVisibilities();
     }
@@ -269,9 +312,14 @@
         }
 
         lp.setTitle("ScreenDecorOverlay");
-        lp.gravity = Gravity.TOP | Gravity.LEFT;
+        if (mRotation == RotationUtils.ROTATION_SEASCAPE
+                || mRotation == RotationUtils.ROTATION_UPSIDE_DOWN) {
+            lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+        } else {
+            lp.gravity = Gravity.TOP | Gravity.LEFT;
+        }
         lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-        if (mLandscape) {
+        if (isLandscape(mRotation)) {
             lp.width = WRAP_CONTENT;
             lp.height = MATCH_PARENT;
         }
@@ -281,7 +329,12 @@
     private WindowManager.LayoutParams getBottomLayoutParams() {
         WindowManager.LayoutParams lp = getWindowLayoutParams();
         lp.setTitle("ScreenDecorOverlayBottom");
-        lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+        if (mRotation == RotationUtils.ROTATION_SEASCAPE
+                || mRotation == RotationUtils.ROTATION_UPSIDE_DOWN) {
+            lp.gravity = Gravity.TOP | Gravity.LEFT;
+        } else {
+            lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+        }
         return lp;
     }
 
@@ -568,4 +621,9 @@
             return cutoutBounds;
         }
     }
+
+    private boolean isLandscape(int rotation) {
+        return rotation == RotationUtils.ROTATION_LANDSCAPE || rotation ==
+                RotationUtils.ROTATION_SEASCAPE;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 721890f..03a6398 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.policy.SmartReplyConstants;
 
 import java.util.function.Consumer;
@@ -148,5 +149,7 @@
         providers.put(NotificationEntryManager.class, () -> new NotificationEntryManager(context));
         providers.put(KeyguardDismissUtil.class, KeyguardDismissUtil::new);
         providers.put(SmartReplyController.class, () -> new SmartReplyController());
+        providers.put(RemoteInputQuickSettingsDisabler.class,
+                () -> new RemoteInputQuickSettingsDisabler(context));
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index e9d78d9..e2047bf 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -69,7 +69,7 @@
                 new DozeScreenState(wrappedService, handler, params, wakeLock),
                 createDozeScreenBrightness(context, wrappedService, sensorManager, host, params,
                         handler),
-                new DozeWallpaperState(context, params)
+                new DozeWallpaperState(context)
         });
 
         return machine;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 90140ff..f14d396 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -42,7 +42,7 @@
      * hiding the wallpaper and changing the display mode is necessary to hide
      * the black frame that's inherent to hardware specs.
      */
-    public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 2000;
+    public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 4500;
 
     private final DozeMachine.Service mDozeService;
     private final Handler mHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 9d110fb..47f86fe 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -38,40 +38,33 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final IWallpaperManager mWallpaperManagerService;
-    private boolean mKeyguardVisible;
     private boolean mIsAmbientMode;
     private final DozeParameters mDozeParameters;
 
-    public DozeWallpaperState(Context context, DozeParameters dozeParameters) {
+    public DozeWallpaperState(Context context) {
         this(IWallpaperManager.Stub.asInterface(
                 ServiceManager.getService(Context.WALLPAPER_SERVICE)),
-                dozeParameters, KeyguardUpdateMonitor.getInstance(context));
+                DozeParameters.getInstance(context));
     }
 
     @VisibleForTesting
-    DozeWallpaperState(IWallpaperManager wallpaperManagerService, DozeParameters parameters,
-            KeyguardUpdateMonitor keyguardUpdateMonitor) {
+    DozeWallpaperState(IWallpaperManager wallpaperManagerService, DozeParameters parameters) {
         mWallpaperManagerService = wallpaperManagerService;
         mDozeParameters = parameters;
-        keyguardUpdateMonitor.registerCallback(new KeyguardUpdateMonitorCallback() {
-            @Override
-            public void onKeyguardVisibilityChanged(boolean showing) {
-                mKeyguardVisible = showing;
-            }
-        });
     }
 
     @Override
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
         final boolean isAmbientMode;
         switch (newState) {
+            case DOZE:
             case DOZE_AOD:
             case DOZE_AOD_PAUSING:
             case DOZE_AOD_PAUSED:
             case DOZE_REQUEST_PULSE:
             case DOZE_PULSING:
             case DOZE_PULSE_DONE:
-                isAmbientMode = mDozeParameters.getAlwaysOn();
+                isAmbientMode = true;
                 break;
             default:
                 isAmbientMode = false;
@@ -81,7 +74,9 @@
         if (isAmbientMode) {
             animated = mDozeParameters.shouldControlScreenOff();
         } else {
-            animated = !mDozeParameters.getDisplayNeedsBlanking();
+            boolean wakingUpFromPulse = oldState == DozeMachine.State.DOZE_PULSING
+                    && newState == DozeMachine.State.FINISH;
+            animated = !mDozeParameters.getDisplayNeedsBlanking() || wakingUpFromPulse;
         }
 
         if (isAmbientMode != mIsAmbientMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index c5e66f9..8b9bf77 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -151,6 +151,8 @@
             return;
         }
         RowBuilder dndBuilder = new RowBuilder(builder, mDndUri)
+                .setContentDescription(getContext().getResources()
+                        .getString(R.string.accessibility_quick_settings_dnd))
                 .addEndItem(Icon.createWithResource(getContext(), R.drawable.stat_sys_dnd));
         builder.addRow(dndBuilder);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index cbd1ca1..b146cfc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -35,6 +35,7 @@
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout.LayoutParams;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.R.id;
@@ -43,6 +44,7 @@
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 public class QSFragment extends Fragment implements QS, CommandQueue.Callbacks {
@@ -72,6 +74,9 @@
     private float mLastQSExpansion = -1;
     private boolean mQsDisabled;
 
+    private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler =
+            Dependency.get(RemoteInputQuickSettingsDisabler.class);
+
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
             Bundle savedInstanceState) {
@@ -191,6 +196,8 @@
 
     @Override
     public void disable(int state1, int state2, boolean animate) {
+        state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2);
+
         final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
         if (disabled == mQsDisabled) return;
         mQsDisabled = disabled;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 89f86c5..23e3f25 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -110,7 +110,8 @@
 
         @Override
         public Drawable getDrawable(Context context) {
-            BatterySaverDrawable b = new BatterySaverDrawable(context, 0);
+            BatterySaverDrawable b =
+                    new BatterySaverDrawable(context, QSTileImpl.getColorForState(context, mState));
             b.mState = mState;
             final int pad = context.getResources()
                     .getDimensionPixelSize(R.dimen.qs_tile_divider_height);
@@ -130,11 +131,16 @@
             setPowerSave(true);
             setCharging(false);
             setPowerSaveAsColorError(false);
+            mPowerSaveAsColorError = true;
+            mFramePaint.setColor(0);
+            mPowersavePaint.setColor(frameColor);
+            mFramePaint.setStrokeWidth(mPowersavePaint.getStrokeWidth());
+            mPlusPaint.setColor(frameColor);
         }
 
         @Override
         protected int batteryColorForLevel(int level) {
-            return QSTileImpl.getColorForState(mContext, mState);
+            return 0;
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 6fcb1c1..7e4acc2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -123,10 +123,16 @@
      */
     class TaskStackListenerImpl extends SysUiTaskStackChangeListener {
 
+        private OverviewProxyService mOverviewProxyService;
+
+        public TaskStackListenerImpl() {
+            mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+        }
+
         @Override
         public void onTaskStackChangedBackground() {
             // Skip background preloading recents in SystemUI if the overview services is bound
-            if (Dependency.get(OverviewProxyService.class).isEnabled()) {
+            if (mOverviewProxyService.isEnabled()) {
                 return;
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index ff0c11d..bcc33d2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -20,6 +20,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 
 import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
+import static com.android.systemui.Prefs.Key.DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT;
 import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING;
 import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING;
 import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
@@ -87,9 +88,17 @@
     private static final int SWIPE_UP_SHOW_ON_OVERVIEW_OPENED_FROM_HOME_COUNT = 3;
     // Show quick scrub tips after opening overview this number of times.
     private static final int QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT = 10;
-    // After explicitly dismissing, show again after launching this number of apps for swipe-up
-    // tips.
+    // Maximum number of dismissals while still showing swipe-up tips.
+    private static final int MAX_DISMISSAL_ON_SWIPE_UP_SHOW = 4;
+    // Number of dismissals for swipe-up tips when exponential backoff starts.
+    private static final int BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW = 2;
+    // After explicitly dismissing for <= BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW times, show again
+    // after launching this number of apps for swipe-up tips.
     private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS = 5;
+    // After explicitly dismissing for > BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW but
+    // <= MAX_DISMISSAL_ON_SWIPE_UP_SHOW times, show again after launching this number of apps for
+    // swipe-up tips.
+    private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS_BACK_OFF = 10;
 
     private final Context mContext;
     private final WindowManager mWindowManager;
@@ -152,9 +161,20 @@
                     if (getOpenedOverviewFromHomeCount()
                             >= SWIPE_UP_SHOW_ON_OVERVIEW_OPENED_FROM_HOME_COUNT) {
                         if (mHasDismissedSwipeUpTip) {
+                            int hasDimissedSwipeUpOnboardingCount =
+                                    getDismissedSwipeUpOnboardingCount();
+                            if (hasDimissedSwipeUpOnboardingCount > MAX_DISMISSAL_ON_SWIPE_UP_SHOW) {
+                                Log.d(TAG, "Should not be reached");
+                                return;
+                            }
+                            final int swipeUpShowOnAppLauncherAfterDismiss =
+                                    hasDimissedSwipeUpOnboardingCount
+                                            <= BACKOFF_DISMISSAL_COUNT_ON_SWIPE_UP_SHOW
+                                            ? SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS
+                                            : SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS_BACK_OFF;
                             mNumAppsLaunchedSinceSwipeUpTipDismiss++;
                             if (mNumAppsLaunchedSinceSwipeUpTipDismiss
-                                    == SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS) {
+                                    == swipeUpShowOnAppLauncherAfterDismiss) {
                                 mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
                                 shouldLog = show(R.string.recents_swipe_up_onboarding);
                             }
@@ -286,6 +306,10 @@
             if (v.getTag().equals(R.string.recents_swipe_up_onboarding)) {
                 mHasDismissedSwipeUpTip = true;
                 mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
+                setDismissedSwipeUpOnboardingCount(getDismissedSwipeUpOnboardingCount() + 1);
+                if (getDismissedSwipeUpOnboardingCount() > MAX_DISMISSAL_ON_SWIPE_UP_SHOW) {
+                    setHasSeenSwipeUpOnboarding(true);
+                }
                 notifyOnTip(DISMISS, RECENTS_SWIPE_UP_ONBOARDING_TIP);
             } else {
                 notifyOnTip(DISMISS, RECENTS_QUICK_SCRUB_ONBOARDING_TIP);
@@ -304,6 +328,7 @@
         if (RESET_PREFS_FOR_DEBUG) {
             setHasSeenSwipeUpOnboarding(false);
             setHasSeenQuickScrubOnboarding(false);
+            setDismissedSwipeUpOnboardingCount(0);
             setHasDismissedQuickScrubOnboardingOnce(false);
             setOpenedOverviewCount(0);
             setOpenedOverviewFromHomeCount(0);
@@ -440,6 +465,8 @@
                 + mNumAppsLaunchedSinceSwipeUpTipDismiss);
         pw.println("      hasSeenSwipeUpOnboarding: " + hasSeenSwipeUpOnboarding());
         pw.println("      hasSeenQuickScrubOnboarding: " + hasSeenQuickScrubOnboarding());
+        pw.println("      getDismissedSwipeUpOnboardingCount: "
+                + getDismissedSwipeUpOnboardingCount());
         pw.println("      hasDismissedQuickScrubOnboardingOnce: "
                 + hasDismissedQuickScrubOnboardingOnce());
         pw.println("      getOpenedOverviewCount: " + getOpenedOverviewCount());
@@ -488,6 +515,16 @@
         }
     }
 
+    private int getDismissedSwipeUpOnboardingCount() {
+        return Prefs.getInt(mContext, DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT, 0);
+    }
+
+    private void setDismissedSwipeUpOnboardingCount(int dismissedSwipeUpOnboardingCount) {
+        Log.d(TAG, "setDismissedSwipeUpOnboardingCount: " + dismissedSwipeUpOnboardingCount);
+        Prefs.putInt(mContext, DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT,
+                dismissedSwipeUpOnboardingCount);
+    }
+
     private boolean hasDismissedQuickScrubOnboardingOnce() {
         return Prefs.getBoolean(mContext, HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE, false);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 167df8c..481d54f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -28,6 +28,7 @@
 import android.os.Binder;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
+import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -40,6 +41,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.statusbar.phone.NavigationBarView;
@@ -259,10 +261,16 @@
             }
 
             if (navigationBarView != null) {
+                int dualToneDarkTheme = Utils.getThemeAttr(getContext(), R.attr.darkIconTheme);
+                int dualToneLightTheme = Utils.getThemeAttr(getContext(), R.attr.lightIconTheme);
+                Context lightContext = new ContextThemeWrapper(getContext(), dualToneLightTheme);
+                Context darkContext = new ContextThemeWrapper(getContext(), dualToneDarkTheme);
                 ((ImageView) mLayout.findViewById(R.id.screen_pinning_back_icon))
-                        .setImageDrawable(navigationBarView.getBackDrawable(mContext));
+                        .setImageDrawable(navigationBarView.getBackDrawable(lightContext,
+                                darkContext));
                 ((ImageView) mLayout.findViewById(R.id.screen_pinning_home_icon))
-                        .setImageDrawable(navigationBarView.getHomeDrawable(mContext));
+                        .setImageDrawable(navigationBarView.getHomeDrawable(lightContext,
+                                darkContext));
             }
 
             ((TextView) mLayout.findViewById(R.id.screen_pinning_description))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
index 5e03fbf..9f82bcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
@@ -19,8 +19,10 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.view.DisplayCutout;
 import android.view.View;
 import android.widget.TextView;
 
@@ -44,8 +46,10 @@
     private boolean mPublicMode;
     private int mMaxWidth;
     private View mRootView;
-    private int mLeftInset;
+    private int mSysWinInset;
+    private int mCutOutInset;
     private Rect mIconDrawingRect = new Rect();
+    private Point mPoint;
     private Runnable mOnDrawingRectChangedListener;
 
     public HeadsUpStatusBarView(Context context) {
@@ -136,9 +140,20 @@
         int bottom = top + mIconPlaceholder.getHeight();
         mLayoutedIconRect.set(left, top, right, bottom);
         updateDrawingRect();
-        int targetPadding = mAbsoluteStartPadding + mLeftInset;
+        int targetPadding = mAbsoluteStartPadding + mSysWinInset + mCutOutInset;
         if (left != targetPadding) {
-            int newPadding = targetPadding - left + getPaddingStart();
+            int start;
+            if (isLayoutRtl()) {
+                if (mPoint == null) {
+                    mPoint = new Point();
+                }
+                getDisplay().getRealSize(mPoint);
+                start = (mPoint.x - right);
+            } else {
+                start = left;
+            }
+
+            int newPadding = targetPadding - start + getPaddingStart();
             setPaddingRelative(newPadding, 0, mEndMargin, 0);
         }
         if (mFirstLayout) {
@@ -150,9 +165,12 @@
         }
     }
 
-    @Override
-    public void setTranslationX(float translationX) {
-        super.setTranslationX(translationX);
+    public void setPanelTranslation(float translationX) {
+        if (isLayoutRtl()) {
+            setTranslationX(translationX + mCutOutInset);
+        } else {
+            setTranslationX(translationX - mCutOutInset);
+        }
         updateDrawingRect();
     }
 
@@ -167,7 +185,21 @@
 
     @Override
     protected boolean fitSystemWindows(Rect insets) {
-        mLeftInset = insets.left;
+        boolean isRtl = isLayoutRtl();
+        mSysWinInset = isRtl ? insets.right : insets.left;
+        DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout();
+        mCutOutInset = (displayCutout != null)
+                ? (isRtl ? displayCutout.getSafeInsetRight() : displayCutout.getSafeInsetLeft())
+                : 0;
+        // For Double Cut Out mode, the System window navigation bar is at the right
+        // side of the left cut out. In this condition, mSysWinInset include the left cut
+        // out width so we set mCutOutInset to be 0. For RTL, the condition is the same.
+        // The navigation bar is at the left side of the right cut out and include the
+        // right cut out width.
+        if (mSysWinInset != 0) {
+            mCutOutInset = 0;
+        }
+
         return super.fitSystemWindows(insets);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 952c961..70dad19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -189,6 +189,7 @@
             if (mExpandedSmartReplyView != null) {
                 notificationMaxHeight += mExpandedSmartReplyView.getHeightUpperLimit();
             }
+            notificationMaxHeight += mExpandedWrapper.getExtraMeasureHeight();
             int size = notificationMaxHeight;
             ViewGroup.LayoutParams layoutParams = mExpandedChild.getLayoutParams();
             boolean useExactly = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 419e262..e24d65a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -32,10 +32,13 @@
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
+import android.app.Person;
 import android.content.Context;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.service.notification.NotificationListenerService.Ranking;
@@ -50,6 +53,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.ForegroundServiceController;
@@ -117,6 +121,11 @@
          */
         public Boolean mIsSystemNotification;
 
+        /**
+         * Has the user sent a reply through this Notification.
+         */
+        private boolean hasSentReply;
+
         public Entry(StatusBarNotification n) {
             this.key = n.getKey();
             this.notification = n;
@@ -298,6 +307,40 @@
             lastRemoteInputSent = NOT_LAUNCHED_YET;
             remoteInputTextWhenReset = null;
         }
+
+        public void setHasSentReply() {
+            hasSentReply = true;
+        }
+
+        public boolean isLastMessageFromReply() {
+            if (!hasSentReply) {
+                return false;
+            }
+            Bundle extras = notification.getNotification().extras;
+            CharSequence[] replyTexts = extras.getCharSequenceArray(
+                    Notification.EXTRA_REMOTE_INPUT_HISTORY);
+            if (!ArrayUtils.isEmpty(replyTexts)) {
+                return true;
+            }
+            Parcelable[] messages = extras.getParcelableArray(Notification.EXTRA_MESSAGES);
+            if (messages != null && messages.length > 0) {
+                Parcelable message = messages[messages.length - 1];
+                if (message instanceof Bundle) {
+                    Notification.MessagingStyle.Message lastMessage =
+                            Notification.MessagingStyle.Message.getMessageFromBundle(
+                                    (Bundle) message);
+                    if (lastMessage != null) {
+                        Person senderPerson = lastMessage.getSenderPerson();
+                        if (senderPerson == null) {
+                            return true;
+                        }
+                        Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON);
+                        return Objects.equals(user, senderPerson);
+                    }
+                }
+            }
+            return false;
+        }
     }
 
     private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 2b7ab10..e52829a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -300,9 +300,11 @@
 
     private void saveImportance() {
         if (!mIsNonblockable) {
-            // Only go through the lock screen/bouncer if the user didn't hit 'Keep showing'.
+            // Only go through the lock screen/bouncer if the user hit 'Stop notifications'.
+            // Otherwise, update the importance immediately.
             if (mCheckSaveListener != null
-                    && !NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING.equals(mExitReason)) {
+                    && NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS.equals(
+                            mExitReason)) {
                 mCheckSaveListener.checkSave(this::updateImportance, mSbn);
             } else {
                 updateImportance();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 04c500f..d6bef12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -88,6 +88,17 @@
         super(context, attrs, defStyleAttr, defStyleRes);
     }
 
+    @Override
+    public void getDrawingRect(Rect outRect) {
+        super.getDrawingRect(outRect);
+        float translationX = getTranslationX();
+        float translationY = getTranslationY();
+        outRect.left += translationX;
+        outRect.right += translationX;
+        outRect.top += translationY;
+        outRect.bottom += translationY;
+    }
+
     private void init() {
         mMobileGroup = findViewById(R.id.mobile_group);
         mMobile = findViewById(R.id.mobile_signal);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index ca00a5a..59a0adc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -151,6 +151,17 @@
         return mVisibleState;
     }
 
+    @Override
+    public void getDrawingRect(Rect outRect) {
+        super.getDrawingRect(outRect);
+        float translationX = getTranslationX();
+        float translationY = getTranslationY();
+        outRect.left += translationX;
+        outRect.right += translationX;
+        outRect.top += translationY;
+        outRect.bottom += translationY;
+    }
+
     private void init() {
         int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
         int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
index 7a8d22b..dabe23e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
@@ -28,4 +28,15 @@
         CarStatusBar statusBar = (CarStatusBar) mStatusBar;
         statusBar.setNavBarVisibility(navBarVisible ? View.VISIBLE : View.GONE);
     }
+
+    /**
+     * Car is a multi-user system.  There's a cancel button on the bouncer that allows the user to
+     * go back to the user switcher and select another user.  Different user may have different
+     * security mode which requires bouncer container to be resized.  For this reason, the bouncer
+     * view is destroyed on cancel.
+     */
+    @Override
+    protected boolean shouldDestroyViewOnReset() {
+        return true;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 68e47f7..aaf1989 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -102,7 +102,8 @@
                 // Don't display guests in the switcher.
                 continue;
             }
-            boolean isForeground = mUserManagerHelper.getForegroundUserId() == userInfo.id;
+            boolean isForeground =
+                mUserManagerHelper.getForegroundUserId() == userInfo.id;
             UserRecord record = new UserRecord(userInfo, false /* isStartGuestSession */,
                     false /* isAddUser */, isForeground);
             userRecords.add(record);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index 2d983c4..03791c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -34,6 +34,7 @@
 import com.android.internal.util.NotificationColorUtil;
 import com.android.internal.widget.NotificationActionListLayout;
 import com.android.systemui.Dependency;
+import com.android.systemui.R;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -58,6 +59,7 @@
     private NotificationActionListLayout mActions;
     private ArraySet<PendingIntent> mCancelledPendingIntents = new ArraySet<>();
     private UiOffloadThread mUiOffloadThread;
+    private View mRemoteInputHistory;
 
     protected NotificationTemplateViewWrapper(Context ctx, View view,
             ExpandableNotificationRow row) {
@@ -146,6 +148,8 @@
         mActionsContainer = mView.findViewById(com.android.internal.R.id.actions_container);
         mActions = mView.findViewById(com.android.internal.R.id.actions);
         mReplyAction = mView.findViewById(com.android.internal.R.id.reply_icon_action);
+        mRemoteInputHistory = mView.findViewById(
+                com.android.internal.R.id.notification_material_reply_container);
         updatePendingIntentCancellations();
     }
 
@@ -329,6 +333,10 @@
         if (mActions != null) {
             extra = mActions.getExtraMeasureHeight();
         }
+        if (mRemoteInputHistory != null && mRemoteInputHistory.getVisibility() != View.GONE) {
+            extra += mRow.getContext().getResources().getDimensionPixelSize(
+                    R.dimen.remote_input_history_extra_height);
+        }
         return extra + super.getExtraMeasureHeight();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 06f3c50..b52e324 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -16,8 +16,10 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.view.View;
+import android.view.WindowInsets;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
@@ -59,6 +61,7 @@
     private final View.OnLayoutChangeListener mStackScrollLayoutChangeListener =
             (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
                     -> updatePanelTranslation();
+    Point mPoint;
 
     public HeadsUpAppearanceController(
             NotificationIconAreaController notificationIconAreaController,
@@ -121,9 +124,55 @@
         updateHeader(headsUp.getEntry());
     }
 
+    /** To count the distance from the window right boundary to scroller right boundary. The
+     * distance formula is the following:
+     *     Y = screenSize - (SystemWindow's width + Scroller.getRight())
+     * There are four modes MUST to be considered in Cut Out of RTL.
+     * No Cut Out:
+     *   Scroller + NB
+     *   NB + Scroller
+     *     => SystemWindow = NavigationBar's width
+     *     => Y = screenSize - (SystemWindow's width + Scroller.getRight())
+     * Corner Cut Out or Tall Cut Out:
+     *   cut out + Scroller + NB
+     *   NB + Scroller + cut out
+     *     => SystemWindow = NavigationBar's width
+     *     => Y = screenSize - (SystemWindow's width + Scroller.getRight())
+     * Double Cut Out:
+     *   cut out left + Scroller + (NB + cut out right)
+     *     SystemWindow = NavigationBar's width + cut out right width
+     *     => Y = screenSize - (SystemWindow's width + Scroller.getRight())
+     *   (cut out left + NB) + Scroller + cut out right
+     *     SystemWindow = NavigationBar's width + cut out left width
+     *     => Y = screenSize - (SystemWindow's width + Scroller.getRight())
+     * @return the translation X value for RTL. In theory, it should be negative. i.e. -Y
+     */
+    private int getRtlTranslation() {
+        // TODO: Corner Cut Out still need to handle.
+        if (mPoint == null) {
+            mPoint = new Point();
+        }
+
+        int realDisplaySize = 0;
+        if (mStackScroller.getDisplay() != null) {
+            mStackScroller.getDisplay().getRealSize(mPoint);
+            realDisplaySize = mPoint.x;
+        }
+
+        WindowInsets windowInset = mStackScroller.getRootWindowInsets();
+        return windowInset.getSystemWindowInsetLeft() + mStackScroller.getRight()
+                + windowInset.getSystemWindowInsetRight() - realDisplaySize;
+    }
+
     public void updatePanelTranslation() {
-        float newTranslation = mStackScroller.getLeft() + mStackScroller.getTranslationX();
-        mHeadsUpStatusBarView.setTranslationX(newTranslation);
+        float newTranslation;
+        if (mStackScroller.isLayoutRtl()) {
+            newTranslation = getRtlTranslation();
+        } else {
+            newTranslation = mStackScroller.getLeft();
+        }
+        newTranslation += mStackScroller.getTranslationX();
+        mHeadsUpStatusBarView.setPanelTranslation(newTranslation);
     }
 
     private void updateTopEntry() {
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 2a37845f..68359bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -608,7 +608,7 @@
     private int computeRotationProposalTimeout() {
         if (mAccessibilityFeedbackEnabled) return 20000;
         if (mHoveringRotationSuggestion) return 16000;
-        return 6000;
+        return 10000;
     }
 
     private boolean isRotateSuggestionIntroduced() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 98672b2..a907bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -39,7 +39,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.support.annotation.ColorInt;
 import android.util.AttributeSet;
@@ -119,7 +118,7 @@
     private Rect mRotationButtonBounds = new Rect();
     private int[] mTmpPosition = new int[2];
 
-    private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
+    private KeyButtonDrawable mBackIcon;
     private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
     private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
     private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
@@ -453,6 +452,7 @@
                 && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
     }
 
+    // TODO(b/80003212): change car mode icons to vector icons.
     private void updateCarModeIcons(Context ctx) {
         mBackCarModeIcon = getDrawable(ctx,
                 R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
@@ -469,33 +469,27 @@
     }
 
     private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
+        int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
+        int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
+        Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
+        Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
+
         if (oldConfig.orientation != newConfig.orientation
                 || oldConfig.densityDpi != newConfig.densityDpi) {
-            mDockedIcon = getDrawable(ctx,
-                    R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
-            mHomeDefaultIcon = getHomeDrawable(ctx);
+            mDockedIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_docked);
+            mHomeDefaultIcon = getHomeDrawable(lightContext, darkContext);
         }
         if (oldConfig.densityDpi != newConfig.densityDpi
                 || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
-            mBackIcon = getBackDrawable(ctx);
-            mBackLandIcon = mBackIcon;
-            mBackAltIcon = getBackImeDrawable(ctx);
-            mBackAltLandIcon = mBackAltIcon;
-            mRecentIcon = getDrawable(ctx,
-                    R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
-            mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
+            mBackIcon = getBackDrawable(lightContext, darkContext);
+            mRecentIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_recent);
+            mMenuIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_menu);
 
-            int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
-            int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
-            Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
-            Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
+            mAccessibilityIcon = getDrawable(lightContext, darkContext,
+                    R.drawable.ic_sysbar_accessibility_button, false /* hasShadow */);
 
-            mAccessibilityIcon = getDrawable(darkContext, lightContext,
-                    R.drawable.ic_sysbar_accessibility_button,
-                    R.drawable.ic_sysbar_accessibility_button);
-
-            mImeIcon = getDrawable(darkContext, lightContext,
-                    R.drawable.ic_ime_switcher_default, R.drawable.ic_ime_switcher_default);
+            mImeIcon = getDrawable(lightContext, darkContext, R.drawable.ic_ime_switcher_default,
+                    false /* hasShadow */);
 
             updateRotateSuggestionButtonStyle(mRotateBtnStyle, false);
 
@@ -505,42 +499,58 @@
         }
     }
 
-    public KeyButtonDrawable getBackDrawable(Context ctx) {
-        return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_back,
-                R.drawable.ic_sysbar_back_dark, R.drawable.ic_sysbar_back_quick_step,
-                R.drawable.ic_sysbar_back_quick_step_dark);
+    public KeyButtonDrawable getBackDrawable(Context lightContext, Context darkContext) {
+        KeyButtonDrawable drawable = chooseNavigationIconDrawable(lightContext, darkContext,
+                R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_quick_step);
+        orientBackButton(drawable);
+        return drawable;
     }
 
-    public KeyButtonDrawable getBackImeDrawable(Context ctx) {
-        return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_back_ime,
-                R.drawable.ic_sysbar_back_ime_dark, R.drawable.ic_sysbar_back_ime_quick_step,
-                R.drawable.ic_sysbar_back_ime_quick_step_dark);
+    public KeyButtonDrawable getHomeDrawable(Context lightContext, Context darkContext) {
+        final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
+        KeyButtonDrawable drawable = quickStepEnabled
+                ? getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home_quick_step)
+                : getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home,
+                        false /* hasShadow */);
+        orientHomeButton(drawable);
+        return drawable;
     }
 
-    public KeyButtonDrawable getHomeDrawable(Context ctx) {
-        return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_home,
-                R.drawable.ic_sysbar_home_dark, R.drawable.ic_sysbar_home_quick_step,
-                R.drawable.ic_sysbar_home_quick_step_dark);
+    private void orientBackButton(KeyButtonDrawable drawable) {
+        final boolean useAltBack =
+            (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+        drawable.setRotation(useAltBack
+                ? -90 : (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) ? 180 : 0);
     }
 
-    private KeyButtonDrawable chooseNavigationIconDrawable(Context ctx, @DrawableRes int iconLight,
-            @DrawableRes int iconDark, @DrawableRes int quickStepIconLight,
-            @DrawableRes int quickStepIconDark) {
+    private void orientHomeButton(KeyButtonDrawable drawable) {
+        drawable.setRotation(mVertical ? 90 : 0);
+    }
+
+    private KeyButtonDrawable chooseNavigationIconDrawable(Context lightContext,
+            Context darkContext, @DrawableRes int icon, @DrawableRes int quickStepIcon) {
         final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
         return quickStepEnabled
-                ? getDrawable(ctx, quickStepIconLight, quickStepIconDark)
-                : getDrawable(ctx, iconLight, iconDark);
+                ? getDrawable(lightContext, darkContext, quickStepIcon)
+                : getDrawable(lightContext, darkContext, icon);
+    }
+
+    private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
+            @DrawableRes int icon) {
+        return getDrawable(lightContext, darkContext, icon, true /* hasShadow */);
+    }
+
+    private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
+            @DrawableRes int icon, boolean hasShadow) {
+        return KeyButtonDrawable.create(lightContext, lightContext.getDrawable(icon),
+                darkContext.getDrawable(icon), hasShadow);
     }
 
     private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
             @DrawableRes int darkIcon) {
-        return getDrawable(ctx, ctx, lightIcon, darkIcon);
-    }
-
-    private KeyButtonDrawable getDrawable(Context darkContext, Context lightContext,
-            @DrawableRes int lightIcon, @DrawableRes int darkIcon) {
-        return KeyButtonDrawable.create(lightContext.getDrawable(lightIcon),
-                darkContext.getDrawable(darkIcon));
+        // Legacy image icons using separate light and dark images will not support shadows
+        return KeyButtonDrawable.create(ctx, ctx.getDrawable(lightIcon),
+            ctx.getDrawable(darkIcon), false /* hasShadow */);
     }
 
     private TintedKeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
@@ -557,13 +567,13 @@
 
     private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
         return landscape
-                ? carMode ? mBackAltLandCarModeIcon : mBackAltLandIcon
-                : carMode ? mBackAltCarModeIcon : mBackAltIcon;
+                ? carMode ? mBackAltLandCarModeIcon : mBackIcon
+                : carMode ? mBackAltCarModeIcon : mBackIcon;
     }
 
     private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
         return landscape
-                ? carMode ? mBackLandCarModeIcon : mBackLandIcon
+                ? carMode ? mBackLandCarModeIcon : mBackIcon
                 : carMode ? mBackCarModeIcon : mBackIcon;
     }
 
@@ -600,20 +610,21 @@
         // We have to replace or restore the back and home button icons when exiting or entering
         // carmode, respectively. Recents are not available in CarMode in nav bar so change
         // to recent icon is not required.
-        KeyButtonDrawable backIcon
-                = ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0)
-                        ? getBackIconWithAlt(mUseCarModeUi, mVertical)
-                        : getBackIcon(mUseCarModeUi, mVertical);
+        final boolean useAltBack =
+                (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+        KeyButtonDrawable backIcon = useAltBack
+                ? getBackIconWithAlt(mUseCarModeUi, mVertical)
+                : getBackIcon(mUseCarModeUi, mVertical);
+        KeyButtonDrawable homeIcon = mUseCarModeUi ? mHomeCarModeIcon : mHomeDefaultIcon;
+        if (!mUseCarModeUi) {
+            orientBackButton(backIcon);
+            orientHomeButton(homeIcon);
+        }
+        getHomeButton().setImageDrawable(homeIcon);
         getBackButton().setImageDrawable(backIcon);
 
         updateRecentsIcon();
 
-        if (mUseCarModeUi) {
-            getHomeButton().setImageDrawable(mHomeCarModeIcon);
-        } else {
-            getHomeButton().setImageDrawable(mHomeDefaultIcon);
-        }
-
         // Update IME button visibility, a11y and rotate button always overrides the appearance
         final boolean showImeButton =
                 !mShowAccessibilityButton &&
@@ -640,8 +651,7 @@
         // Always disable recents when alternate car mode UI is active.
         boolean disableRecent = mUseCarModeUi || !isOverviewEnabled();
 
-        boolean disableBack = ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
-                && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
+        boolean disableBack = ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && !useAltBack;
 
         // When screen pinning, don't hide back and home when connected service or back and
         // recents buttons when disconnected from launcher service in screen pinning mode,
@@ -945,6 +955,7 @@
     }
 
     private void updateRecentsIcon() {
+        mDockedIcon.setRotation(mDockedStackExists && mVertical ? 90 : 0);
         getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
         mBarTransitions.reapplyDarkIntensity();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index b043100..44d666e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -141,7 +141,7 @@
     }
 
     protected boolean shouldShowNotificationIcon(NotificationData.Entry entry,
-            boolean showAmbient, boolean hideDismissed) {
+            boolean showAmbient, boolean hideDismissed, boolean hideRepliedMessages) {
         if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
             return false;
         }
@@ -155,6 +155,10 @@
             return false;
         }
 
+        if (hideRepliedMessages && entry.isLastMessageFromReply()) {
+            return false;
+        }
+
         // showAmbient == show in shade but not shelf
         if (!showAmbient && mEntryManager.getNotificationData().shouldSuppressStatusBar(entry)) {
             return false;
@@ -170,14 +174,15 @@
 
         updateStatusBarIcons();
         updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
-                NotificationShelf.SHOW_AMBIENT_ICONS, false /* hideDismissed */);
+                NotificationShelf.SHOW_AMBIENT_ICONS, false /* hideDismissed */,
+                false /* hideRepliedMessages */);
 
         applyNotificationIconsTint();
     }
 
-    private void updateStatusBarIcons() {
+    public void updateStatusBarIcons() {
         updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
-                false /* showAmbient */, true /* hideDismissed */);
+                false /* showAmbient */, true /* hideDismissed */, true /* hideRepliedMessages */);
     }
 
     /**
@@ -187,9 +192,11 @@
      * @param hostLayout which layout should be updated
      * @param showAmbient should ambient notification icons be shown
      * @param hideDismissed should dismissed icons be hidden
+     * @param hideRepliedMessages should messages that have been replied to be hidden
      */
     private void updateIconsForLayout(Function<NotificationData.Entry, StatusBarIconView> function,
-            NotificationIconContainer hostLayout, boolean showAmbient, boolean hideDismissed) {
+            NotificationIconContainer hostLayout, boolean showAmbient, boolean hideDismissed,
+            boolean hideRepliedMessages) {
         ArrayList<StatusBarIconView> toShow = new ArrayList<>(
                 mNotificationScrollLayout.getChildCount());
 
@@ -198,7 +205,8 @@
             View view = mNotificationScrollLayout.getChildAt(i);
             if (view instanceof ExpandableNotificationRow) {
                 NotificationData.Entry ent = ((ExpandableNotificationRow) view).getEntry();
-                if (shouldShowNotificationIcon(ent, showAmbient, hideDismissed)) {
+                if (shouldShowNotificationIcon(ent, showAmbient, hideDismissed,
+                        hideRepliedMessages)) {
                     toShow.add(function.apply(ent));
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 8c257fe..5dee2a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -129,13 +129,14 @@
 
     public static final int MAX_VISIBLE_ICONS_WHEN_DARK = 5;
     public static final int MAX_STATIC_ICONS = 4;
-    private static final int MAX_DOTS = 3;
+    private static final int MAX_DOTS = 1;
 
     private boolean mIsStaticLayout = true;
     private final HashMap<View, IconState> mIconStates = new HashMap<>();
     private int mDotPadding;
     private int mStaticDotRadius;
     private int mStaticDotDiameter;
+    private int mOverflowWidth;
     private int mActualLayoutWidth = NO_VALUE;
     private float mActualPaddingEnd = NO_VALUE;
     private float mActualPaddingStart = NO_VALUE;
@@ -230,7 +231,7 @@
             int top = (int) (centerY - height / 2.0f);
             child.layout(0, top, width, top + height);
             if (i == 0) {
-                mIconSize = child.getWidth();
+                setIconSize(child.getWidth());
             }
         }
         getLocationOnScreen(mAbsolutePosition);
@@ -239,6 +240,11 @@
         }
     }
 
+    private void setIconSize(int size) {
+        mIconSize = size;
+        mOverflowWidth = mIconSize + (MAX_DOTS - 1) * (mStaticDotDiameter + mDotPadding);
+    }
+
     private void updateState() {
         resetViewStates();
         calculateIconTranslations();
@@ -391,12 +397,12 @@
             iconState.visibleState = StatusBarIconView.STATE_ICON;
 
             boolean isOverflowing =
-                    (translationX >= (noOverflowAfter ? layoutEnd - mIconSize : overflowStart));
+                    (translationX > (noOverflowAfter ? layoutEnd - mIconSize
+                            : overflowStart - mIconSize));
             if (firstOverflowIndex == -1 && (forceOverflow || isOverflowing)) {
                 firstOverflowIndex = noOverflowAfter && !forceOverflow ? i - 1 : i;
-                mVisualOverflowStart = layoutEnd - mIconSize
-                        - 2 * (mStaticDotDiameter + mDotPadding);
-                if (forceOverflow) {
+                mVisualOverflowStart = layoutEnd - mOverflowWidth;
+                if (forceOverflow || mIsStaticLayout) {
                     mVisualOverflowStart = Math.min(translationX, mVisualOverflowStart);
                 }
             }
@@ -408,7 +414,7 @@
             for (int i = firstOverflowIndex; i < childCount; i++) {
                 View view = getChildAt(i);
                 IconState iconState = mIconStates.get(view);
-                int dotWidth = mStaticDotRadius * 2 + mDotPadding;
+                int dotWidth = mStaticDotDiameter + mDotPadding;
                 iconState.xTranslation = translationX;
                 if (mNumDots < MAX_DOTS) {
                     if (mNumDots == 0 && iconState.iconAppearAmount < 0.8f) {
@@ -536,7 +542,7 @@
     }
 
     private float getMaxOverflowStart() {
-        return getLayoutEnd() - mIconSize * (2 + OVERFLOW_EARLY_AMOUNT);
+        return getLayoutEnd() - mOverflowWidth;
     }
 
     public void setChangingViewPositions(boolean changingViewPositions) {
@@ -607,7 +613,7 @@
             return 0;
         }
 
-        int collapsedPadding = mIconSize + 2 * (mStaticDotDiameter + mDotPadding);
+        int collapsedPadding = mOverflowWidth;
 
         if (collapsedPadding + getFinalTranslationX() > getWidth()) {
             collapsedPadding = getWidth() - getFinalTranslationX();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadowKeyDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadowKeyDrawable.java
new file mode 100644
index 0000000..8311dfd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadowKeyDrawable.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+
+import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
+import android.graphics.BlurMaskFilter.Blur;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+import com.android.systemui.R;
+
+/**
+ * A drawable which adds shadow around a child drawable.
+ */
+public class ShadowKeyDrawable extends Drawable {
+    private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+
+    private final ShadowDrawableState mState;
+
+    public ShadowKeyDrawable(Drawable d) {
+        this(d, new ShadowDrawableState());
+    }
+
+    private ShadowKeyDrawable(Drawable d, ShadowDrawableState state) {
+        mState = state;
+        if (d != null) {
+            mState.mBaseHeight = d.getIntrinsicHeight();
+            mState.mBaseWidth = d.getIntrinsicWidth();
+            mState.mChangingConfigurations = d.getChangingConfigurations();
+            mState.mChildState = d.getConstantState();
+        }
+    }
+
+    public void setRotation(float degrees) {
+        if (mState.mRotateDegrees != degrees) {
+            mState.mRotateDegrees = degrees;
+            mState.mLastDrawnBitmap = null;
+            invalidateSelf();
+        }
+    }
+
+    public void setShadowProperties(int x, int y, int size, int color) {
+        if (mState.mShadowOffsetX != x || mState.mShadowOffsetY != y
+                || mState.mShadowSize != size || mState.mShadowColor != color) {
+            mState.mShadowOffsetX = x;
+            mState.mShadowOffsetY = y;
+            mState.mShadowSize = size;
+            mState.mShadowColor = color;
+            mState.mLastDrawnBitmap = null;
+            invalidateSelf();
+        }
+    }
+
+    public float getRotation() {
+        return mState.mRotateDegrees;
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        Rect bounds = getBounds();
+        if (bounds.isEmpty()) {
+            return;
+        }
+        if (mState.mLastDrawnBitmap == null) {
+            regenerateBitmapCache();
+        }
+        canvas.drawBitmap(mState.mLastDrawnBitmap, null, bounds, mPaint);
+    }
+
+    @Override
+    public void setTint(int tintColor) {
+        super.setTint(tintColor);
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        mPaint.setAlpha(alpha);
+        invalidateSelf();
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter colorFilter) {
+        mPaint.setColorFilter(colorFilter);
+        invalidateSelf();
+    }
+
+    @Override
+    public ConstantState getConstantState() {
+        return mState;
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mState.mBaseHeight;
+    }
+
+    @Override
+    public int getIntrinsicWidth() {
+        return mState.mBaseWidth;
+    }
+
+    @Override
+    public boolean canApplyTheme() {
+        return mState.canApplyTheme();
+    }
+
+    private void regenerateBitmapCache() {
+        final int width = getIntrinsicWidth();
+        final int height = getIntrinsicHeight();
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        canvas.save();
+        final float radians = (float) (mState.mRotateDegrees * Math.PI / 180);
+
+        // Rotate canvas before drawing original drawable if no shadow
+        if (mState.mShadowSize == 0) {
+            canvas.rotate(mState.mRotateDegrees, width / 2, height / 2);
+        }
+
+        // Call mutate, so that the pixel allocation by the underlying vector drawable is cleared.
+        final Drawable d = mState.mChildState.newDrawable().mutate();
+        d.setBounds(0, 0, mState.mBaseWidth, mState.mBaseHeight);
+        d.draw(canvas);
+
+        if (mState.mShadowSize > 0) {
+            // Draws the shadow
+            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+            paint.setMaskFilter(new BlurMaskFilter(mState.mShadowSize, Blur.NORMAL));
+            int[] offset = new int[2];
+
+            final Bitmap shadow = bitmap.extractAlpha(paint, offset);
+
+            paint.setMaskFilter(null);
+            paint.setColor(mState.mShadowColor);
+            bitmap.eraseColor(Color.TRANSPARENT);
+
+            canvas.rotate(mState.mRotateDegrees, width / 2, height / 2);
+
+            final float shadowOffsetX = (float) (Math.sin(radians) * mState.mShadowOffsetY
+                    + Math.cos(radians) * mState.mShadowOffsetX);
+            final float shadowOffsetY = (float) (Math.cos(radians) * mState.mShadowOffsetY
+                    - Math.sin(radians) * mState.mShadowOffsetX);
+
+            canvas.drawBitmap(shadow, offset[0] + shadowOffsetX, offset[1] + shadowOffsetY, paint);
+            d.draw(canvas);
+        }
+
+        bitmap = bitmap.copy(Bitmap.Config.HARDWARE, false);
+        mState.mLastDrawnBitmap = bitmap;
+        canvas.restore();
+    }
+
+    private static class ShadowDrawableState extends ConstantState {
+        int mChangingConfigurations;
+        int mBaseWidth;
+        int mBaseHeight;
+        float mRotateDegrees;
+        int mShadowOffsetX;
+        int mShadowOffsetY;
+        int mShadowSize;
+        int mShadowColor;
+
+        Bitmap mLastDrawnBitmap;
+        ConstantState mChildState;
+
+        @Override
+        public Drawable newDrawable() {
+            return new ShadowKeyDrawable(null, this);
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mChangingConfigurations;
+        }
+
+        @Override
+        public boolean canApplyTheme() {
+            return true;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index b0d72c5..c70f034 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -234,6 +234,7 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 import com.android.systemui.statusbar.policy.PreviewInflater;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -399,6 +400,9 @@
     private View mPendingRemoteInputView;
     private View mPendingWorkRemoteInputView;
 
+    private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler =
+            Dependency.get(RemoteInputQuickSettingsDisabler.class);
+
     private View mReportRejectedTouch;
 
     private int mMaxAllowedKeyguardNotifications;
@@ -1759,6 +1763,8 @@
      */
     @Override
     public void disable(int state1, int state2, boolean animate) {
+        state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2);
+
         animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN;
         final int old1 = mDisabled1;
         final int diff1 = state1 ^ old1;
@@ -2090,7 +2096,8 @@
      * @param animate should the change of the icons be animated.
      */
     private void updateHideIconsForBouncer(boolean animate) {
-        boolean hideBecauseApp = mTopHidesStatusBar && mIsOccluded && mStatusBarWindowHidden;
+        boolean hideBecauseApp = mTopHidesStatusBar && mIsOccluded
+                && (mStatusBarWindowHidden || mBouncerShowing);
         boolean hideBecauseKeyguard = !mPanelExpanded && !mIsOccluded && mBouncerShowing;
         boolean shouldHideIconsForBouncer = hideBecauseApp || hideBecauseKeyguard;
         if (mHideIconsForBouncer != shouldHideIconsForBouncer) {
@@ -4715,7 +4722,7 @@
             // Bouncer needs the front scrim when it's on top of an activity,
             // tapping on a notification, editing QS or being dismissed by
             // FLAG_DISMISS_KEYGUARD_ACTIVITY.
-            ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
+            ScrimState state = mIsOccluded || mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
                     || mStatusBarKeyguardViewManager.willDismissWithAction()
                     || mStatusBarKeyguardViewManager.isFullscreenBouncer() ?
                     ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
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 6a6a7dd..5f5d12e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -169,7 +169,7 @@
         // • Full-screen user switcher is displayed.
         if (mNotificationPanelView.isUnlockHintRunning()) {
             mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
-        } else if (mBouncer.willDismissWithAction() || mBouncer.isShowingScrimmed()
+        } else if (mOccluded || mBouncer.willDismissWithAction() || mBouncer.isShowingScrimmed()
                 || mStatusBar.isFullScreenUserSwitcherState()) {
             mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
         } else if (mShowing && !mDozing) {
@@ -206,13 +206,17 @@
         } else {
             mStatusBar.showKeyguard();
             if (hideBouncerWhenShowing) {
-                hideBouncer(false /* destroyView */);
+                hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
                 mBouncer.prepare();
             }
         }
         updateStates();
     }
 
+    protected boolean shouldDestroyViewOnReset() {
+        return false;
+    }
+
     private void hideBouncer(boolean destroyView) {
         mBouncer.hide(destroyView);
         cancelPendingWakeupAction();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index cce9d1c..1a85c47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -17,10 +17,16 @@
 package com.android.systemui.statusbar.policy;
 
 import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.view.Gravity;
 
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.ShadowKeyDrawable;
+
 /**
  * Drawable for {@link KeyButtonView}s which contains an asset for both normal mode and light
  * navigation bar mode.
@@ -29,13 +35,24 @@
 
     private final boolean mHasDarkDrawable;
 
-    public static KeyButtonDrawable create(Drawable lightDrawable,
-            @Nullable Drawable darkDrawable) {
+    public static KeyButtonDrawable create(Context lightContext, Drawable lightDrawable,
+            @Nullable Drawable darkDrawable, boolean hasShadow) {
         if (darkDrawable != null) {
-            return new KeyButtonDrawable(
-                    new Drawable[] { lightDrawable.mutate(), darkDrawable.mutate() });
+            ShadowKeyDrawable light = new ShadowKeyDrawable(lightDrawable.mutate());
+            ShadowKeyDrawable dark = new ShadowKeyDrawable(darkDrawable.mutate());
+            if (hasShadow) {
+                // Only apply the shadow on the light drawable
+                Resources res = lightContext.getResources();
+                int offsetX = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_offset_x);
+                int offsetY = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_offset_y);
+                int radius = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_radius);
+                int color = lightContext.getColor(R.color.nav_key_button_shadow_color);
+                light.setShadowProperties(offsetX, offsetY, radius, color);
+            }
+            return new KeyButtonDrawable(new Drawable[] { light, dark });
         } else {
-            return new KeyButtonDrawable(new Drawable[] { lightDrawable.mutate() });
+            return new KeyButtonDrawable(new Drawable[] {
+                    new ShadowKeyDrawable(lightDrawable.mutate()) });
         }
     }
 
@@ -57,4 +74,13 @@
         getDrawable(1).setAlpha((int) (intensity * 255f));
         invalidateSelf();
     }
+
+    public void setRotation(float degrees) {
+        if (getDrawable(0) instanceof ShadowKeyDrawable) {
+            ((ShadowKeyDrawable) getDrawable(0)).setRotation(degrees);
+        }
+        if (mHasDarkDrawable && getDrawable(1) instanceof ShadowKeyDrawable) {
+            ((ShadowKeyDrawable) getDrawable(1)).setRotation(degrees);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
new file mode 100644
index 0000000..c2933e151
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.app.StatusBarManager;
+import android.content.Context;
+import android.content.res.Configuration;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+/**
+ * Let {@link RemoteInputView} to control the visibility of QuickSetting.
+ */
+public class RemoteInputQuickSettingsDisabler
+        implements ConfigurationController.ConfigurationListener {
+
+    private Context mContext;
+    @VisibleForTesting boolean mRemoteInputActive;
+    @VisibleForTesting boolean misLandscape;
+    private int mLastOrientation;
+    @VisibleForTesting CommandQueue mCommandQueue;
+
+    public RemoteInputQuickSettingsDisabler(Context context) {
+        mContext = context;
+        mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
+        mLastOrientation = mContext.getResources().getConfiguration().orientation;
+        Dependency.get(ConfigurationController.class).addCallback(this);
+    }
+
+    public int adjustDisableFlags(int state) {
+        if (mRemoteInputActive && misLandscape) {
+            state |= StatusBarManager.DISABLE2_QUICK_SETTINGS;
+        }
+
+        return state;
+    }
+
+    public void setRemoteInputActive(boolean active){
+        if(mRemoteInputActive != active){
+            mRemoteInputActive = active;
+            recomputeDisableFlags();
+        }
+    }
+
+    @Override
+    public void onConfigChanged(Configuration newConfig) {
+        if (newConfig.orientation != mLastOrientation) {
+            misLandscape = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
+            mLastOrientation = newConfig.orientation;
+            recomputeDisableFlags();
+        }
+    }
+
+    /**
+     * Reapplies the disable flags. Then the method adjustDisableFlags in this class will be invoked
+     * in {@link QSFragment#disable(int, int, boolean)} and
+     * {@link StatusBar#disable(int, int, boolean)}
+     * to modify the disable flags according to the status of mRemoteInputActive and misLandscape.
+     */
+    private void recomputeDisableFlags() {
+        mCommandQueue.recomputeDisableFlags(true);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 310f14c..4ec9ae8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -53,6 +53,7 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.NotificationData;
@@ -81,6 +82,7 @@
     private RemoteInput[] mRemoteInputs;
     private RemoteInput mRemoteInput;
     private RemoteInputController mController;
+    private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
 
     private NotificationData.Entry mEntry;
 
@@ -96,6 +98,7 @@
 
     public RemoteInputView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mRemoteInputQuickSettingsDisabler = Dependency.get(RemoteInputQuickSettingsDisabler.class);
     }
 
     @Override
@@ -151,6 +154,7 @@
         mController.removeRemoteInput(mEntry, mToken);
         mEditText.mShowImeOnInputConnection = false;
         mController.remoteInputSent(mEntry);
+        mEntry.setHasSentReply();
 
         // Tell ShortcutManager that this package has been "activated".  ShortcutManager
         // will reset the throttling for this package.
@@ -232,6 +236,9 @@
                 }
             }
         }
+
+        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(false);
+
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_CLOSE,
                 mEntry.notification.getPackageName());
     }
@@ -291,6 +298,9 @@
         mEditText.setSelection(mEditText.getText().length());
         mEditText.requestFocus();
         mController.addRemoteInput(mEntry, mToken);
+
+        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(true);
+
         updateSendButton();
     }
 
@@ -554,6 +564,14 @@
         }
 
         @Override
+        public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+                mRemoteInputView.mRemoteInputQuickSettingsDisabler.setRemoteInputActive(false);
+            }
+            return super.dispatchKeyEvent(event);
+        }
+
+        @Override
         public boolean onCheckIsTextEditor() {
             // Stop being editable while we're being removed. During removal, we get reattached,
             // and editable views get their spellchecking state re-evaluated which is too costly
@@ -565,11 +583,6 @@
         @Override
         public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
             final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
-            //if pinned, set imeOption to keep the behavior like in portrait.
-            if (mRemoteInputView != null && mRemoteInputView.mEntry.row.isPinned()) {
-                outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI
-                        | EditorInfo.IME_FLAG_NO_FULLSCREEN;
-            }
 
             if (mShowImeOnInputConnection && inputConnection != null) {
                 final InputMethodManager imm = InputMethodManager.getInstance();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 585787e..924aa01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -213,6 +213,7 @@
             Intent intent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
             RemoteInput.addResultsToIntent(new RemoteInput[]{remoteInput}, intent, results);
             RemoteInput.setResultsSource(intent, RemoteInput.SOURCE_CHOICE);
+            entry.setHasSentReply();
             try {
                 pendingIntent.send(context, 0, intent);
             } catch (PendingIntent.CanceledException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TintedKeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TintedKeyButtonDrawable.java
index 4d33dec..30a5cc84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TintedKeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TintedKeyButtonDrawable.java
@@ -21,6 +21,7 @@
 import android.graphics.drawable.Drawable;
 
 import com.android.internal.graphics.ColorUtils;
+import com.android.systemui.statusbar.phone.ShadowKeyDrawable;
 
 /**
  * Drawable for {@link KeyButtonView}s which contains a single asset and colors for light and dark
@@ -36,7 +37,8 @@
 
     public static TintedKeyButtonDrawable create(Drawable drawable, @ColorInt int lightColor,
             @ColorInt int darkColor) {
-        return new TintedKeyButtonDrawable(new Drawable[] { drawable }, lightColor, darkColor);
+        return new TintedKeyButtonDrawable(new Drawable[] { drawable },
+                lightColor, darkColor);
     }
 
     private TintedKeyButtonDrawable(Drawable[] drawables, int lightColor, int darkColor){
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 91a4b07..db3f0d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -30,7 +30,6 @@
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
 import java.util.ArrayList;
-import java.util.Collection;
 
 /**
  * A global state to track all input states for the algorithm.
@@ -72,6 +71,7 @@
     private ExpandableNotificationRow mExpandingNotification;
     private int mDarkTopPadding;
     private float mDarkAmount;
+    private boolean mAppearing;
 
     public AmbientState(Context context) {
         reload(context);
@@ -436,4 +436,12 @@
     public int getDarkTopPadding() {
         return mDarkTopPadding;
     }
+
+    public void setAppearing(boolean appearing) {
+        mAppearing = appearing;
+    }
+
+    public boolean isAppearing() {
+        return mAppearing;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index bd56d79..a2b33fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -885,7 +885,9 @@
         float appearEndPosition = getAppearEndPosition();
         float appearStartPosition = getAppearStartPosition();
         float appearFraction = 1.0f;
-        if (height >= appearEndPosition) {
+        boolean appearing = height < appearEndPosition;
+        mAmbientState.setAppearing(appearing);
+        if (!appearing) {
             translationY = 0;
             if (mShouldShowShelfOnly) {
                 stackHeight = mTopPadding + mShelf.getIntrinsicHeight();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 85f33d7..0d50f5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -478,22 +478,6 @@
                 childState.hidden = false;
             }
         }
-        // Let's hide all the views if we are not expanded. the views might otherwise be visible
-        // in the headsup area if a view was swiped away
-        if (!mIsExpanded) {
-            for (int i = 0; i < childCount; i++) {
-                boolean visible = false;
-                View child = algorithmState.visibleChildren.get(i);
-                if (child instanceof ExpandableNotificationRow) {
-                    ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                    visible = row.isHeadsUp() || row.isHeadsUpAnimatingAway();
-                }
-                if (!visible) {
-                    ExpandableViewState childState = resultState.getViewStateForView(child);
-                    childState.hidden = true;
-                }
-            }
-        }
     }
 
     private void clampHunToTop(AmbientState ambientState, ExpandableNotificationRow row,
@@ -536,6 +520,10 @@
 
         int shelfStart = ambientState.getInnerHeight()
                 - ambientState.getShelf().getIntrinsicHeight();
+        if (ambientState.isAppearing() && !child.isAboveShelf()) {
+            // Don't show none heads-up notifications while in appearing phase.
+            childViewState.yTranslation = Math.max(childViewState.yTranslation, shelfStart);
+        }
         childViewState.yTranslation = Math.min(childViewState.yTranslation, shelfStart);
         if (childViewState.yTranslation >= shelfStart) {
             childViewState.hidden = !child.isExpandAnimationRunning() && !child.hasExpandingChild();
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index d527465..2f8dfdc 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -640,7 +640,7 @@
     }
 
     private PendingIntent buildBrowsePendingIntent(VolumeInfo vol) {
-        final Intent intent = vol.buildBrowseIntent();
+        final Intent intent = vol.buildBrowseIntentForUser(vol.getMountUserId());
 
         final int requestKey = vol.getId().hashCode();
         return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
index ad20900..11c72c4 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
@@ -23,6 +23,7 @@
     public static final int ROTATION_NONE = 0;
     public static final int ROTATION_LANDSCAPE = 1;
     public static final int ROTATION_SEASCAPE = 2;
+    public static final int ROTATION_UPSIDE_DOWN = 3;
 
     public static int getRotation(Context context) {
         Configuration config = context.getResources().getConfiguration();
@@ -36,4 +37,19 @@
         }
         return ROTATION_NONE;
     }
+
+    public static int getExactRotation(Context context) {
+        Configuration config = context.getResources().getConfiguration();
+        int rot = context.getDisplay().getRotation();
+        if (config.smallestScreenWidthDp < 600) {
+            if (rot == Surface.ROTATION_90) {
+                return ROTATION_LANDSCAPE;
+            } else if (rot == Surface.ROTATION_270) {
+                return ROTATION_SEASCAPE;
+            } else if (rot == Surface.ROTATION_180) {
+                return ROTATION_UPSIDE_DOWN;
+            }
+        }
+        return ROTATION_NONE;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index d76b7f0..03474a8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -727,6 +727,12 @@
     }
 
     protected void onStateChangedH(State state) {
+        if (mState != null && state != null
+                && mState.ringerModeInternal != state.ringerModeInternal
+                && state.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
+            mController.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK));
+        }
+
         mState = state;
         mDynamic.clear();
         // add any new dynamic rows
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 2f05b06..f1bf31d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -36,6 +36,7 @@
 import android.content.res.Configuration;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
 import android.view.Display;
 import android.view.View;
 import android.view.WindowManager;
@@ -54,6 +55,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+@RunWithLooper
 @RunWith(AndroidTestingRunner.class)
 @SmallTest
 public class ScreenDecorationsTest extends SysuiTestCase {
@@ -98,6 +100,8 @@
         mContext.getOrCreateTestableResources().addOverride(
                 com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
         mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 0);
+        mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius_top, 0);
+        mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius_bottom, 0);
         mContext.getOrCreateTestableResources()
                 .addOverride(dimen.rounded_corner_content_padding, 0);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
index 5c80bb5..6ac4462 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
@@ -45,13 +45,11 @@
     private DozeWallpaperState mDozeWallpaperState;
     @Mock IWallpaperManager mIWallpaperManager;
     @Mock DozeParameters mDozeParameters;
-    @Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mDozeParameters,
-                mKeyguardUpdateMonitor);
+        mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mDozeParameters);
     }
 
     @Test
@@ -100,4 +98,28 @@
         mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_AOD, DozeMachine.State.FINISH);
         verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(false));
     }
+
+    @Test
+    public void testTransitionTo_requestPulseIsAmbientMode() throws RemoteException {
+        mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE,
+                DozeMachine.State.DOZE_REQUEST_PULSE);
+        verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(false));
+    }
+
+    @Test
+    public void testTransitionTo_pulseIsAmbientMode() throws RemoteException {
+        mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE,
+                DozeMachine.State.DOZE_PULSING);
+        verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(false));
+    }
+
+    @Test
+    public void testTransitionTo_animatesWhenWakingUpFromPulse() throws RemoteException {
+        mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE,
+                DozeMachine.State.DOZE_PULSING);
+        reset(mIWallpaperManager);
+        mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_PULSING,
+                DozeMachine.State.FINISH);
+        verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(true));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index bdeb8bc..a72fed4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -508,7 +508,6 @@
                         anyString(), eq(TEST_UID), eq(true));
     }
 
-
     @Test
     public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing()
             throws Exception {
@@ -537,6 +536,43 @@
                         anyString(), eq(TEST_UID), eq(true));
     }
 
+    @Test
+    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss()
+            throws Exception {
+        NotificationInfo.CheckSaveListener listener =
+                mock(NotificationInfo.CheckSaveListener.class);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                false /* isNonblockable */, true /* isForBlockingHelper */,
+                true /* isUserSentimentNegative */);
+
+        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
+
+        mTestableLooper.processAllMessages();
+        verify(listener, times(0)).checkSave(any(Runnable.class), eq(mSbn));
+    }
+
+    @Test
+    public void testCloseControls_checkSaveListenerDelaysStopNotifications()
+            throws Exception {
+        NotificationInfo.CheckSaveListener listener =
+                mock(NotificationInfo.CheckSaveListener.class);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
+                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
+                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
+                false /* isNonblockable */, true /* isForBlockingHelper */,
+                true /* isUserSentimentNegative */);
+
+        mNotificationInfo.findViewById(R.id.block).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
+
+        mTestableLooper.processAllMessages();
+        verify(listener).checkSave(any(Runnable.class), eq(mSbn));
+    }
 
     @Test
     public void testCloseControls_blockingHelperDismissedIfShown() throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index e2e5b32..8340ab2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -162,6 +162,14 @@
         verify(mBouncer, never()).show(eq(false), eq(false));
     }
 
+    @Test
+    public void onPanelExpansionChanged_neverTranslatesBouncerWhenOccluded() {
+        mStatusBarKeyguardViewManager.setOccluded(true /* occluded */, false /* animate */);
+        mStatusBarKeyguardViewManager.onPanelExpansionChanged(0.5f /* expansion */,
+                true /* tracking */);
+        verify(mBouncer, never()).setExpansion(eq(0.5f));
+    }
+
     private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
 
         public TestableStatusBarKeyguardViewManager(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java
new file mode 100644
index 0000000..3b47eae
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.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.systemui.statusbar.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.content.res.Configuration;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RemoteInputQuickSettingsDisablerTest extends SysuiTestCase {
+
+    private CommandQueue mCommandQueue;
+    private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mCommandQueue = mock(CommandQueue.class);
+        mContext.putComponent(CommandQueue.class, mCommandQueue);
+
+        mRemoteInputQuickSettingsDisabler = new RemoteInputQuickSettingsDisabler(mContext);
+    }
+
+    @Test
+    public void shouldEnableQuickSetting_afterDeactiviate() {
+        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(Boolean.TRUE);
+        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(Boolean.FALSE);
+        assertFalse(mRemoteInputQuickSettingsDisabler.mRemoteInputActive);
+        verify(mCommandQueue, atLeastOnce()).recomputeDisableFlags(anyBoolean());
+    }
+
+    @Test
+    public void shouldDisableQuickSetting_afteActiviate() {
+        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(Boolean.FALSE);
+        mRemoteInputQuickSettingsDisabler.setRemoteInputActive(Boolean.TRUE);
+        assertTrue(mRemoteInputQuickSettingsDisabler.mRemoteInputActive);
+        verify(mCommandQueue, atLeastOnce()).recomputeDisableFlags(anyBoolean());
+    }
+
+    @Test
+    public void testChangeToLandscape() {
+        Configuration c = new Configuration(mContext.getResources().getConfiguration());
+        c.orientation = Configuration.ORIENTATION_PORTRAIT;
+        mRemoteInputQuickSettingsDisabler.onConfigChanged(c);
+        c.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        mRemoteInputQuickSettingsDisabler.onConfigChanged(c);
+        assertTrue(mRemoteInputQuickSettingsDisabler.misLandscape);
+        verify(mCommandQueue, atLeastOnce()).recomputeDisableFlags(anyBoolean());
+    }
+
+    @Test
+    public void testChangeToPortrait() {
+        Configuration c = new Configuration(mContext.getResources().getConfiguration());
+        c.orientation = Configuration.ORIENTATION_LANDSCAPE;
+        mRemoteInputQuickSettingsDisabler.onConfigChanged(c);
+        c.orientation = Configuration.ORIENTATION_PORTRAIT;
+        mRemoteInputQuickSettingsDisabler.onConfigChanged(c);
+        assertFalse(mRemoteInputQuickSettingsDisabler.misLandscape);
+        verify(mCommandQueue, atLeastOnce()).recomputeDisableFlags(anyBoolean());
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index 938dfca..a6fa4f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -54,6 +54,7 @@
 
     @Mock private RemoteInputController mController;
     @Mock private ShortcutManager mShortcutManager;
+    @Mock private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
     private BlockingQueueIntentReceiver mReceiver;
     private RemoteInputView mView;
 
@@ -61,6 +62,9 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
+        mDependency.injectTestDependency(RemoteInputQuickSettingsDisabler.class,
+                mRemoteInputQuickSettingsDisabler);
+
         mReceiver = new BlockingQueueIntentReceiver();
         mContext.registerReceiver(mReceiver, new IntentFilter(TEST_ACTION), null,
                 Handler.createAsync(Dependency.get(Dependency.BG_LOOPER)));
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 686ab53..d064105 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -205,6 +205,14 @@
         HARDWARE_FAILURE_FINGERPRINT_TOO_MANY_DEAD_PIXELS = 5;
     }
 
+    enum IoOperation {
+        IOOP_UNKNOWN = 0;
+        IOOP_READ = 1;
+        IOOP_WRITE = 2;
+        IOOP_UNMAP = 3;
+        IOOP_SYNC = 4;
+    }
+
   // Known visual elements: views or controls.
   enum View {
     // Unknown view
@@ -5931,8 +5939,7 @@
     // ACTION: Battery health snapshot
     // CATEGORY: OTHER
     // OS: P
-    // uses FIELD_END_BATTERY_PERCENT for batt %
-    // uses FIELD_END_BATTERY_UA for instantaneous current load
+    // uses FIELD_END_BATTERY_PERCENT for instantaneous batt %
     ACTION_BATTERY_HEALTH = 1433;
 
     // FIELD: Battery health snapshot type - min daily voltage, resistance, etc.
@@ -5940,31 +5947,33 @@
     // OS: P
     FIELD_BATTERY_HEALTH_SNAPSHOT_TYPE = 1434;
 
-    // FIELD: Battery temperature at snapshop.
+    // FIELD: Battery temperature at snapshot, in 1/10 deg C.
     // CATEGORY: OTHER
     // OS: P
-    FIELD_BATTERY_TEMPERATURE = 1435;
+    FIELD_BATTERY_TEMPERATURE_DECI_C = 1435;
 
-    // FIELD: Battery voltage at snapshot.
+    // FIELD: Battery voltage at snapshot, in microVolts.
     // CATEGORY: OTHER
     // OS: P
-    FIELD_BATTERY_VOLTAGE = 1436;
+    FIELD_BATTERY_VOLTAGE_UV = 1436;
 
-    // FIELD: Battery open circuit voltage at snapshot.
+    // FIELD: Battery open circuit voltage at snapshot, in microVolts.
     // CATEGORY: OTHER
     // OS: P
-    FIELD_BATTERY_OPEN_CIRCUIT_VOLTAGE = 1437;
+    FIELD_BATTERY_OPEN_CIRCUIT_VOLTAGE_UV = 1437;
 
-    // ACTION: Battery charge cycles
-    //         Number of times the battery has charged beyond a
+    // ACTION: Number of times the battery has charged beyond a
     //         fractional threshold of full capacity.
     // CATEGORY: OTHER
     // OS: P
     ACTION_BATTERY_CHARGE_CYCLES = 1438;
 
-    // FIELD: Battery charge cycles
-    //        Number of times the battery has charged beyond a
-    //        fractional threshold of full capacity.
+    // FIELD: BATTERY_CHARGE_CYCLES - Number of times the battery has charged
+    //                                beyond a fractional threshold of full
+    //                                capacity.  A comma-separated string of
+    //                                buckets.  If there are eight buckets,
+    //                                each bucket represents charging to n/8
+    //                                percent full.
     // CATEGORY: OTHER
     // OS: P
     FIELD_BATTERY_CHARGE_CYCLES = 1439;
@@ -5980,6 +5989,62 @@
     // OS: P
     DIALOG_BLUETOOTH_DISABLE_A2DP_HW_OFFLOAD = 1441;
 
+    // ACTION: SLOW_IO - I/O operation took longer than threshold,
+    //                   reported aggregated per day when > 0.
+    // CATEGORY: OTHER
+    // OS: P
+    ACTION_SLOW_IO = 1442;
+
+    // FIELD: IO_OPERATION_TYPE - The IO Operation that caused the high latency.
+    //        The value is an integer from the enum IoOperation.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_IO_OPERATION_TYPE = 1443;
+
+    // FIELD: IO_OPERATION_COUNT - Count of how many times this slow IO operation happened
+    //                over the past 24hr (reported only if > 0).
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_IO_OPERATION_COUNT = 1444;
+
+    // ACTION: Speaker Imedance - last recorded speaker impedance.
+    //                            reported max once per 24hr.
+    // CATEGORY: OTHER
+    // OS: P
+    ACTION_SPEAKER_IMPEDANCE = 1445;
+
+    // FIELD: Speaker Impedance in milliohms.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_SPEAKER_IMPEDANCE_MILLIOHMS = 1446;
+
+    // FIELD: Speaker Location - identifies one of several speakers on a device.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_SPEAKER_LOCATION = 1447;
+
+    // FIELD: Instantaneous battery resistance in microohms.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_BATTERY_RESISTANCE_UOHMS = 1448;
+
+    // FIELD: Instantaneous battery current - in microamps.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_BATTERY_CURRENT_UA = 1449;
+
+    // FIELD: HARDWARE_LOCATION - Identifier for instance of a hardware type on a
+    //                            board.
+    // CATEGORY: OTHER
+    // OS: P
+    FIELD_HARDWARE_LOCATION = 1450;
+
+    // ACTION: BATTERY_CAUSED_SHUTDOWN - shutdown due to low battery, the
+    //                  action is logged after the subsequent boot.
+    // CATEGORY: OTHER
+    // OS: P
+    ACTION_BATTERY_CAUSED_SHUTDOWN = 1451;
+
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 9ff8e7d..bf9ccb8 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -453,6 +453,10 @@
 
   // Number of times the firmware picked a SoftAp channel not satisfying user band preference.
   optional int32 num_soft_ap_user_band_preference_unsatisfied = 116;
+
+  // Identifier for experimental scoring parameter settings.
+  optional string score_experiment_id = 117;
+
 }
 
 // Information that gets logged for every WiFi connection.
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index fa2a0d9..a5311b2 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -53,7 +53,6 @@
 import android.view.autofill.AutofillManager;
 import android.widget.ImageView;
 import android.widget.RemoteViews;
-import android.widget.ScrollView;
 import android.widget.TextView;
 
 import com.android.internal.R;
@@ -208,7 +207,7 @@
             mSubTitle = info.getDescription();
             if (mSubTitle != null) {
                 writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE, type);
-                final ScrollView subtitleContainer =
+                final ViewGroup subtitleContainer =
                         view.findViewById(R.id.autofill_save_custom_subtitle);
                 final TextView subtitleView = new TextView(context);
                 subtitleView.setText(mSubTitle);
@@ -361,7 +360,7 @@
             }
 
             // Finally, add the custom description to the save UI.
-            final ScrollView subtitleContainer =
+            final ViewGroup subtitleContainer =
                     saveUiView.findViewById(R.id.autofill_save_custom_subtitle);
             subtitleContainer.addView(customSubtitleView);
             subtitleContainer.setVisibility(View.VISIBLE);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 797cb4b..e22a86e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2503,6 +2503,9 @@
                 ensureNetworkTransitionWakelock(nai.name());
             }
             mLegacyTypeTracker.remove(nai, wasDefault);
+            if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
+                updateAllVpnsCapabilities();
+            }
             rematchAllNetworksAndRequests(null, 0);
             mLingerMonitor.noteDisconnect(nai);
             if (nai.created) {
@@ -3778,6 +3781,26 @@
         }
     }
 
+    /**
+     * Ask all VPN objects to recompute and update their capabilities.
+     *
+     * When underlying networks change, VPNs may have to update capabilities to reflect things
+     * like the metered bit, their transports, and so on. This asks the VPN objects to update
+     * their capabilities, and as this will cause them to send messages to the ConnectivityService
+     * handler thread through their agent, this is asynchronous. When the capabilities objects
+     * are computed they will be up-to-date as they are computed synchronously from here and
+     * this is running on the ConnectivityService thread.
+     * TODO : Fix this and call updateCapabilities inline to remove out-of-order events.
+     */
+    private void updateAllVpnsCapabilities() {
+        synchronized (mVpns) {
+            for (int i = 0; i < mVpns.size(); i++) {
+                final Vpn vpn = mVpns.valueAt(i);
+                vpn.updateCapabilities();
+            }
+        }
+    }
+
     @Override
     public boolean updateLockdownVpn() {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
@@ -4575,7 +4598,7 @@
 
     // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
     private final NetworkRequest mDefaultRequest;
- 
+
     // Request used to optionally keep mobile data active even when higher
     // priority networks like Wi-Fi are active.
     private final NetworkRequest mDefaultMobileDataRequest;
@@ -4651,7 +4674,7 @@
     }
 
     private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties oldLp) {
-        LinkProperties newLp = networkAgent.linkProperties;
+        LinkProperties newLp = new LinkProperties(networkAgent.linkProperties);
         int netId = networkAgent.network.netId;
 
         // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before
@@ -4685,6 +4708,9 @@
         }
         // TODO - move this check to cover the whole function
         if (!Objects.equals(newLp, oldLp)) {
+            synchronized (networkAgent) {
+                networkAgent.linkProperties = newLp;
+            }
             notifyIfacesChangedForNetworkStats();
             notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
         }
@@ -4935,12 +4961,7 @@
         if (!newNc.hasTransport(TRANSPORT_VPN)) {
             // Tell VPNs about updated capabilities, since they may need to
             // bubble those changes through.
-            synchronized (mVpns) {
-                for (int i = 0; i < mVpns.size(); i++) {
-                    final Vpn vpn = mVpns.valueAt(i);
-                    vpn.updateCapabilities();
-                }
-            }
+            updateAllVpnsCapabilities();
         }
     }
 
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 2869114..5a25f48 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import android.annotation.Nullable;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -47,10 +49,18 @@
 import dalvik.system.VMRuntime;
 
 import java.io.FileDescriptor;
+import java.io.Closeable;
+import java.io.InputStream;
+import java.io.DataInputStream;
 import java.io.IOException;
+import java.io.EOFException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
+import java.util.zip.ZipFile;
+import java.util.zip.ZipException;
+import java.util.zip.ZipEntry;
+
 /**
  * <p>PinnerService pins important files for key processes in memory.</p>
  * <p>Files to pin are specified in the config_defaultPinnerServiceFiles
@@ -60,16 +70,18 @@
 public final class PinnerService extends SystemService {
     private static final boolean DEBUG = false;
     private static final String TAG = "PinnerService";
+    private static final int MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); //80MB max
+    private static final String PIN_META_FILENAME = "pinlist.meta";
+    private static final int PAGE_SIZE = (int) Os.sysconf(OsConstants._SC_PAGESIZE);
 
     private final Context mContext;
-    private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<PinnedFile>();
-    private final ArrayList<PinnedFile> mPinnedCameraFiles = new ArrayList<PinnedFile>();
     private final boolean mShouldPinCamera;
 
+    /* These lists protected by PinnerService monitor lock */
+    private final ArrayList<PinnedFile> mPinnedFiles = new ArrayList<PinnedFile>();
+    private final ArrayList<PinnedFile> mPinnedCameraFiles = new ArrayList<PinnedFile>();
+
     private BinderService mBinderService;
-
-    private final long MAX_CAMERA_PIN_SIZE = 80 * (1 << 20); //80MB max
-
     private PinnerHandler mPinnerHandler = null;
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -146,18 +158,18 @@
          // Files to pin come from the overlay and can be specified per-device config
         String[] filesToPin = mContext.getResources().getStringArray(
                 com.android.internal.R.array.config_defaultPinnerServiceFiles);
-        synchronized(this) {
-            // Continue trying to pin remaining files even if there is a failure
-            for (int i = 0; i < filesToPin.length; i++){
-                PinnedFile pf = pinFile(filesToPin[i], 0, 0, 0);
-                if (pf != null) {
-                    mPinnedFiles.add(pf);
-                    if (DEBUG) {
-                        Slog.i(TAG, "Pinned file = " + pf.mFilename);
-                    }
-                } else {
-                    Slog.e(TAG, "Failed to pin file = " + filesToPin[i]);
-                }
+        // Continue trying to pin each file even if we fail to pin some of them
+        for (String fileToPin : filesToPin) {
+            PinnedFile pf = pinFile(fileToPin,
+                                    Integer.MAX_VALUE,
+                                    /*attemptPinIntrospection=*/false);
+            if (pf == null) {
+                Slog.e(TAG, "Failed to pin file = " + fileToPin);
+                continue;
+            }
+
+            synchronized (this) {
+                mPinnedFiles.add(pf);
             }
         }
     }
@@ -166,44 +178,23 @@
      * Handler for camera pinning message
      */
     private void handlePinCamera(int userHandle) {
-        if (mShouldPinCamera) {
-            synchronized(this) {
-                boolean success = pinCamera(userHandle);
-                if (!success) {
-                    //this is not necessarily an error
-                    if (DEBUG) {
-                        Slog.v(TAG, "Failed to pin camera.");
-                    }
-                }
+        if (!mShouldPinCamera) return;
+        if (!pinCamera(userHandle)) {
+            if (DEBUG) {
+                Slog.v(TAG, "Failed to pin camera.");
             }
         }
     }
 
-    /**
-     *  determine if the camera app is already pinned by comparing the
-     *  intent resolution to the pinned files list
-     */
-    private boolean alreadyPinned(int userHandle) {
-        ApplicationInfo cameraInfo = getCameraInfo(userHandle);
-        if (cameraInfo == null ) {
-            return false;
-        }
-        for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
-            if (mPinnedCameraFiles.get(i).mFilename.equals(cameraInfo.sourceDir)) {
-                if (DEBUG) {
-                  Slog.v(TAG, "Camera is already pinned");
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
     private void unpinCameraApp() {
-        for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
-            unpinFile(mPinnedCameraFiles.get(i));
+        ArrayList<PinnedFile> pinnedCameraFiles;
+        synchronized (this) {
+            pinnedCameraFiles = new ArrayList<>(mPinnedCameraFiles);
+            mPinnedCameraFiles.clear();
         }
-        mPinnedCameraFiles.clear();
+        for (PinnedFile pinnedFile : pinnedCameraFiles) {
+            pinnedFile.close();
+        }
     }
 
     private boolean isResolverActivity(ActivityInfo info) {
@@ -255,15 +246,19 @@
 
         //pin APK
         String camAPK = cameraInfo.sourceDir;
-        PinnedFile pf = pinFile(camAPK, 0, 0, MAX_CAMERA_PIN_SIZE);
+        PinnedFile pf = pinFile(camAPK,
+                                MAX_CAMERA_PIN_SIZE,
+                                /*attemptPinIntrospection=*/true);
         if (pf == null) {
             Slog.e(TAG, "Failed to pin " + camAPK);
             return false;
         }
         if (DEBUG) {
-            Slog.i(TAG, "Pinned " + pf.mFilename);
+            Slog.i(TAG, "Pinned " + pf.fileName);
         }
-        mPinnedCameraFiles.add(pf);
+        synchronized (this) {
+            mPinnedCameraFiles.add(pf);
+        }
 
         // determine the ABI from either ApplicationInfo or Build
         String arch = "arm";
@@ -289,11 +284,13 @@
 
         //not pinning the oat/odex is not a fatal error
         for (String file : files) {
-            pf = pinFile(file, 0, 0, MAX_CAMERA_PIN_SIZE);
+            pf = pinFile(file, MAX_CAMERA_PIN_SIZE, /*attemptPinIntrospection=*/false);
             if (pf != null) {
-                mPinnedCameraFiles.add(pf);
+                synchronized (this) {
+                    mPinnedCameraFiles.add(pf);
+                }
                 if (DEBUG) {
-                    Slog.i(TAG, "Pinned " + pf.mFilename);
+                    Slog.i(TAG, "Pinned " + pf.fileName);
                 }
             }
         }
@@ -302,70 +299,294 @@
     }
 
 
-    /** mlock length bytes of fileToPin in memory, starting at offset
-     *  length == 0 means pin from offset to end of file
-     *  maxSize == 0 means infinite
+    /** mlock length bytes of fileToPin in memory
+     *
+     * If attemptPinIntrospection is true, then treat the file to pin as a zip file and
+     * look for a "pinlist.meta" file in the archive root directory. The structure of this
+     * file is a PINLIST_META as described below:
+     *
+     * <pre>
+     *   PINLIST_META: PIN_RANGE*
+     *   PIN_RANGE: PIN_START PIN_LENGTH
+     *   PIN_START: big endian i32: offset in bytes of pin region from file start
+     *   PIN_LENGTH: big endian i32: length of pin region in bytes
+     * </pre>
+     *
+     * (We use big endian because that's what DataInputStream is hardcoded to use.)
+     *
+     * If attemptPinIntrospection is false, then we use a single implicit PIN_RANGE of (0,
+     * maxBytesToPin); that is, we attempt to pin the first maxBytesToPin bytes of the file.
+     *
+     * After we open a file, we march through the list of pin ranges and attempt to pin
+     * each one, stopping after we've pinned maxBytesToPin bytes. (We may truncate the last
+     * pinned range to fit.)  In this way, by choosing to emit certain PIN_RANGE pairs
+     * before others, file generators can express pins in priority order, making most
+     * effective use of the pinned-page quota.
+     *
+     * N.B. Each PIN_RANGE is clamped to the actual bounds of the file; all inputs have a
+     * meaningful interpretation. Also, a range locking a single byte of a page locks the
+     * whole page. Any truncated PIN_RANGE at EOF is ignored. Overlapping pinned entries
+     * are legal, but each pin of a byte counts toward the pin quota regardless of whether
+     * that byte has already been pinned, so the generator of PINLIST_META ought to ensure
+     * that ranges are non-overlapping.
+     *
+     * @param fileToPin Path to file to pin
+     * @param maxBytesToPin Maximum number of bytes to pin
+     * @param attemptPinIntrospection If true, try to open file as a
+     *   zip in order to extract the
+     * @return Pinned memory resource owner thing or null on error
      */
-    private static PinnedFile pinFile(String fileToPin, long offset, long length, long maxSize) {
-        FileDescriptor fd = new FileDescriptor();
+    private static PinnedFile pinFile(String fileToPin,
+                                      int maxBytesToPin,
+                                      boolean attemptPinIntrospection) {
+        ZipFile fileAsZip = null;
+        InputStream pinRangeStream = null;
         try {
-            fd = Os.open(fileToPin,
-                    OsConstants.O_RDONLY | OsConstants.O_CLOEXEC | OsConstants.O_NOFOLLOW,
-                    OsConstants.O_RDONLY);
-
-            StructStat sb = Os.fstat(fd);
-
-            if (offset + length > sb.st_size) {
-                Os.close(fd);
-                Slog.e(TAG, "Failed to pin file " + fileToPin +
-                        ", request extends beyond end of file.  offset + length =  "
-                        + (offset + length) + ", file length = " + sb.st_size);
-                return null;
+            if (attemptPinIntrospection) {
+                fileAsZip = maybeOpenZip(fileToPin);
             }
 
-            if (length == 0) {
-                length = sb.st_size - offset;
+            if (fileAsZip != null) {
+                pinRangeStream = maybeOpenPinMetaInZip(fileAsZip, fileToPin);
             }
 
-            if (maxSize > 0 && length > maxSize) {
-                Slog.e(TAG, "Could not pin file " + fileToPin +
-                        ", size = " + length + ", maxSize = " + maxSize);
-                Os.close(fd);
-                return null;
-            }
+            Slog.d(TAG, "pinRangeStream: " + pinRangeStream);
 
-            long address = Os.mmap(0, length, OsConstants.PROT_READ,
-                    OsConstants.MAP_PRIVATE, fd, offset);
-            Os.close(fd);
-
-            Os.mlock(address, length);
-
-            return new PinnedFile(address, length, fileToPin);
-        } catch (ErrnoException e) {
-            Slog.e(TAG, "Could not pin file " + fileToPin + " with error " + e.getMessage());
-            if(fd.valid()) {
-                try {
-                    Os.close(fd);
-                }
-                catch (ErrnoException eClose) {
-                    Slog.e(TAG, "Failed to close fd, error = " + eClose.getMessage());
-                }
-            }
-            return null;
+            PinRangeSource pinRangeSource = (pinRangeStream != null)
+                ? new PinRangeSourceStream(pinRangeStream)
+                : new PinRangeSourceStatic(0, Integer.MAX_VALUE /* will be clipped */);
+            return pinFileRanges(fileToPin, maxBytesToPin, pinRangeSource);
+        } finally {
+            safeClose(pinRangeStream);
+            safeClose(fileAsZip);  // Also closes any streams we've opened
         }
     }
 
-    private static boolean unpinFile(PinnedFile pf) {
+    /**
+     * Attempt to open a file as a zip file. On any sort of corruption, log, swallow the
+     * error, and return null.
+     */
+    private static ZipFile maybeOpenZip(String fileName) {
+        ZipFile zip = null;
         try {
-            Os.munlock(pf.mAddress, pf.mLength);
-        } catch (ErrnoException e) {
-            Slog.e(TAG, "Failed to unpin file " + pf.mFilename + " with error " + e.getMessage());
-            return false;
+            zip = new ZipFile(fileName);
+        } catch (IOException ex) {
+            Slog.w(TAG,
+                   String.format(
+                       "could not open \"%s\" as zip: pinning as blob",
+                                 fileName),
+                   ex);
         }
-        if (DEBUG) {
-            Slog.i(TAG, "Unpinned file " + pf.mFilename );
+        return zip;
+    }
+
+    /**
+     * Open a pin metadata file in the zip if one is present.
+     *
+     * @param zipFile Zip file to search
+     * @return Open input stream or null on any error
+     */
+    private static InputStream maybeOpenPinMetaInZip(ZipFile zipFile, String fileName) {
+        ZipEntry pinMetaEntry = zipFile.getEntry(PIN_META_FILENAME);
+        InputStream pinMetaStream = null;
+        if (pinMetaEntry != null) {
+            try {
+                pinMetaStream = zipFile.getInputStream(pinMetaEntry);
+            } catch (IOException ex) {
+                Slog.w(TAG,
+                       String.format("error reading pin metadata \"%s\": pinning as blob",
+                                     fileName),
+                       ex);
+            }
         }
-        return true;
+        return pinMetaStream;
+    }
+
+    private static abstract class PinRangeSource {
+        /** Retrive a range to pin.
+         *
+         * @param outPinRange Receives the pin region
+         * @return True if we filled in outPinRange or false if we're out of pin entries
+         */
+        abstract boolean read(PinRange outPinRange);
+    }
+
+    private static final class PinRangeSourceStatic extends PinRangeSource {
+        private final int mPinStart;
+        private final int mPinLength;
+        private boolean mDone = false;
+
+        PinRangeSourceStatic(int pinStart, int pinLength) {
+            mPinStart = pinStart;
+            mPinLength = pinLength;
+        }
+
+        @Override
+        boolean read(PinRange outPinRange) {
+            outPinRange.start = mPinStart;
+            outPinRange.length = mPinLength;
+            boolean done = mDone;
+            mDone = true;
+            return !done;
+        }
+    }
+
+    private static final class PinRangeSourceStream extends PinRangeSource {
+        private final DataInputStream mStream;
+        private boolean mDone = false;
+
+        PinRangeSourceStream(InputStream stream) {
+            mStream = new DataInputStream(stream);
+        }
+
+        @Override
+        boolean read(PinRange outPinRange) {
+            if (!mDone) {
+                try {
+                    outPinRange.start = mStream.readInt();
+                    outPinRange.length = mStream.readInt();
+                } catch (IOException ex) {
+                    mDone = true;
+                }
+            }
+            return !mDone;
+        }
+    }
+
+    /**
+     * Helper for pinFile.
+     *
+     * @param fileToPin Name of file to pin
+     * @param maxBytesToPin Maximum number of bytes to pin
+     * @param pinRangeSource Read PIN_RANGE entries from this stream to tell us what bytes
+     *   to pin.
+     * @return PinnedFile or null on error
+     */
+    private static PinnedFile pinFileRanges(
+        String fileToPin,
+        int maxBytesToPin,
+        PinRangeSource pinRangeSource)
+    {
+        FileDescriptor fd = new FileDescriptor();
+        long address = -1;
+        int mapSize = 0;
+
+        try {
+            int openFlags = (OsConstants.O_RDONLY |
+                             OsConstants.O_CLOEXEC |
+                             OsConstants.O_NOFOLLOW);
+            fd = Os.open(fileToPin, openFlags, 0);
+            mapSize = (int) Math.min(Os.fstat(fd).st_size, Integer.MAX_VALUE);
+            address = Os.mmap(0, mapSize,
+                              OsConstants.PROT_READ,
+                              OsConstants.MAP_SHARED,
+                              fd, /*offset=*/0);
+
+            PinRange pinRange = new PinRange();
+            int bytesPinned = 0;
+
+            // We pin at page granularity, so make sure the limit is page-aligned
+            if (maxBytesToPin % PAGE_SIZE != 0) {
+                maxBytesToPin -= maxBytesToPin % PAGE_SIZE;
+            }
+
+            while (bytesPinned < maxBytesToPin && pinRangeSource.read(pinRange)) {
+                int pinStart = pinRange.start;
+                int pinLength = pinRange.length;
+                pinStart = clamp(0, pinStart, mapSize);
+                pinLength = clamp(0, pinLength, mapSize - pinStart);
+                pinLength = Math.min(maxBytesToPin - bytesPinned, pinLength);
+
+                // mlock doesn't require the region to be page-aligned, but we snap the
+                // lock region to page boundaries anyway so that we don't under-count
+                // locking a single byte of a page as a charge of one byte even though the
+                // OS will retain the whole page. Thanks to this adjustment, we slightly
+                // over-count the pin charge of back-to-back pins touching the same page,
+                // but better that than undercounting. Besides: nothing stops pin metafile
+                // creators from making the actual regions page-aligned.
+                pinLength += pinStart % PAGE_SIZE;
+                pinStart -= pinStart % PAGE_SIZE;
+                if (pinLength % PAGE_SIZE != 0) {
+                    pinLength += PAGE_SIZE - pinLength % PAGE_SIZE;
+                }
+                pinLength = clamp(0, pinLength, maxBytesToPin - bytesPinned);
+
+                if (pinLength > 0) {
+                    if (DEBUG) {
+                        Slog.d(TAG,
+                               String.format(
+                                   "pinning at %s %s bytes of %s",
+                                   pinStart, pinLength, fileToPin));
+                    }
+                    Os.mlock(address + pinStart, pinLength);
+                }
+                bytesPinned += pinLength;
+            }
+
+            PinnedFile pinnedFile = new PinnedFile(address, mapSize, fileToPin, bytesPinned);
+            address = -1;  // Ownership transferred
+            return pinnedFile;
+        } catch (ErrnoException ex) {
+            Slog.e(TAG, "Could not pin file " + fileToPin, ex);
+            return null;
+        } finally {
+            safeClose(fd);
+            if (address >= 0) {
+                safeMunmap(address, mapSize);
+            }
+        }
+    }
+
+    private static int clamp(int min, int value, int max) {
+        return Math.max(min, Math.min(value, max));
+    }
+
+    private static void safeMunmap(long address, long mapSize) {
+        try {
+            Os.munmap(address, mapSize);
+        } catch (ErrnoException ex) {
+            Slog.w(TAG, "ignoring error in unmap", ex);
+        }
+    }
+
+    /**
+     * Close FD, swallowing irrelevant errors.
+     */
+    private static void safeClose(@Nullable FileDescriptor fd) {
+        if (fd != null && fd.valid()) {
+            try {
+                Os.close(fd);
+            } catch (ErrnoException ex) {
+                // Swallow the exception: non-EBADF errors in close(2)
+                // indicate deferred paging write errors, which we
+                // don't care about here. The underlying file
+                // descriptor is always closed.
+                if (ex.errno == OsConstants.EBADF) {
+                    throw new AssertionError(ex);
+                }
+            }
+        }
+    }
+
+    /**
+     * Close closeable thing, swallowing errors.
+     */
+    private static void safeClose(@Nullable Closeable thing) {
+        if (thing != null) {
+            try {
+                thing.close();
+            } catch (IOException ex) {
+                Slog.w(TAG, "ignoring error closing resource: " + thing, ex);
+            }
+        }
+    }
+
+    private synchronized ArrayList<PinnedFile> snapshotPinnedFiles() {
+        int nrPinnedFiles = mPinnedFiles.size() + mPinnedCameraFiles.size();
+        ArrayList<PinnedFile> pinnedFiles = new ArrayList<>(nrPinnedFiles);
+        pinnedFiles.addAll(mPinnedFiles);
+        pinnedFiles.addAll(mPinnedCameraFiles);
+        return pinnedFiles;
     }
 
     private final class BinderService extends Binder {
@@ -373,31 +594,44 @@
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
             long totalSize = 0;
-            pw.println("Pinned Files:");
-            synchronized(this) {
-                for (int i = 0; i < mPinnedFiles.size(); i++) {
-                    pw.println(mPinnedFiles.get(i).mFilename);
-                    totalSize += mPinnedFiles.get(i).mLength;
-                }
-                for (int i = 0; i < mPinnedCameraFiles.size(); i++) {
-                    pw.println(mPinnedCameraFiles.get(i).mFilename);
-                    totalSize += mPinnedCameraFiles.get(i).mLength;
-                }
+            for (PinnedFile pinnedFile : snapshotPinnedFiles()) {
+                pw.format("%s %s\n", pinnedFile.fileName, pinnedFile.bytesPinned);
+                totalSize += pinnedFile.bytesPinned;
             }
-            pw.println("Total size: " + totalSize);
+            pw.format("Total size: %s\n", totalSize);
         }
     }
 
-    private static class PinnedFile {
-        long mAddress;
-        long mLength;
-        String mFilename;
+    private static final class PinnedFile implements AutoCloseable {
+        private long mAddress;
+        final int mapSize;
+        final String fileName;
+        final int bytesPinned;
 
-        PinnedFile(long address, long length, String filename) {
+        PinnedFile(long address, int mapSize, String fileName, int bytesPinned) {
              mAddress = address;
-             mLength = length;
-             mFilename = filename;
+             this.mapSize = mapSize;
+             this.fileName = fileName;
+             this.bytesPinned = bytesPinned;
         }
+
+        @Override
+        public void close() {
+            if (mAddress >= 0) {
+                safeMunmap(mAddress, mapSize);
+                mAddress = -1;
+            }
+        }
+
+        @Override
+        public void finalize() {
+            close();
+        }
+    }
+
+    final static class PinRange {
+        int start;
+        int length;
     }
 
     final class PinnerHandler extends Handler {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 113f452..67a16bd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -37,9 +37,7 @@
 import static android.app.ActivityManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
 import static android.app.ActivityManagerInternal.ASSIST_KEY_STRUCTURE;
 import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
-import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
 import static android.app.AppOpsManager.OP_NONE;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -5128,6 +5126,7 @@
         final ActivityRecord sourceRecord;
         final int targetUid;
         final String targetPackage;
+        final boolean isResolver;
         synchronized (this) {
             if (resultTo == null) {
                 throw new SecurityException("Must be called from an activity");
@@ -5165,6 +5164,7 @@
             }
             targetUid = sourceRecord.launchedFromUid;
             targetPackage = sourceRecord.launchedFromPackage;
+            isResolver = sourceRecord.isResolverOrChildActivity();
         }
 
         if (userId == UserHandle.USER_NULL) {
@@ -5184,6 +5184,7 @@
                     .setActivityOptions(bOptions)
                     .setMayWait(userId)
                     .setIgnoreTargetSecurity(ignoreTargetSecurity)
+                    .setFilterCallingUid(isResolver ? 0 /* system */ : targetUid)
                     .execute();
         } catch (SecurityException e) {
             // XXX need to figure out how to propagate to original app.
@@ -15952,7 +15953,10 @@
     }
 
     @Override
-    public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) {
+    public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outState) {
+        if (outState == null) {
+            throw new IllegalArgumentException("outState is null");
+        }
         enforceNotIsolatedCaller("getMyMemoryState");
 
         final int callingUid = Binder.getCallingUid();
@@ -15963,7 +15967,9 @@
             synchronized (mPidsSelfLocked) {
                 proc = mPidsSelfLocked.get(Binder.getCallingPid());
             }
-            fillInProcMemInfo(proc, outInfo, clientTargetSdk);
+            if (proc != null) {
+                fillInProcMemInfo(proc, outState, clientTargetSdk);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 73710d3..ef5a5a3 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -826,6 +826,18 @@
         return ResolverActivity.class.getName().equals(realActivity.getClassName());
     }
 
+    boolean isResolverOrChildActivity() {
+        if (!"android".equals(packageName)) {
+            return false;
+        }
+        try {
+            return ResolverActivity.class.isAssignableFrom(
+                    Object.class.getClassLoader().loadClass(realActivity.getClassName()));
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+    }
+
     ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid,
             int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
             ActivityInfo aInfo, Configuration _configuration,
@@ -1077,6 +1089,11 @@
             // System process can launch home activity.
             return true;
         }
+        // Allow the recents component to launch the home activity.
+        final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
+        if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
+            return true;
+        }
         // Resolver activity can launch home activity.
         return sourceRecord != null && sourceRecord.isResolverActivity();
     }
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index bbdc924..a7c3200 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -37,6 +37,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
 import android.view.RemoteAnimationAdapter;
@@ -340,7 +341,7 @@
                     // Collect information about the target of the Intent.
                     ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
                             null, userId, ActivityStarter.computeResolveFilterUid(
-                                    callingUid, realCallingUid));
+                                    callingUid, realCallingUid, UserHandle.USER_NULL));
                     // TODO: New, check if this is correct
                     aInfo = mService.getActivityInfoForUser(aInfo, userId);
 
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index ad434b4..73e3d33 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -312,6 +312,7 @@
         Configuration globalConfig;
         int userId;
         WaitResult waitResult;
+        int filterCallingUid;
 
         /**
          * If set to {@code true}, allows this activity start to look into
@@ -367,6 +368,7 @@
             mayWait = false;
             avoidMoveToFront = false;
             allowPendingRemoteAnimationRegistryLookup = true;
+            filterCallingUid = UserHandle.USER_NULL;
         }
 
         /**
@@ -404,6 +406,7 @@
             avoidMoveToFront = request.avoidMoveToFront;
             allowPendingRemoteAnimationRegistryLookup
                     = request.allowPendingRemoteAnimationRegistryLookup;
+            filterCallingUid = request.filterCallingUid;
         }
     }
 
@@ -792,7 +795,8 @@
                 callingPid = realCallingPid;
 
                 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
-                        computeResolveFilterUid(callingUid, realCallingUid));
+                        computeResolveFilterUid(
+                                callingUid, realCallingUid, mRequest.filterCallingUid));
                 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
                         null /*profilerInfo*/);
 
@@ -984,7 +988,9 @@
         }
 
         ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
-                0 /* matchFlags */, computeResolveFilterUid(callingUid, realCallingUid));
+                0 /* matchFlags */,
+                        computeResolveFilterUid(
+                                callingUid, realCallingUid, mRequest.filterCallingUid));
         if (rInfo == null) {
             UserInfo userInfo = mSupervisor.getUserInfo(userId);
             if (userInfo != null && userInfo.isManagedProfile()) {
@@ -1006,7 +1012,8 @@
                     rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                             PackageManager.MATCH_DIRECT_BOOT_AWARE
                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                            computeResolveFilterUid(callingUid, realCallingUid));
+                            computeResolveFilterUid(
+                                    callingUid, realCallingUid, mRequest.filterCallingUid));
                 }
             }
         }
@@ -1078,8 +1085,8 @@
                         callingPid = Binder.getCallingPid();
                         componentSpecified = true;
                         rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
-                                0 /* matchFlags */, computeResolveFilterUid(callingUid,
-                                        realCallingUid));
+                                0 /* matchFlags */, computeResolveFilterUid(
+                                        callingUid, realCallingUid, mRequest.filterCallingUid));
                         aInfo = rInfo != null ? rInfo.activityInfo : null;
                         if (aInfo != null) {
                             aInfo = mService.getActivityInfoForUser(aInfo, userId);
@@ -1173,10 +1180,14 @@
      *
      * @param customCallingUid The UID on whose behalf to make the call.
      * @param actualCallingUid The UID actually making the call.
+     * @param filterCallingUid The UID to be used to filter for instant apps.
      * @return The logical UID making the call.
      */
-    static int computeResolveFilterUid(int customCallingUid, int actualCallingUid) {
-        return customCallingUid >= 0 ? customCallingUid : actualCallingUid;
+    static int computeResolveFilterUid(int customCallingUid, int actualCallingUid,
+            int filterCallingUid) {
+        return filterCallingUid != UserHandle.USER_NULL
+                ? filterCallingUid
+                : (customCallingUid >= 0 ? customCallingUid : actualCallingUid);
     }
 
     private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
@@ -2562,6 +2573,11 @@
         return this;
     }
 
+    ActivityStarter setFilterCallingUid(int filterCallingUid) {
+        mRequest.filterCallingUid = filterCallingUid;
+        return this;
+    }
+
     ActivityStarter setComponentSpecified(boolean componentSpecified) {
         mRequest.componentSpecified = componentSpecified;
         return this;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 7c9a3ae..28665e3 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3795,7 +3795,7 @@
                             queueMsgUnderWakeLock(mAudioHandler,
                                     MSG_SET_A2DP_SINK_CONNECTION_STATE,
                                     state,
-                                    0 /* arg2 unused */,
+                                    -1,
                                     btDevice,
                                     delay);
                         }
@@ -4641,22 +4641,22 @@
     public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
     {
         return setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
-                device, state, profile, false /* suppressNoisyIntent */);
+                device, state, profile, false /* suppressNoisyIntent */, -1 /* a2dpVolume */);
     }
 
     public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device,
-                int state, int profile, boolean suppressNoisyIntent)
+                int state, int profile, boolean suppressNoisyIntent, int a2dpVolume)
     {
         if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, device)) {
             return 0;
         }
         return setBluetoothA2dpDeviceConnectionStateInt(
-                device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE);
+                device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE, a2dpVolume);
     }
 
     public int setBluetoothA2dpDeviceConnectionStateInt(
             BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
-            int musicDevice)
+            int musicDevice, int a2dpVolume)
     {
         int delay;
         if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
@@ -4674,7 +4674,7 @@
                     (profile == BluetoothProfile.A2DP ?
                         MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
                     state,
-                    0 /* arg2 unused */,
+                    a2dpVolume,
                     device,
                     delay);
         }
@@ -5204,41 +5204,41 @@
         }
     }
 
-    /** Handles internal volume messages in separate volume thread. */
-    private class AudioHandler extends Handler {
+    private void setDeviceVolume(VolumeStreamState streamState, int device) {
 
-        private void setDeviceVolume(VolumeStreamState streamState, int device) {
+        synchronized (VolumeStreamState.class) {
+            // Apply volume
+            streamState.applyDeviceVolume_syncVSS(device);
 
-            synchronized (VolumeStreamState.class) {
-                // Apply volume
-                streamState.applyDeviceVolume_syncVSS(device);
-
-                // Apply change to all streams using this one as alias
-                int numStreamTypes = AudioSystem.getNumStreamTypes();
-                for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
-                    if (streamType != streamState.mStreamType &&
-                            mStreamVolumeAlias[streamType] == streamState.mStreamType) {
-                        // Make sure volume is also maxed out on A2DP device for aliased stream
-                        // that may have a different device selected
-                        int streamDevice = getDeviceForStream(streamType);
-                        if ((device != streamDevice) && mAvrcpAbsVolSupported &&
-                                ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
-                            mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
-                        }
-                        mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
+            // Apply change to all streams using this one as alias
+            int numStreamTypes = AudioSystem.getNumStreamTypes();
+            for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+                if (streamType != streamState.mStreamType &&
+                        mStreamVolumeAlias[streamType] == streamState.mStreamType) {
+                    // Make sure volume is also maxed out on A2DP device for aliased stream
+                    // that may have a different device selected
+                    int streamDevice = getDeviceForStream(streamType);
+                    if ((device != streamDevice) && mAvrcpAbsVolSupported &&
+                            ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
+                        mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
                     }
+                    mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
                 }
             }
-            // Post a persist volume msg
-            sendMsg(mAudioHandler,
-                    MSG_PERSIST_VOLUME,
-                    SENDMSG_QUEUE,
-                    device,
-                    0,
-                    streamState,
-                    PERSIST_DELAY);
-
         }
+        // Post a persist volume msg
+        sendMsg(mAudioHandler,
+                MSG_PERSIST_VOLUME,
+                SENDMSG_QUEUE,
+                device,
+                0,
+                streamState,
+                PERSIST_DELAY);
+
+    }
+
+    /** Handles internal volume messages in separate volume thread. */
+    private class AudioHandler extends Handler {
 
         private void setAllVolumes(VolumeStreamState streamState) {
 
@@ -5605,7 +5605,7 @@
                     break;
 
                 case MSG_SET_A2DP_SINK_CONNECTION_STATE:
-                    onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1);
+                    onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1, msg.arg2);
                     mAudioEventWakeLock.release();
                     break;
 
@@ -5899,7 +5899,7 @@
         return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
     }
 
-    private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state)
+    private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state, int a2dpVolume)
     {
         if (DEBUG_DEVICES) {
             Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice+"state=" + state);
@@ -5944,6 +5944,14 @@
                         makeA2dpDeviceUnavailableNow(mDockAddress);
                     }
                 }
+                if (a2dpVolume != -1) {
+                    VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
+                    // Convert index to internal representation in VolumeStreamState
+                    a2dpVolume = a2dpVolume * 10;
+                    streamState.setIndex(a2dpVolume, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                            "onSetA2dpSinkConnectionState");
+                    setDeviceVolume(streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+                }
                 makeA2dpDeviceAvailable(address, btDevice.getName(),
                         "onSetA2dpSinkConnectionState");
                 setCurrentAudioRouteName(btDevice.getAliasName());
@@ -6046,7 +6054,7 @@
                    // consistent with audio policy manager state
                    setBluetoothA2dpDeviceConnectionStateInt(
                            btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
-                           false /* suppressNoisyIntent */, musicDevice);
+                           false /* suppressNoisyIntent */, musicDevice, -1 /* a2dpVolume */);
                }
             }
         }
@@ -6056,6 +6064,9 @@
         // address is not used for now, but may be used when multiple a2dp devices are supported
         synchronized (mA2dpAvrcpLock) {
             mAvrcpAbsVolSupported = support;
+            sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
+                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
+                    mStreamStates[AudioSystem.STREAM_MUSIC], 0);
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index c81624a..9b9a380 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -19,7 +19,11 @@
 import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
 import static android.net.CaptivePortal.APP_RETURN_UNWANTED;
 import static android.net.CaptivePortal.APP_RETURN_WANTED_AS_IS;
+import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
+import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL;
+import static android.net.metrics.ValidationProbeEvent.PROBE_FALLBACK;
 
+import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -34,6 +38,8 @@
 import android.net.ProxyInfo;
 import android.net.TrafficStats;
 import android.net.Uri;
+import android.net.captiveportal.CaptivePortalProbeResult;
+import android.net.captiveportal.CaptivePortalProbeSpec;
 import android.net.dns.ResolvUtil;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkEvent;
@@ -62,6 +68,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -258,6 +265,8 @@
     private final URL mCaptivePortalHttpsUrl;
     private final URL mCaptivePortalHttpUrl;
     private final URL[] mCaptivePortalFallbackUrls;
+    @Nullable
+    private final CaptivePortalProbeSpec[] mCaptivePortalFallbackSpecs;
 
     @VisibleForTesting
     protected boolean mIsCaptivePortalCheckEnabled;
@@ -333,6 +342,7 @@
         mCaptivePortalHttpsUrl = makeURL(getCaptivePortalServerHttpsUrl());
         mCaptivePortalHttpUrl = makeURL(getCaptivePortalServerHttpUrl(settings, context));
         mCaptivePortalFallbackUrls = makeCaptivePortalFallbackUrls();
+        mCaptivePortalFallbackSpecs = makeCaptivePortalFallbackProbeSpecs();
 
         start();
     }
@@ -541,8 +551,12 @@
                                     sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
                                 }
                             }));
-                    intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL,
-                            mLastPortalProbeResult.detectUrl);
+                    final CaptivePortalProbeResult probeRes = mLastPortalProbeResult;
+                    intent.putExtra(EXTRA_CAPTIVE_PORTAL_URL, probeRes.detectUrl);
+                    if (probeRes.probeSpec != null) {
+                        final String encodedSpec = probeRes.probeSpec.getEncodedSpec();
+                        intent.putExtra(EXTRA_CAPTIVE_PORTAL_PROBE_SPEC, encodedSpec);
+                    }
                     intent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT,
                             mCaptivePortalUserAgent);
                     intent.setFlags(
@@ -561,47 +575,6 @@
         }
     }
 
-    /**
-     * Result of calling isCaptivePortal().
-     * @hide
-     */
-    @VisibleForTesting
-    public static final class CaptivePortalProbeResult {
-        static final int SUCCESS_CODE = 204;
-        static final int FAILED_CODE = 599;
-
-        static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE);
-        static final CaptivePortalProbeResult SUCCESS = new CaptivePortalProbeResult(SUCCESS_CODE);
-
-        private final int mHttpResponseCode;  // HTTP response code returned from Internet probe.
-        final String redirectUrl;             // Redirect destination returned from Internet probe.
-        final String detectUrl;               // URL where a 204 response code indicates
-                                              // captive portal has been appeased.
-
-        public CaptivePortalProbeResult(
-                int httpResponseCode, String redirectUrl, String detectUrl) {
-            mHttpResponseCode = httpResponseCode;
-            this.redirectUrl = redirectUrl;
-            this.detectUrl = detectUrl;
-        }
-
-        public CaptivePortalProbeResult(int httpResponseCode) {
-            this(httpResponseCode, null, null);
-        }
-
-        boolean isSuccessful() {
-            return mHttpResponseCode == SUCCESS_CODE;
-        }
-
-        boolean isPortal() {
-            return !isSuccessful() && (mHttpResponseCode >= 200) && (mHttpResponseCode <= 399);
-        }
-
-        boolean isFailed() {
-            return !isSuccessful() && !isPortal();
-        }
-    }
-
     // Being in the EvaluatingState State indicates the Network is being evaluated for internet
     // connectivity, or that the user has indicated that this network is unwanted.
     private class EvaluatingState extends State {
@@ -822,8 +795,9 @@
         private void resolveStrictModeHostname() {
             try {
                 // Do a blocking DNS resolution using the network-assigned nameservers.
+                // Do not set AI_ADDRCONFIG in ai_flags so we get all address families in advance.
                 final InetAddress[] ips = ResolvUtil.blockingResolveAllLocally(
-                        mNetwork, mPrivateDnsProviderHostname);
+                        mNetwork, mPrivateDnsProviderHostname, 0 /* aiFlags */);
                 mPrivateDnsConfig = new PrivateDnsConfig(mPrivateDnsProviderHostname, ips);
             } catch (UnknownHostException uhe) {
                 mPrivateDnsConfig = null;
@@ -922,23 +896,47 @@
     }
 
     private URL[] makeCaptivePortalFallbackUrls() {
-        String separator = ",";
-        String firstUrl = mSettings.getSetting(mContext,
-                Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL);
-        String joinedUrls = firstUrl + separator + mSettings.getSetting(mContext,
-                Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS, DEFAULT_OTHER_FALLBACK_URLS);
-        List<URL> urls = new ArrayList<>();
-        for (String s : joinedUrls.split(separator)) {
-            URL u = makeURL(s);
-            if (u == null) {
-                continue;
+        try {
+            String separator = ",";
+            String firstUrl = mSettings.getSetting(mContext,
+                    Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL, DEFAULT_FALLBACK_URL);
+            String joinedUrls = firstUrl + separator + mSettings.getSetting(mContext,
+                    Settings.Global.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS,
+                    DEFAULT_OTHER_FALLBACK_URLS);
+            List<URL> urls = new ArrayList<>();
+            for (String s : joinedUrls.split(separator)) {
+                URL u = makeURL(s);
+                if (u == null) {
+                    continue;
+                }
+                urls.add(u);
             }
-            urls.add(u);
+            if (urls.isEmpty()) {
+                Log.e(TAG, String.format("could not create any url from %s", joinedUrls));
+            }
+            return urls.toArray(new URL[urls.size()]);
+        } catch (Exception e) {
+            // Don't let a misconfiguration bootloop the system.
+            Log.e(TAG, "Error parsing configured fallback URLs", e);
+            return new URL[0];
         }
-        if (urls.isEmpty()) {
-            Log.e(TAG, String.format("could not create any url from %s", joinedUrls));
+    }
+
+    private CaptivePortalProbeSpec[] makeCaptivePortalFallbackProbeSpecs() {
+        try {
+            final String settingsValue = mSettings.getSetting(
+                    mContext, Settings.Global.CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS, null);
+            // Probe specs only used if configured in settings
+            if (TextUtils.isEmpty(settingsValue)) {
+                return null;
+            }
+
+            return CaptivePortalProbeSpec.parseCaptivePortalProbeSpecs(settingsValue);
+        } catch (Exception e) {
+            // Don't let a misconfiguration bootloop the system.
+            Log.e(TAG, "Error parsing configured fallback probe specs", e);
+            return null;
         }
-        return urls.toArray(new URL[urls.size()]);
     }
 
     private String getCaptivePortalUserAgent() {
@@ -955,6 +953,15 @@
         return mCaptivePortalFallbackUrls[idx];
     }
 
+    private CaptivePortalProbeSpec nextFallbackSpec() {
+        if (ArrayUtils.isEmpty(mCaptivePortalFallbackSpecs)) {
+            return null;
+        }
+        // Randomly change spec without memory. Also randomize the first attempt.
+        final int idx = Math.abs(new Random().nextInt()) % mCaptivePortalFallbackSpecs.length;
+        return mCaptivePortalFallbackSpecs[idx];
+    }
+
     @VisibleForTesting
     protected CaptivePortalProbeResult isCaptivePortal() {
         if (!mIsCaptivePortalCheckEnabled) {
@@ -1025,7 +1032,7 @@
         // unnecessary resolution.
         final String host = (proxy != null) ? proxy.getHost() : url.getHost();
         sendDnsProbe(host);
-        return sendHttpProbe(url, probeType);
+        return sendHttpProbe(url, probeType, null);
     }
 
     /** Do a DNS resolution of the given server. */
@@ -1061,7 +1068,8 @@
      * @return a CaptivePortalProbeResult inferred from the HTTP response.
      */
     @VisibleForTesting
-    protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType) {
+    protected CaptivePortalProbeResult sendHttpProbe(URL url, int probeType,
+            @Nullable CaptivePortalProbeSpec probeSpec) {
         HttpURLConnection urlConnection = null;
         int httpResponseCode = CaptivePortalProbeResult.FAILED_CODE;
         String redirectUrl = null;
@@ -1133,7 +1141,12 @@
             TrafficStats.setThreadStatsTag(oldTag);
         }
         logValidationProbe(probeTimer.stop(), probeType, httpResponseCode);
-        return new CaptivePortalProbeResult(httpResponseCode, redirectUrl, url.toString());
+
+        if (probeSpec == null) {
+            return new CaptivePortalProbeResult(httpResponseCode, redirectUrl, url.toString());
+        } else {
+            return probeSpec.getResult(httpResponseCode, redirectUrl);
+        }
     }
 
     private CaptivePortalProbeResult sendParallelHttpProbes(
@@ -1196,11 +1209,12 @@
         if (httpsResult.isPortal() || httpsResult.isSuccessful()) {
             return httpsResult;
         }
-        // If a fallback url exists, use a fallback probe to try again portal detection.
-        URL fallbackUrl = nextFallbackUrl();
+        // If a fallback method exists, use it to retry portal detection.
+        // If we have new-style probe specs, use those. Otherwise, use the fallback URLs.
+        final CaptivePortalProbeSpec probeSpec = nextFallbackSpec();
+        final URL fallbackUrl = (probeSpec != null) ? probeSpec.getUrl() : nextFallbackUrl();
         if (fallbackUrl != null) {
-            CaptivePortalProbeResult result =
-                    sendHttpProbe(fallbackUrl, ValidationProbeEvent.PROBE_FALLBACK);
+            CaptivePortalProbeResult result = sendHttpProbe(fallbackUrl, PROBE_FALLBACK, probeSpec);
             if (result.isPortal()) {
                 return result;
             }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2fda08e..a9198983 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -172,10 +172,13 @@
     private PendingIntent mStatusIntent;
     private volatile boolean mEnableTeardown = true;
     private final INetworkManagementService mNetd;
-    private VpnConfig mConfig;
-    private NetworkAgent mNetworkAgent;
+    @VisibleForTesting
+    protected VpnConfig mConfig;
+    @VisibleForTesting
+    protected NetworkAgent mNetworkAgent;
     private final Looper mLooper;
-    private final NetworkCapabilities mNetworkCapabilities;
+    @VisibleForTesting
+    protected final NetworkCapabilities mNetworkCapabilities;
     private final SystemServices mSystemServices;
 
     /**
@@ -316,15 +319,12 @@
         boolean roaming = false;
         boolean congested = false;
 
-        if (ArrayUtils.isEmpty(underlyingNetworks)) {
-            // No idea what the underlying networks are; assume sane defaults
-            metered = true;
-            roaming = false;
-            congested = false;
-        } else {
+        boolean hadUnderlyingNetworks = false;
+        if (null != underlyingNetworks) {
             for (Network underlying : underlyingNetworks) {
                 final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
                 if (underlyingCaps == null) continue;
+                hadUnderlyingNetworks = true;
                 for (int underlyingType : underlyingCaps.getTransportTypes()) {
                     transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
                 }
@@ -340,6 +340,12 @@
                 congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
             }
         }
+        if (!hadUnderlyingNetworks) {
+            // No idea what the underlying networks are; assume sane defaults
+            metered = true;
+            roaming = false;
+            congested = false;
+        }
 
         caps.setTransportTypes(transportTypes);
         caps.setLinkDownstreamBandwidthKbps(downKbps);
@@ -1071,7 +1077,8 @@
 
     // Returns true if the VPN has been established and the calling UID is its owner. Used to check
     // that a call to mutate VPN state is admissible.
-    private boolean isCallerEstablishedOwnerLocked() {
+    @VisibleForTesting
+    protected boolean isCallerEstablishedOwnerLocked() {
         return isRunningLocked() && Binder.getCallingUid() == mOwnerUID;
     }
 
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index 213ec36..0b6786c 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -189,6 +189,13 @@
         mController = new ColorDisplayController(getContext(), mCurrentUser);
         mController.setListener(this);
 
+        // Set the color mode, if valid, and immediately apply the updated tint matrix based on the
+        // existing activated state. This ensures consistency of tint across the color mode change.
+        onDisplayColorModeChanged(mController.getColorMode());
+
+        // Reset the activated state.
+        mIsActivated = null;
+
         setCoefficientMatrix(getContext(), DisplayTransformManager.needsLinearColorMatrix());
 
         // Prepare color transformation matrix.
@@ -201,9 +208,6 @@
         if (mIsActivated == null) {
             onActivated(mController.isActivated());
         }
-
-        // Transition the screen to the current temperature.
-        applyTint(false);
     }
 
     private void tearDown() {
@@ -223,8 +227,6 @@
             mColorMatrixAnimator.end();
             mColorMatrixAnimator = null;
         }
-
-        mIsActivated = null;
     }
 
     @Override
@@ -288,6 +290,10 @@
 
     @Override
     public void onDisplayColorModeChanged(int mode) {
+        if (mode == -1) {
+            return;
+        }
+
         // Cancel the night display tint animator if it's running.
         if (mColorMatrixAnimator != null) {
             mColorMatrixAnimator.cancel();
@@ -297,7 +303,8 @@
         setMatrix(mController.getColorTemperature(), mMatrixNight);
 
         final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
-        dtm.setColorMode(mode, mIsActivated ? mMatrixNight : MATRIX_IDENTITY);
+        dtm.setColorMode(mode, (mIsActivated != null && mIsActivated) ? mMatrixNight
+                : MATRIX_IDENTITY);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1be507e..99412c5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -489,6 +489,7 @@
         mTemporaryScreenBrightness = -1;
         mPendingScreenBrightnessSetting = -1;
         mTemporaryAutoBrightnessAdjustment = Float.NaN;
+        mPendingAutoBrightnessAdjustment = Float.NaN;
     }
 
     /**
@@ -815,7 +816,7 @@
             mAppliedTemporaryAutoBrightnessAdjustment = true;
         } else {
             autoBrightnessAdjustment = mAutoBrightnessAdjustment;
-            mAppliedTemporaryAutoBrightnessAdjustment = true;
+            mAppliedTemporaryAutoBrightnessAdjustment = false;
         }
 
         // Apply brightness boost.
@@ -1499,6 +1500,7 @@
             return false;
         }
         if (mAutoBrightnessAdjustment == mPendingAutoBrightnessAdjustment) {
+            mPendingAutoBrightnessAdjustment = Float.NaN;
             return false;
         }
         mAutoBrightnessAdjustment = mPendingAutoBrightnessAdjustment;
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 2a6f7c8..06329e57 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -1500,7 +1500,10 @@
                 userId = getUserOrWorkProfileId(clientPackage, userId);
                 if (userId != mCurrentUserId) {
                     int firstSdkInt = Build.VERSION.FIRST_SDK_INT;
-                    if (firstSdkInt == 0) firstSdkInt = Build.VERSION.SDK_INT;
+                    if (firstSdkInt < Build.VERSION_CODES.BASE) {
+                        Slog.e(TAG, "First SDK version " + firstSdkInt + " is invalid; must be " +
+                                "at least VERSION_CODES.BASE");
+                    }
                     File baseDir;
                     if (firstSdkInt <= Build.VERSION_CODES.O_MR1) {
                         baseDir = Environment.getUserSystemDirectory(userId);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 1078f6e..36b04fc 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2537,6 +2537,7 @@
      * Returns a fixed pseudorandom byte string derived from the user's synthetic password.
      * This is used to salt the password history hash to protect the hash against offline
      * bruteforcing, since rederiving this value requires a successful authentication.
+     * If user is a managed profile with unified challenge, currentCredential is ignored.
      */
     @Override
     public byte[] getHashFactor(String currentCredential, int userId) throws RemoteException {
@@ -2544,6 +2545,14 @@
         if (TextUtils.isEmpty(currentCredential)) {
             currentCredential = null;
         }
+        if (isManagedProfileWithUnifiedLock(userId)) {
+            try {
+                currentCredential = getDecryptedPasswordForTiedProfile(userId);
+            } catch (Exception e) {
+                Slog.e(TAG, "Failed to get work profile credential", e);
+                return null;
+            }
+        }
         synchronized (mSpManager) {
             if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
                 Slog.w(TAG, "Synthetic password not enabled");
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index b3aa0bf..442354b 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -235,6 +235,7 @@
      * @param packageName The package that made the original volume request.
      * @param pid The pid that made the original volume request.
      * @param uid The uid that made the original volume request.
+     * @param caller caller binder. can be {@code null} if it's from the volume key.
      * @param asSystemService {@code true} if the event sent to the session as if it was come from
      *          the system service instead of the app process. This helps sessions to distinguish
      *          between the key injection by the app and key events from the hardware devices.
@@ -244,8 +245,9 @@
      * @param flags Any of the flags from {@link AudioManager}.
      * @param useSuggested True to use adjustSuggestedStreamVolume instead of
      */
-    public void adjustVolume(String packageName, int pid, int uid, boolean asSystemService,
-            int direction, int flags, boolean useSuggested) {
+    public void adjustVolume(String packageName, int pid, int uid,
+            ISessionControllerCallback caller, boolean asSystemService, int direction, int flags,
+            boolean useSuggested) {
         int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND;
         if (isPlaybackActive() || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
             flags &= ~AudioManager.FLAG_PLAY_SOUND;
@@ -266,7 +268,7 @@
                 Log.w(TAG, "Muting remote playback is not supported");
                 return;
             }
-            mSessionCb.adjustVolume(packageName, pid, uid, asSystemService, direction);
+            mSessionCb.adjustVolume(packageName, pid, uid, caller, asSystemService, direction);
 
             int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
             mOptimisticVolume = volumeBefore + direction;
@@ -285,7 +287,8 @@
         }
     }
 
-    public void setVolumeTo(String packageName, int pid, int uid, int value, int flags) {
+    private void setVolumeTo(String packageName, int pid, int uid,
+            ISessionControllerCallback caller, int value, int flags) {
         if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
             int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
             mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid);
@@ -295,7 +298,7 @@
                 return;
             }
             value = Math.max(0, Math.min(value, mMaxVolume));
-            mSessionCb.setVolumeTo(packageName, pid, uid, value);
+            mSessionCb.setVolumeTo(packageName, pid, uid, caller, value);
 
             int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
             mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume));
@@ -611,6 +614,7 @@
                 try {
                     holder.mCallback.onVolumeInfoChanged(info);
                 } catch (DeadObjectException e) {
+                    mControllerCallbackHolders.remove(i);
                     logCallbackException("Removing dead callback in pushVolumeUpdate", holder, e);
                 } catch (RemoteException e) {
                     logCallbackException("Unexpected exception in pushVolumeUpdate", holder, e);
@@ -629,8 +633,8 @@
                 try {
                     holder.mCallback.onEvent(event, data);
                 } catch (DeadObjectException e) {
-                    logCallbackException("Removing dead callback in pushEvent", holder, e);
                     mControllerCallbackHolders.remove(i);
+                    logCallbackException("Removing dead callback in pushEvent", holder, e);
                 } catch (RemoteException e) {
                     logCallbackException("unexpected exception in pushEvent", holder, e);
                 }
@@ -705,14 +709,6 @@
         return -1;
     }
 
-    private String getPackageName(int uid) {
-        String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
-        if (packages != null && packages.length > 0) {
-            return packages[0];
-        }
-        return null;
-    }
-
     private final Runnable mClearOptimisticVolumeRunnable = new Runnable() {
         @Override
         public void run() {
@@ -913,14 +909,13 @@
 
         public boolean sendMediaButton(String packageName, int pid, int uid,
                 boolean asSystemService, KeyEvent keyEvent, int sequenceId, ResultReceiver cb) {
-            Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
-            mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
             try {
                 if (asSystemService) {
                     mCb.onMediaButton(mContext.getPackageName(), Process.myPid(),
-                            Process.SYSTEM_UID, mediaButtonIntent, sequenceId, cb);
+                            Process.SYSTEM_UID, createMediaButtonIntent(keyEvent), sequenceId, cb);
                 } else {
-                    mCb.onMediaButton(packageName, pid, uid, mediaButtonIntent, sequenceId, cb);
+                    mCb.onMediaButton(packageName, pid, uid,
+                            createMediaButtonIntent(keyEvent), sequenceId, cb);
                 }
                 return true;
             } catch (RemoteException e) {
@@ -929,205 +924,239 @@
             return false;
         }
 
-        public void sendCommand(String packageName, int pid, int uid, String command, Bundle args,
-                ResultReceiver cb) {
+        public boolean sendMediaButton(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, boolean asSystemService,
+                KeyEvent keyEvent) {
             try {
-                mCb.onCommand(packageName, pid, uid, command, args, cb);
+                if (asSystemService) {
+                    mCb.onMediaButton(mContext.getPackageName(), Process.myPid(),
+                            Process.SYSTEM_UID, createMediaButtonIntent(keyEvent), 0, null);
+                } else {
+                    mCb.onMediaButtonFromController(packageName, pid, uid, caller,
+                            createMediaButtonIntent(keyEvent));
+                }
+                return true;
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in sendMediaRequest.", e);
+            }
+            return false;
+        }
+
+        public void sendCommand(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String command, Bundle args, ResultReceiver cb) {
+            try {
+                mCb.onCommand(packageName, pid, uid, caller, command, args, cb);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in sendCommand.", e);
             }
         }
 
-        public void sendCustomAction(String packageName, int pid, int uid, String action,
+        public void sendCustomAction(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String action,
                 Bundle args) {
             try {
-                mCb.onCustomAction(packageName, pid, uid, action, args);
+                mCb.onCustomAction(packageName, pid, uid, caller, action, args);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in sendCustomAction.", e);
             }
         }
 
-        public void prepare(String packageName, int pid, int uid) {
+        public void prepare(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             try {
-                mCb.onPrepare(packageName, pid, uid);
+                mCb.onPrepare(packageName, pid, uid, caller);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in prepare.", e);
             }
         }
 
-        public void prepareFromMediaId(String packageName, int pid, int uid, String mediaId,
-                Bundle extras) {
+        public void prepareFromMediaId(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String mediaId, Bundle extras) {
             try {
-                mCb.onPrepareFromMediaId(packageName, pid, uid, mediaId, extras);
+                mCb.onPrepareFromMediaId(packageName, pid, uid, caller, mediaId, extras);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in prepareFromMediaId.", e);
             }
         }
 
-        public void prepareFromSearch(String packageName, int pid, int uid, String query,
-                Bundle extras) {
+        public void prepareFromSearch(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String query, Bundle extras) {
             try {
-                mCb.onPrepareFromSearch(packageName, pid, uid, query, extras);
+                mCb.onPrepareFromSearch(packageName, pid, uid, caller, query, extras);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in prepareFromSearch.", e);
             }
         }
 
-        public void prepareFromUri(String packageName, int pid, int uid, Uri uri,
-                Bundle extras) {
+        public void prepareFromUri(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, Uri uri, Bundle extras) {
             try {
-                mCb.onPrepareFromUri(packageName, pid, uid, uri, extras);
+                mCb.onPrepareFromUri(packageName, pid, uid, caller, uri, extras);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in prepareFromUri.", e);
             }
         }
 
-        public void play(String packageName, int pid, int uid) {
+        public void play(String packageName, int pid, int uid, ISessionControllerCallback caller) {
             try {
-                mCb.onPlay(packageName, pid, uid);
+                mCb.onPlay(packageName, pid, uid, caller);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in play.", e);
             }
         }
 
-        public void playFromMediaId(String packageName, int pid, int uid, String mediaId,
-                Bundle extras) {
+        public void playFromMediaId(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String mediaId, Bundle extras) {
             try {
-                mCb.onPlayFromMediaId(packageName, pid, uid, mediaId, extras);
+                mCb.onPlayFromMediaId(packageName, pid, uid, caller, mediaId, extras);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in playFromMediaId.", e);
             }
         }
 
-        public void playFromSearch(String packageName, int pid, int uid, String query,
-                Bundle extras) {
+        public void playFromSearch(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, String query, Bundle extras) {
             try {
-                mCb.onPlayFromSearch(packageName, pid, uid, query, extras);
+                mCb.onPlayFromSearch(packageName, pid, uid, caller, query, extras);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in playFromSearch.", e);
             }
         }
 
-        public void playFromUri(String packageName, int pid, int uid, Uri uri, Bundle extras) {
+        public void playFromUri(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, Uri uri, Bundle extras) {
             try {
-                mCb.onPlayFromUri(packageName, pid, uid, uri, extras);
+                mCb.onPlayFromUri(packageName, pid, uid, caller, uri, extras);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in playFromUri.", e);
             }
         }
 
-        public void skipToTrack(String packageName, int pid, int uid, long id) {
+        public void skipToTrack(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, long id) {
             try {
-                mCb.onSkipToTrack(packageName, pid, uid, id);
+                mCb.onSkipToTrack(packageName, pid, uid, caller, id);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in skipToTrack", e);
             }
         }
 
-        public void pause(String packageName, int pid, int uid) {
+        public void pause(String packageName, int pid, int uid, ISessionControllerCallback caller) {
             try {
-                mCb.onPause(packageName, pid, uid);
+                mCb.onPause(packageName, pid, uid, caller);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in pause.", e);
             }
         }
 
-        public void stop(String packageName, int pid, int uid) {
+        public void stop(String packageName, int pid, int uid, ISessionControllerCallback caller) {
             try {
-                mCb.onStop(packageName, pid, uid);
+                mCb.onStop(packageName, pid, uid, caller);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in stop.", e);
             }
         }
 
-        public void next(String packageName, int pid, int uid) {
+        public void next(String packageName, int pid, int uid, ISessionControllerCallback caller) {
             try {
-                mCb.onNext(packageName, pid, uid);
+                mCb.onNext(packageName, pid, uid, caller);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in next.", e);
             }
         }
 
-        public void previous(String packageName, int pid, int uid) {
+        public void previous(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             try {
-                mCb.onPrevious(packageName, pid, uid);
+                mCb.onPrevious(packageName, pid, uid, caller);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in previous.", e);
             }
         }
 
-        public void fastForward(String packageName, int pid, int uid) {
+        public void fastForward(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             try {
-                mCb.onFastForward(packageName, pid, uid);
+                mCb.onFastForward(packageName, pid, uid, caller);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in fastForward.", e);
             }
         }
 
-        public void rewind(String packageName, int pid, int uid) {
+        public void rewind(String packageName, int pid, int uid,
+                ISessionControllerCallback caller) {
             try {
-                mCb.onRewind(packageName, pid, uid);
+                mCb.onRewind(packageName, pid, uid, caller);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in rewind.", e);
             }
         }
 
-        public void seekTo(String packageName, int pid, int uid, long pos) {
+        public void seekTo(String packageName, int pid, int uid, ISessionControllerCallback caller,
+                long pos) {
             try {
-                mCb.onSeekTo(packageName, pid, uid, pos);
+                mCb.onSeekTo(packageName, pid, uid, caller, pos);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in seekTo.", e);
             }
         }
 
-        public void rate(String packageName, int pid, int uid, Rating rating) {
+        public void rate(String packageName, int pid, int uid, ISessionControllerCallback caller,
+                Rating rating) {
             try {
-                mCb.onRate(packageName, pid, uid, rating);
+                mCb.onRate(packageName, pid, uid, caller, rating);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in rate.", e);
             }
         }
 
-        public void adjustVolume(String packageName, int pid, int uid, boolean asSystemService,
-                int direction) {
+        public void adjustVolume(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, boolean asSystemService, int direction) {
             try {
                 if (asSystemService) {
                     mCb.onAdjustVolume(mContext.getPackageName(), Process.myPid(),
-                            Process.SYSTEM_UID, direction);
+                            Process.SYSTEM_UID, null, direction);
                 } else {
-                    mCb.onAdjustVolume(packageName, pid, uid, direction);
+                    mCb.onAdjustVolume(packageName, pid, uid, caller, direction);
                 }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in adjustVolume.", e);
             }
         }
 
-        public void setVolumeTo(String packageName, int pid, int uid, int value) {
+        public void setVolumeTo(String packageName, int pid, int uid,
+                ISessionControllerCallback caller, int value) {
             try {
-                mCb.onSetVolumeTo(packageName, pid, uid, value);
+                mCb.onSetVolumeTo(packageName, pid, uid, caller, value);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Remote failure in setVolumeTo.", e);
             }
         }
+
+        private Intent createMediaButtonIntent(KeyEvent keyEvent) {
+            Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+            mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+            return mediaButtonIntent;
+        }
     }
 
     class ControllerStub extends ISessionController.Stub {
         @Override
-        public void sendCommand(String packageName, String command, Bundle args,
-                ResultReceiver cb) {
+        public void sendCommand(String packageName, ISessionControllerCallback caller,
+                String command, Bundle args, ResultReceiver cb) {
             mSessionCb.sendCommand(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
-                    command, args, cb);
+                    caller, command, args, cb);
         }
 
         @Override
-        public boolean sendMediaButton(String packageName, boolean asSystemService,
-                KeyEvent mediaButtonIntent) {
+        public boolean sendMediaButton(String packageName, ISessionControllerCallback cb,
+                boolean asSystemService, KeyEvent keyEvent) {
             return mSessionCb.sendMediaButton(packageName, Binder.getCallingPid(),
-                    Binder.getCallingUid(), asSystemService, mediaButtonIntent, 0, null);
+                    Binder.getCallingUid(), cb, asSystemService, keyEvent);
         }
 
         @Override
-        public void registerCallbackListener(ISessionControllerCallback cb) {
+        public void registerCallbackListener(String packageName, ISessionControllerCallback cb) {
             synchronized (mLock) {
                 // If this session is already destroyed tell the caller and
                 // don't add them.
@@ -1141,24 +1170,24 @@
                 }
                 if (getControllerHolderIndexForCb(cb) < 0) {
                     mControllerCallbackHolders.add(new ISessionControllerCallbackHolder(cb,
-                          Binder.getCallingUid()));
+                            packageName, Binder.getCallingUid()));
                     if (DEBUG) {
-                        Log.d(TAG, "registering controller callback " + cb);
+                        Log.d(TAG, "registering controller callback " + cb + " from controller"
+                                + packageName);
                     }
                 }
             }
         }
 
         @Override
-        public void unregisterCallbackListener(ISessionControllerCallback cb)
-                throws RemoteException {
+        public void unregisterCallbackListener(ISessionControllerCallback cb) {
             synchronized (mLock) {
                 int index = getControllerHolderIndexForCb(cb);
                 if (index != -1) {
                     mControllerCallbackHolders.remove(index);
                 }
                 if (DEBUG) {
-                    Log.d(TAG, "unregistering callback " + cb + ". index=" + index);
+                    Log.d(TAG, "unregistering callback " + cb.asBinder());
                 }
             }
         }
@@ -1204,13 +1233,13 @@
         }
 
         @Override
-        public void adjustVolume(String packageName, boolean asSystemService, int direction,
-                int flags) {
+        public void adjustVolume(String packageName, ISessionControllerCallback caller,
+                boolean asSystemService, int direction, int flags) {
             int pid = Binder.getCallingPid();
             int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
             try {
-                MediaSessionRecord.this.adjustVolume(packageName, pid, uid, asSystemService,
+                MediaSessionRecord.this.adjustVolume(packageName, pid, uid, caller, asSystemService,
                         direction, flags, false /* useSuggested */);
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -1218,115 +1247,128 @@
         }
 
         @Override
-        public void setVolumeTo(String packageName, int value, int flags) {
+        public void setVolumeTo(String packageName, ISessionControllerCallback caller,
+                int value, int flags) {
             int pid = Binder.getCallingPid();
             int uid = Binder.getCallingUid();
             final long token = Binder.clearCallingIdentity();
             try {
-                MediaSessionRecord.this.setVolumeTo(packageName, pid, uid, value, flags);
+                MediaSessionRecord.this.setVolumeTo(packageName, pid, uid, caller, value, flags);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
         }
 
         @Override
-        public void prepare(String packageName) {
-            mSessionCb.prepare(packageName, Binder.getCallingPid(), Binder.getCallingUid());
+        public void prepare(String packageName, ISessionControllerCallback caller) {
+            mSessionCb.prepare(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
         }
 
         @Override
-        public void prepareFromMediaId(String packageName, String mediaId, Bundle extras) {
+        public void prepareFromMediaId(String packageName, ISessionControllerCallback caller,
+                String mediaId, Bundle extras) {
             mSessionCb.prepareFromMediaId(packageName, Binder.getCallingPid(),
-                    Binder.getCallingUid(), mediaId, extras);
+                    Binder.getCallingUid(), caller, mediaId, extras);
         }
 
         @Override
-        public void prepareFromSearch(String packageName, String query, Bundle extras) {
+        public void prepareFromSearch(String packageName, ISessionControllerCallback caller,
+                String query, Bundle extras) {
             mSessionCb.prepareFromSearch(packageName, Binder.getCallingPid(),
-                    Binder.getCallingUid(), query, extras);
+                    Binder.getCallingUid(), caller, query, extras);
         }
 
         @Override
-        public void prepareFromUri(String packageName, Uri uri, Bundle extras) {
+        public void prepareFromUri(String packageName, ISessionControllerCallback caller,
+                Uri uri, Bundle extras) {
             mSessionCb.prepareFromUri(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
-                    uri, extras);
+                    caller, uri, extras);
         }
 
         @Override
-        public void play(String packageName) {
-            mSessionCb.play(packageName, Binder.getCallingPid(), Binder.getCallingUid());
+        public void play(String packageName, ISessionControllerCallback caller) {
+            mSessionCb.play(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
         }
 
         @Override
-        public void playFromMediaId(String packageName, String mediaId, Bundle extras) {
+        public void playFromMediaId(String packageName, ISessionControllerCallback caller,
+                String mediaId, Bundle extras) {
             mSessionCb.playFromMediaId(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
-                    mediaId, extras);
+                    caller, mediaId, extras);
         }
 
         @Override
-        public void playFromSearch(String packageName, String query, Bundle extras) {
+        public void playFromSearch(String packageName, ISessionControllerCallback caller,
+                String query, Bundle extras) {
             mSessionCb.playFromSearch(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
-                    query, extras);
+                    caller, query, extras);
         }
 
         @Override
-        public void playFromUri(String packageName, Uri uri, Bundle extras) {
+        public void playFromUri(String packageName, ISessionControllerCallback caller,
+                Uri uri, Bundle extras) {
             mSessionCb.playFromUri(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
-                    uri, extras);
+                    caller, uri, extras);
         }
 
         @Override
-        public void skipToQueueItem(String packageName, long id) {
-            mSessionCb.skipToTrack(packageName, Binder.getCallingPid(), Binder.getCallingUid(), id);
+        public void skipToQueueItem(String packageName, ISessionControllerCallback caller,
+                long id) {
+            mSessionCb.skipToTrack(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
+                    caller, id);
         }
 
         @Override
-        public void pause(String packageName) {
-            mSessionCb.pause(packageName, Binder.getCallingPid(), Binder.getCallingUid());
+        public void pause(String packageName, ISessionControllerCallback caller) {
+            mSessionCb.pause(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
         }
 
         @Override
-        public void stop(String packageName) {
-            mSessionCb.stop(packageName, Binder.getCallingPid(), Binder.getCallingUid());
+        public void stop(String packageName, ISessionControllerCallback caller) {
+            mSessionCb.stop(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
         }
 
         @Override
-        public void next(String packageName) {
-            mSessionCb.next(packageName, Binder.getCallingPid(), Binder.getCallingUid());
+        public void next(String packageName, ISessionControllerCallback caller) {
+            mSessionCb.next(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
         }
 
         @Override
-        public void previous(String packageName) {
-            mSessionCb.previous(packageName, Binder.getCallingPid(), Binder.getCallingUid());
+        public void previous(String packageName, ISessionControllerCallback caller) {
+            mSessionCb.previous(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
+                    caller);
         }
 
         @Override
-        public void fastForward(String packageName) {
-            mSessionCb.fastForward(packageName, Binder.getCallingPid(), Binder.getCallingUid());
+        public void fastForward(String packageName, ISessionControllerCallback caller) {
+            mSessionCb.fastForward(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
+                    caller);
         }
 
         @Override
-        public void rewind(String packageName) {
-            mSessionCb.rewind(packageName, Binder.getCallingPid(), Binder.getCallingUid());
+        public void rewind(String packageName, ISessionControllerCallback caller) {
+            mSessionCb.rewind(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller);
         }
 
         @Override
-        public void seekTo(String packageName, long pos) {
-            mSessionCb.seekTo(packageName, Binder.getCallingPid(), Binder.getCallingUid(), pos);
+        public void seekTo(String packageName, ISessionControllerCallback caller, long pos) {
+            mSessionCb.seekTo(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller,
+                    pos);
         }
 
         @Override
-        public void rate(String packageName, Rating rating) {
-            mSessionCb.rate(packageName, Binder.getCallingPid(), Binder.getCallingUid(), rating);
+        public void rate(String packageName, ISessionControllerCallback caller, Rating rating) {
+            mSessionCb.rate(packageName, Binder.getCallingPid(), Binder.getCallingUid(), caller,
+                    rating);
         }
 
         @Override
-        public void sendCustomAction(String packageName, String action, Bundle args) {
+        public void sendCustomAction(String packageName, ISessionControllerCallback caller,
+                String action, Bundle args) {
             mSessionCb.sendCustomAction(packageName, Binder.getCallingPid(), Binder.getCallingUid(),
-                    action, args);
+                    caller, action, args);
         }
 
-
         @Override
         public MediaMetadata getMetadata() {
             synchronized (mLock) {
@@ -1372,10 +1414,13 @@
     private class ISessionControllerCallbackHolder {
         private final ISessionControllerCallback mCallback;
         private final String mPackageName;
+        private final int mUid;
 
-        ISessionControllerCallbackHolder(ISessionControllerCallback callback, int uid) {
+        ISessionControllerCallbackHolder(ISessionControllerCallback callback, String packageName,
+                int uid) {
             mCallback = callback;
-            mPackageName = getPackageName(uid);
+            mPackageName = packageName;
+            mUid = uid;
         }
     }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index a6e9389..6fff367 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1851,7 +1851,7 @@
                     }
                 });
             } else {
-                session.adjustVolume(packageName, pid, uid, asSystemService,
+                session.adjustVolume(packageName, pid, uid, null, asSystemService,
                         direction, flags, true);
             }
         }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 5bd7c0b..ab482bb 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2706,6 +2706,9 @@
     private void normalizePoliciesNL(NetworkPolicy[] policies) {
         mNetworkPolicy.clear();
         for (NetworkPolicy policy : policies) {
+            if (policy == null) {
+                continue;
+            }
             // When two normalized templates conflict, prefer the most
             // restrictive policy
             policy.template = NetworkTemplate.normalize(policy.template, mMergedSubscriberIds);
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 4bee55e..a16dcf3 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -241,6 +241,20 @@
         NetworkStats.Entry entry = null;
         for (int i = 0; i < delta.size(); i++) {
             entry = delta.getValues(i, entry);
+
+            // As a last-ditch sanity check, report any negative values and
+            // clamp them so recording below doesn't croak.
+            if (entry.isNegative()) {
+                if (mObserver != null) {
+                    mObserver.foundNonMonotonic(delta, i, mCookie);
+                }
+                entry.rxBytes = Math.max(entry.rxBytes, 0);
+                entry.rxPackets = Math.max(entry.rxPackets, 0);
+                entry.txBytes = Math.max(entry.txBytes, 0);
+                entry.txPackets = Math.max(entry.txPackets, 0);
+                entry.operations = Math.max(entry.operations, 0);
+            }
+
             final NetworkIdentitySet ident = ifaceIdent.get(entry.iface);
             if (ident == null) {
                 unknownIfaces.add(entry.iface);
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 9ef6c66..addc479 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -184,6 +184,8 @@
 
     private final PowerManager.WakeLock mWakeLock;
 
+    private final boolean mUseBpfTrafficStats;
+
     private IConnectivityManager mConnManager;
 
     @VisibleForTesting
@@ -347,6 +349,7 @@
         mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers");
         mSystemDir = checkNotNull(systemDir, "missing systemDir");
         mBaseDir = checkNotNull(baseDir, "missing baseDir");
+        mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
 
         LocalServices.addService(NetworkStatsManagerInternal.class,
                 new NetworkStatsManagerInternalImpl());
@@ -947,7 +950,7 @@
     }
 
     private boolean checkBpfStatsEnable() {
-        return new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
+        return mUseBpfTrafficStats;
     }
 
     /**
@@ -1713,7 +1716,7 @@
         @Override
         public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
                 int rightIndex, String cookie) {
-            Log.w(TAG, "found non-monotonic values; saving to dropbox");
+            Log.w(TAG, "Found non-monotonic values; saving to dropbox");
 
             // record error for debugging
             final StringBuilder builder = new StringBuilder();
@@ -1722,9 +1725,21 @@
             builder.append("left=").append(left).append('\n');
             builder.append("right=").append(right).append('\n');
 
-            final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
-                    Context.DROPBOX_SERVICE);
-            dropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
+            mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
+                    builder.toString());
+        }
+
+        @Override
+        public void foundNonMonotonic(
+                NetworkStats stats, int statsIndex, String cookie) {
+            Log.w(TAG, "Found non-monotonic values; saving to dropbox");
+
+            final StringBuilder builder = new StringBuilder();
+            builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n");
+            builder.append("stats=").append(stats).append('\n');
+
+            mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
+                    builder.toString());
         }
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e2e6f6d..8f7fa1b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -821,6 +821,7 @@
                         }
                     }
                     r.setVisibility(true, nv.rank, nv.count);
+                    maybeRecordInterruptionLocked(r);
                     nv.recycle();
                 }
                 // Note that we might receive this event after notifications
@@ -1928,11 +1929,12 @@
 
     @GuardedBy("mNotificationLock")
     protected void maybeRecordInterruptionLocked(NotificationRecord r) {
-        if (r.isInterruptive()) {
+        if (r.isInterruptive() && !r.hasRecordedInterruption()) {
             mAppUsageStats.reportInterruptiveNotification(r.sbn.getPackageName(),
                     r.getChannel().getId(),
                     getRealUserId(r.sbn.getUserId()));
             logRecentLocked(r);
+            r.setRecordedInterruption(true);
         }
     }
 
@@ -2669,6 +2671,7 @@
                                 if (DBG) Slog.d(TAG, "Marking notification as seen " + keys[i]);
                                 reportSeen(r);
                                 r.setSeen();
+                                maybeRecordInterruptionLocked(r);
                             }
                         }
                     }
@@ -4440,7 +4443,7 @@
                     if (index < 0) {
                         mNotificationList.add(r);
                         mUsageStats.registerPostedByApp(r);
-                        r.setInterruptive(isVisuallyInterruptive(null, r));
+                        r.setInterruptive(true);
                     } else {
                         old = mNotificationList.get(index);
                         mNotificationList.set(index, r);
@@ -4449,7 +4452,7 @@
                         notification.flags |=
                                 old.getNotification().flags & FLAG_FOREGROUND_SERVICE;
                         r.isUpdate = true;
-                        r.setInterruptive(isVisuallyInterruptive(old, r));
+                        r.setTextChanged(isVisuallyInterruptive(old, r));
                     }
 
                     mNotificationsByKey.put(n.getKey(), r);
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 2aec3ea..0f3f44e 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -158,6 +158,8 @@
     private final NotificationStats mStats;
     private int mUserSentiment;
     private boolean mIsInterruptive;
+    private boolean mTextChanged;
+    private boolean mRecordedInterruption;
     private int mNumberOfSmartRepliesAdded;
     private boolean mHasSeenSmartReplies;
     /**
@@ -839,6 +841,9 @@
     /** Mark the notification as seen by the user. */
     public void setSeen() {
         mStats.setSeen();
+        if (mTextChanged) {
+            mIsInterruptive = true;
+        }
     }
 
     public void setAuthoritativeRank(int authoritativeRank) {
@@ -935,6 +940,18 @@
         mIsInterruptive = interruptive;
     }
 
+    public void setTextChanged(boolean textChanged) {
+        mTextChanged = textChanged;
+    }
+
+    public void setRecordedInterruption(boolean recorded) {
+        mRecordedInterruption = recorded;
+    }
+
+    public boolean hasRecordedInterruption() {
+        return mRecordedInterruption;
+    }
+
     public boolean isInterruptive() {
         return mIsInterruptive;
     }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 7f141ee..61b5415e 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -25,22 +25,18 @@
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
-import android.content.pm.Signature;
 import android.metrics.LogMaker;
 import android.os.Build;
 import android.os.UserHandle;
-import android.print.PrintManager;
 import android.provider.Settings.Secure;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.RankingHelperProto;
 import android.service.notification.RankingHelperProto.RecordProto;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.proto.ProtoOutputStream;
@@ -156,6 +152,8 @@
             }
         }
 
+        mAreChannelsBypassingDnd = (mZenModeHelper.getNotificationPolicy().state &
+                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND) == 1;
         updateChannelsBypassingDnd();
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2650ef0..9886a07 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2072,6 +2072,16 @@
                             installerPackageName, null /*finishedReceiver*/,
                             updateUserIds, instantUserIds);
                 }
+                // if the required verifier is defined, but, is not the installer of record
+                // for the package, it gets notified
+                final boolean notifyVerifier = mRequiredVerifierPackage != null
+                        && !mRequiredVerifierPackage.equals(installerPackageName);
+                if (notifyVerifier) {
+                    sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+                            extras, 0 /*flags*/,
+                            mRequiredVerifierPackage, null /*finishedReceiver*/,
+                            updateUserIds, instantUserIds);
+                }
 
                 // Send replaced for users that don't see the package for the first time
                 if (update) {
@@ -2085,6 +2095,12 @@
                                 installerPackageName, null /*finishedReceiver*/,
                                 updateUserIds, instantUserIds);
                     }
+                    if (notifyVerifier) {
+                        sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
+                                extras, 0 /*flags*/,
+                                mRequiredVerifierPackage, null /*finishedReceiver*/,
+                                updateUserIds, instantUserIds);
+                    }
                     sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
                             null /*package*/, null /*extras*/, 0 /*flags*/,
                             packageName /*targetPackage*/,
@@ -8765,8 +8781,16 @@
 
         if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
             // The version of the application on the /system partition is less than or
-            // equal to the version on the /data partition. Throw an exception and use
-            // the application already installed on the /data partition.
+            // equal to the version on the /data partition. Even though the disabled system package
+            // is likely to be replaced by a version on the /data partition, we make assumptions
+            // that it's part of the mPackages collection during package manager initialization. So,
+            // add it to mPackages if there isn't already a package in the collection and then throw
+            // an exception to use the application already installed on the /data partition.
+            synchronized (mPackages) {
+                if (!mPackages.containsKey(pkg.packageName)) {
+                    mPackages.put(pkg.packageName, pkg);
+                }
+            }
             throw new PackageManagerException(Log.WARN, "Package " + pkg.packageName + " at "
                     + pkg.codePath + " ignored: updated version " + pkgSetting.versionCode
                     + " better than this " + pkg.getLongVersionCode());
@@ -14090,13 +14114,9 @@
     public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
             PersistableBundle appExtras, PersistableBundle launcherExtras, String dialogMessage,
             String callingPackage, int userId) {
-        try {
-            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS, null);
-        } catch (SecurityException e) {
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_USERS,
-                    "Callers need to have either " + Manifest.permission.SUSPEND_APPS + " or "
-                            + Manifest.permission.MANAGE_USERS);
-        }
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SUSPEND_APPS,
+                "setPackagesSuspendedAsUser");
+
         final int callingUid = Binder.getCallingUid();
         if (callingUid != Process.ROOT_UID && callingUid != Process.SYSTEM_UID
                 && getPackageUid(callingPackage, 0, userId) != callingUid) {
@@ -24388,6 +24408,9 @@
         if (info.targetSdkVersion < Build.VERSION_CODES.O) {
             return false;
         }
+        if (isInstantApp(packageName, userId)) {
+            return false;
+        }
         String appOpPermission = Manifest.permission.REQUEST_INSTALL_PACKAGES;
         String[] packagesDeclaringPermission = getAppOpPermissionPackages(appOpPermission);
         if (!ArrayUtils.contains(packagesDeclaringPermission, packageName)) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index dd0a5d2..06c56a0 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -873,9 +873,8 @@
             throw new SecurityException("MANAGE_USERS permission is required to start intent "
                     + "after disabling quiet mode.");
         }
-        final boolean hasModifyQuietModePermission = ActivityManager.checkComponentPermission(
-                Manifest.permission.MODIFY_QUIET_MODE,
-                callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
+        final boolean hasModifyQuietModePermission = hasPermissionGranted(
+                Manifest.permission.MODIFY_QUIET_MODE, callingUid);
         if (hasModifyQuietModePermission) {
             return;
         }
@@ -1002,6 +1001,30 @@
         }
     }
 
+    @Override
+    public void setUserAdmin(int userId) {
+        checkManageUserAndAcrossUsersFullPermission("set user admin");
+
+        synchronized (mPackagesLock) {
+            UserInfo info;
+            synchronized (mUsersLock) {
+                info = getUserInfoLU(userId);
+            }
+            if (info == null || info.isAdmin()) {
+                // Exit if no user found with that id, or the user is already an Admin.
+                return;
+            }
+
+            info.flags ^= UserInfo.FLAG_ADMIN;
+            writeUserLP(getUserDataLU(info.id));
+        }
+
+        // Remove non-admin restrictions.
+        // Keep synchronized with createUserEvenWhenDisallowed.
+        setUserRestriction(UserManager.DISALLOW_SMS, false, userId);
+        setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, userId);
+    }
+
     /**
      * Evicts a user's CE key by stopping and restarting the user.
      *
@@ -1122,8 +1145,8 @@
                 hasManageUsersPermission()) {
             return;
         }
-        if (ActivityManager.checkComponentPermission(Manifest.permission.INTERACT_ACROSS_USERS,
-                Binder.getCallingUid(), -1, true) != PackageManager.PERMISSION_GRANTED) {
+        if (!hasPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS,
+                Binder.getCallingUid())) {
             throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS permission "
                     + "to: check " + name);
         }
@@ -1801,17 +1824,26 @@
      */
     private static final void checkManageUserAndAcrossUsersFullPermission(String message) {
         final int uid = Binder.getCallingUid();
-        if (uid != Process.SYSTEM_UID && uid != 0
-                && ActivityManager.checkComponentPermission(
-                Manifest.permission.MANAGE_USERS,
-                uid, -1, true) != PackageManager.PERMISSION_GRANTED
-                && ActivityManager.checkComponentPermission(
-                Manifest.permission.INTERACT_ACROSS_USERS_FULL,
-                uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "You need MANAGE_USERS and INTERACT_ACROSS_USERS_FULL permission to: "
-                            + message);
+
+        if (uid == Process.SYSTEM_UID || uid == 0) {
+            // System UID or root's UID are granted privilege.
+            return;
         }
+
+        if (hasPermissionGranted(Manifest.permission.MANAGE_USERS, uid)
+                && hasPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)) {
+            // Apps with both permissions are granted privilege.
+            return;
+        }
+
+        throw new SecurityException(
+                "You need MANAGE_USERS and INTERACT_ACROSS_USERS_FULL permission to: " + message);
+    }
+
+    private static boolean hasPermissionGranted(String permission, int uid) {
+        return ActivityManager.checkComponentPermission(
+                permission, uid, /* owningUid = */-1, /* exported = */ true) ==
+                PackageManager.PERMISSION_GRANTED;
     }
 
     /**
@@ -1872,9 +1904,7 @@
         final int callingUid = Binder.getCallingUid();
         return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
                 || callingUid == Process.ROOT_UID
-                || ActivityManager.checkComponentPermission(
-                        android.Manifest.permission.MANAGE_USERS,
-                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
+                || hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid);
     }
 
     /**
@@ -1886,12 +1916,8 @@
         final int callingUid = Binder.getCallingUid();
         return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
                 || callingUid == Process.ROOT_UID
-                || ActivityManager.checkComponentPermission(
-                        android.Manifest.permission.MANAGE_USERS,
-                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED
-                || ActivityManager.checkComponentPermission(
-                        android.Manifest.permission.CREATE_USERS,
-                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
+                || hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid)
+                || hasPermissionGranted(android.Manifest.permission.CREATE_USERS, callingUid);
     }
 
     /**
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index d911761..a735297b 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -234,7 +234,6 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
 import android.view.DisplayCutout;
-import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.IApplicationToken;
@@ -2292,6 +2291,11 @@
                     public void onTrustedChanged() {
                         mWindowManagerFuncs.notifyKeyguardTrustedChanged();
                     }
+
+                    @Override
+                    public void onShowingChanged() {
+                        mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
+                    }
                 });
         mScreenshotHelper = new ScreenshotHelper(mContext);
     }
@@ -6651,6 +6655,8 @@
     }
 
     void launchVoiceAssistWithWakeLock() {
+        sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
+
         final Intent voiceIntent;
         if (!keyguardOn()) {
             voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 33eafb9..02dd6e6 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -660,6 +660,11 @@
          * abort animations that have no timeout, in case they got stuck.
          */
         void triggerAnimationFailsafe();
+
+        /**
+         * The keyguard showing state has changed
+         */
+        void onKeyguardShowingAndNotOccludedChanged();
     }
 
     /** Window has been added to the screen. */
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index e56caf8..1cba1c7 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -94,6 +94,7 @@
     public void onShowingStateChanged(boolean showing) {
         mIsShowing = showing;
 
+        mCallback.onShowingChanged();
         try {
             mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId);
         } catch (RemoteException e) {
@@ -132,6 +133,7 @@
 
     public interface StateCallback {
         void onTrustedChanged();
+        void onShowingChanged();
     }
 
     public void dump(String prefix, PrintWriter pw) {
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 2621c50..c3b9841 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -55,6 +55,7 @@
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.Xml.Encoding;
 
 import com.android.internal.annotations.GuardedBy;
@@ -77,6 +78,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
+import java.util.function.Supplier;
 
 public class SliceManagerService extends ISliceManager.Stub {
 
@@ -90,6 +92,10 @@
 
     @GuardedBy("mLock")
     private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>();
+    @GuardedBy("mLock")
+    private final SparseArray<PackageMatchingCache> mAssistantLookup = new SparseArray<>();
+    @GuardedBy("mLock")
+    private final SparseArray<PackageMatchingCache> mHomeLookup = new SparseArray<>();
     private final Handler mHandler;
 
     private final SlicePermissionManager mPermissions;
@@ -453,17 +459,37 @@
     }
 
     private boolean isAssistant(String pkg, int userId) {
-        final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId);
-        if (cn == null) {
-            return false;
-        }
-        return cn.getPackageName().equals(pkg);
+        return getAssistantMatcher(userId).matches(pkg);
     }
 
     private boolean isDefaultHomeApp(String pkg, int userId) {
-        String defaultHome = getDefaultHome(userId);
+        return getHomeMatcher(userId).matches(pkg);
+    }
 
-        return pkg != null && Objects.equals(pkg, defaultHome);
+    private PackageMatchingCache getAssistantMatcher(int userId) {
+        PackageMatchingCache matcher = mAssistantLookup.get(userId);
+        if (matcher == null) {
+            matcher = new PackageMatchingCache(() -> getAssistant(userId));
+            mAssistantLookup.put(userId, matcher);
+        }
+        return matcher;
+    }
+
+    private PackageMatchingCache getHomeMatcher(int userId) {
+        PackageMatchingCache matcher = mHomeLookup.get(userId);
+        if (matcher == null) {
+            matcher = new PackageMatchingCache(() -> getDefaultHome(userId));
+            mHomeLookup.put(userId, matcher);
+        }
+        return matcher;
+    }
+
+    private String getAssistant(int userId) {
+        final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId);
+        if (cn == null) {
+            return null;
+        }
+        return cn.getPackageName();
     }
 
     // Based on getDefaultHome in ShortcutService.
@@ -559,6 +585,30 @@
         return mPermissions.getAllPackagesGranted(pkg);
     }
 
+    /**
+     * Holder that caches a package that has access to a slice.
+     */
+    static class PackageMatchingCache {
+
+        private final Supplier<String> mPkgSource;
+        private String mCurrentPkg;
+
+        public PackageMatchingCache(Supplier<String> pkgSource) {
+            mPkgSource = pkgSource;
+        }
+
+        public boolean matches(String pkgCandidate) {
+            if (pkgCandidate == null) return false;
+
+            if (Objects.equals(pkgCandidate, mCurrentPkg)) {
+                return true;
+            }
+            // Failed on cached value, try updating.
+            mCurrentPkg = mPkgSource.get();
+            return Objects.equals(pkgCandidate, mCurrentPkg);
+        }
+    }
+
     public static class Lifecycle extends SystemService {
         private SliceManagerService mService;
 
diff --git a/services/core/java/com/android/server/updates/ApnDbInstallReceiver.java b/services/core/java/com/android/server/updates/ApnDbInstallReceiver.java
index 3b6f9d6..8d53143 100644
--- a/services/core/java/com/android/server/updates/ApnDbInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/ApnDbInstallReceiver.java
@@ -29,7 +29,7 @@
             "update_db");
 
     public ApnDbInstallReceiver() {
-        super("/data/misc/", "apns-conf.xml", "metadata/", "version");
+        super("/data/misc/apns/", "apns-conf.xml", "metadata/", "version");
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index a7c203d..2886126 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -51,6 +51,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapRegionDecoder;
@@ -75,6 +76,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.service.wallpaper.IWallpaperConnection;
 import android.service.wallpaper.IWallpaperEngine;
 import android.service.wallpaper.IWallpaperService;
@@ -336,6 +338,102 @@
         }
     }
 
+    /**
+     * Observes changes of theme settings. It will check whether to call
+     * notifyWallpaperColorsChanged by the current theme and updated theme.
+     * The light theme and dark theme are controlled by the hint values in Wallpaper colors,
+     * threrfore, if light theme mode is chosen, HINT_SUPPORTS_DARK_THEME in hint will be
+     * removed and then notify listeners.
+     */
+    private class ThemeSettingsObserver extends ContentObserver {
+
+        public ThemeSettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        public void startObserving(Context context) {
+            context.getContentResolver().registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.THEME_MODE),
+                    false,
+                    this);
+        }
+
+        public void stopObserving(Context context) {
+            context.getContentResolver().unregisterContentObserver(this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            onThemeSettingsChanged();
+        }
+    }
+
+    /**
+     * Check whether to call notifyWallpaperColorsChanged. Assumed that the theme mode
+     * was wallpaper theme mode and dark wallpaper was set, therefoe, the theme was dark.
+     * Then theme mode changing to dark theme mode, however, theme should not update since
+     * theme was dark already.
+     */
+    private boolean needUpdateLocked(WallpaperColors colors, int themeMode) {
+        if (colors == null) {
+            return false;
+        }
+
+        if (themeMode == mThemeMode) {
+            return false;
+        }
+
+        boolean result = true;
+        boolean supportDarkTheme =
+                (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
+        switch (themeMode) {
+            case Settings.Secure.THEME_MODE_WALLPAPER:
+                if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) {
+                    result = supportDarkTheme;
+                } else {
+                    result = !supportDarkTheme;
+                }
+                break;
+            case Settings.Secure.THEME_MODE_LIGHT:
+                if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) {
+                    result = supportDarkTheme;
+                }
+                break;
+            case Settings.Secure.THEME_MODE_DARK:
+                if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER) {
+                    result = !supportDarkTheme;
+                }
+                break;
+            default:
+                Slog.w(TAG, "unkonwn theme mode " + themeMode);
+                return false;
+        }
+        mThemeMode = themeMode;
+        return result;
+    }
+
+    void onThemeSettingsChanged() {
+        WallpaperData wallpaper;
+        synchronized (mLock) {
+            wallpaper = mWallpaperMap.get(mCurrentUserId);
+            int updatedThemeMode = Settings.Secure.getInt(
+                    mContext.getContentResolver(), Settings.Secure.THEME_MODE,
+                    Settings.Secure.THEME_MODE_WALLPAPER);
+
+            if (DEBUG) {
+                Slog.v(TAG, "onThemeSettingsChanged, mode = " + updatedThemeMode);
+            }
+
+            if (!needUpdateLocked(wallpaper.primaryColors, updatedThemeMode)) {
+                return;
+            }
+        }
+
+        if (wallpaper != null) {
+            notifyWallpaperColorsChanged(wallpaper, FLAG_SYSTEM);
+        }
+    }
+
     void notifyLockWallpaperChanged() {
         final IWallpaperManagerCallback cb = mKeyguardListener;
         if (cb != null) {
@@ -413,6 +511,7 @@
                 }
                 userAllColorListeners.finishBroadcast();
             }
+            wallpaperColors = getThemeColorsLocked(wallpaperColors);
         }
 
         final int count = colorListeners.size();
@@ -481,6 +580,40 @@
     }
 
     /**
+     * We can easily change theme by modified colors hint. This function will check
+     * current theme mode and return the WallpaperColors fit current theme mode.
+     * If color need modified, it will return a copied WallpaperColors which
+     * its ColorsHint is modified to fit current theme mode.
+     *
+     * @param colors a wallpaper primary colors representation
+     */
+    private WallpaperColors getThemeColorsLocked(WallpaperColors colors) {
+        if (colors == null) {
+            Slog.w(TAG, "Cannot get theme colors because WallpaperColors is null.");
+            return null;
+        }
+
+        int colorHints = colors.getColorHints();
+        boolean supportDarkTheme = (colorHints & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
+        if (mThemeMode == Settings.Secure.THEME_MODE_WALLPAPER ||
+                (mThemeMode == Settings.Secure.THEME_MODE_LIGHT && !supportDarkTheme) ||
+                (mThemeMode == Settings.Secure.THEME_MODE_DARK && supportDarkTheme)) {
+            return colors;
+        }
+
+        WallpaperColors themeColors = new WallpaperColors(colors.getPrimaryColor(),
+                colors.getSecondaryColor(), colors.getTertiaryColor());
+
+        if (mThemeMode == Settings.Secure.THEME_MODE_LIGHT) {
+            colorHints &= ~WallpaperColors.HINT_SUPPORTS_DARK_THEME;
+        } else if (mThemeMode == Settings.Secure.THEME_MODE_DARK) {
+            colorHints |= WallpaperColors.HINT_SUPPORTS_DARK_THEME;
+        }
+        themeColors.setColorHints(colorHints);
+        return themeColors;
+    }
+
+    /**
      * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
      * for display.
      */
@@ -676,6 +809,7 @@
     final SparseArray<Boolean> mUserRestorecon = new SparseArray<Boolean>();
     int mCurrentUserId = UserHandle.USER_NULL;
     boolean mInAmbientMode;
+    int mThemeMode;
 
     static class WallpaperData {
 
@@ -734,6 +868,7 @@
         long lastDiedTime;
         boolean wallpaperUpdating;
         WallpaperObserver wallpaperObserver;
+        ThemeSettingsObserver themeSettingsObserver;
 
         /**
          * List of callbacks registered they should each be notified when the wallpaper is changed.
@@ -1279,6 +1414,10 @@
                 wallpaper.wallpaperObserver.stopWatching();
                 wallpaper.wallpaperObserver = null;
             }
+            if (wallpaper.themeSettingsObserver != null) {
+                wallpaper.themeSettingsObserver.stopObserving(mContext);
+                wallpaper.themeSettingsObserver = null;
+            }
         }
     }
 
@@ -1362,6 +1501,13 @@
                 systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
                 systemWallpaper.wallpaperObserver.startWatching();
             }
+            if (systemWallpaper.themeSettingsObserver == null) {
+                systemWallpaper.themeSettingsObserver = new ThemeSettingsObserver(null);
+                systemWallpaper.themeSettingsObserver.startObserving(mContext);
+            }
+            mThemeMode = Settings.Secure.getInt(
+                    mContext.getContentResolver(), Settings.Secure.THEME_MODE,
+                    Settings.Secure.THEME_MODE_WALLPAPER);
             switchWallpaper(systemWallpaper, reply);
         }
 
@@ -1835,7 +1981,7 @@
         }
 
         synchronized (mLock) {
-            return wallpaperData.primaryColors;
+            return getThemeColorsLocked(wallpaperData.primaryColors);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 50d0d0a..a709c55 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -157,10 +157,18 @@
     }
 
     WindowState computeFocusedWindow() {
+        // While the keyguard is showing, we must focus anything besides the main display.
+        // Otherwise we risk input not going to the keyguard when the user expects it to.
+        final boolean forceDefaultDisplay = mService.isKeyguardShowingAndNotOccluded();
+
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final DisplayContent dc = mChildren.get(i);
             final WindowState win = dc.findFocusedWindow();
             if (win != null) {
+                if (forceDefaultDisplay && !dc.isDefaultDisplay) {
+                    EventLog.writeEvent(0x534e4554, "71786287", win.mOwnerUid, "");
+                    continue;
+                }
                 return win;
             }
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index cb64142..f42f855 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2846,6 +2846,11 @@
         mH.sendEmptyMessage(H.ANIMATION_FAILSAFE);
     }
 
+    @Override
+    public void onKeyguardShowingAndNotOccludedChanged() {
+        mH.sendEmptyMessage(H.RECOMPUTE_FOCUS);
+    }
+
     /**
      * Starts deferring layout passes. Useful when doing multiple changes but to optimize
      * performance, only one layout pass should be done. This can be called multiple times, and
@@ -4626,6 +4631,7 @@
         public static final int SET_HAS_OVERLAY_UI = 58;
         public static final int SET_RUNNING_REMOTE_ANIMATION = 59;
         public static final int ANIMATION_FAILSAFE = 60;
+        public static final int RECOMPUTE_FOCUS = 61;
 
         /**
          * Used to denote that an integer field in a message will not be used.
@@ -5052,6 +5058,13 @@
                     }
                 }
                 break;
+                case RECOMPUTE_FOCUS: {
+                    synchronized (mWindowMap) {
+                        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+                                true /* updateInputWindows */);
+                    }
+                }
+                break;
             }
             if (DEBUG_WINDOW_TRACE) {
                 Slog.v(TAG_WM, "handleMessage: exit");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index dac85b3..c797d8d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2298,8 +2298,8 @@
                     if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
                             "setAnimationLocked: setting mFocusMayChange true");
                     mService.mFocusMayChange = true;
-                    setDisplayLayoutNeeded();
                 }
+                setDisplayLayoutNeeded();
                 // Window is no longer visible -- make sure if we were waiting
                 // for it to be displayed before enabling the display, that
                 // we allow the display to be enabled now.
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 70287db..d247960 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -644,6 +644,11 @@
                 ? null : wallpaperTarget;
         final ArraySet<AppWindowToken> openingApps = mService.mOpeningApps;
         final ArraySet<AppWindowToken> closingApps = mService.mClosingApps;
+        final AppWindowToken topOpeningApp = getTopApp(mService.mOpeningApps,
+                false /* ignoreHidden */);
+        final AppWindowToken topClosingApp = getTopApp(mService.mClosingApps,
+                true /* ignoreHidden */);
+
         boolean openingCanBeWallpaperTarget = canBeWallpaperTarget(openingApps);
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                 "New wallpaper target=" + wallpaperTarget
@@ -677,13 +682,15 @@
                         "New transit: " + AppTransition.appTransitionToString(transit));
             } else if (oldWallpaper != null && !mService.mOpeningApps.isEmpty()
                     && !openingApps.contains(oldWallpaper.mAppToken)
-                    && closingApps.contains(oldWallpaper.mAppToken)) {
+                    && closingApps.contains(oldWallpaper.mAppToken)
+                    && topClosingApp == oldWallpaper.mAppToken) {
                 // We are transitioning from an activity with a wallpaper to one without.
                 transit = TRANSIT_WALLPAPER_CLOSE;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit away from wallpaper: "
                         + AppTransition.appTransitionToString(transit));
             } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()
                     && openingApps.contains(wallpaperTarget.mAppToken)
+                    && topOpeningApp == wallpaperTarget.mAppToken
                     && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE) {
                 // We are transitioning from an activity without
                 // a wallpaper to now showing the wallpaper
@@ -748,6 +755,31 @@
         return false;
     }
 
+    /**
+     * Finds the top app in a list of apps, using its {@link AppWindowToken#getPrefixOrderIndex} to
+     * compare z-order.
+     *
+     * @param apps The list of apps to search.
+     * @param ignoreHidden If set to true, ignores apps that are {@link AppWindowToken#isHidden}.
+     * @return The top {@link AppWindowToken}.
+     */
+    private AppWindowToken getTopApp(ArraySet<AppWindowToken> apps, boolean ignoreHidden) {
+        int topPrefixOrderIndex = Integer.MIN_VALUE;
+        AppWindowToken topApp = null;
+        for (int i = apps.size() - 1; i >= 0; i--) {
+            final AppWindowToken app = apps.valueAt(i);
+            if (ignoreHidden && app.isHidden()) {
+                continue;
+            }
+            final int prefixOrderIndex = app.getPrefixOrderIndex();
+            if (prefixOrderIndex > topPrefixOrderIndex) {
+                topPrefixOrderIndex = prefixOrderIndex;
+                topApp = app;
+            }
+        }
+        return topApp;
+    }
+
     private void processApplicationsAnimatingInPlace(int transit) {
         if (transit == TRANSIT_TASK_IN_PLACE) {
             // Find the focused window
diff --git a/services/net/java/android/net/dns/ResolvUtil.java b/services/net/java/android/net/dns/ResolvUtil.java
index a2a6615..d9d4b96f 100644
--- a/services/net/java/android/net/dns/ResolvUtil.java
+++ b/services/net/java/android/net/dns/ResolvUtil.java
@@ -16,6 +16,8 @@
 
 package android.net.dns;
 
+import static android.system.OsConstants.AI_ADDRCONFIG;
+
 import android.net.Network;
 import android.net.NetworkUtils;
 import android.system.GaiException;
@@ -41,12 +43,17 @@
 
     public static InetAddress[] blockingResolveAllLocally(Network network, String name)
             throws UnknownHostException {
+        // Use AI_ADDRCONFIG by default
+        return blockingResolveAllLocally(network, name, AI_ADDRCONFIG);
+    }
+
+    public static InetAddress[] blockingResolveAllLocally(
+            Network network, String name, int aiFlags) throws UnknownHostException  {
         final StructAddrinfo hints = new StructAddrinfo();
-        // Unnecessary, but expressly no AI_ADDRCONFIG.
-        hints.ai_flags = 0;
-        // Fetch all IP addresses at once to minimize re-resolution.
+        hints.ai_flags = aiFlags;
+        // Other hints identical to the default Inet6AddressImpl implementation
         hints.ai_family = OsConstants.AF_UNSPEC;
-        hints.ai_socktype = OsConstants.SOCK_DGRAM;
+        hints.ai_socktype = OsConstants.SOCK_STREAM;
 
         final Network networkForResolv = getNetworkWithUseLocalNameserversFlag(network);
 
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index b4dc941..17babe9 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -1628,6 +1628,20 @@
         }
     }
 
+    /**
+     * Test that policy set of {null, NetworkPolicy, null} does not crash and restores the valid
+     * NetworkPolicy.
+     */
+    @Test
+    public void testSetNetworkPolicies_withNullPolicies_doesNotThrow() {
+        NetworkPolicy[] policies = new NetworkPolicy[3];
+        policies[1] = buildDefaultFakeMobilePolicy();
+        setNetworkPolicies(policies);
+
+        assertNetworkPolicyEquals(DEFAULT_CYCLE_DAY, mDefaultWarningBytes, mDefaultLimitBytes,
+                true);
+    }
+
     private SubscriptionPlan buildMonthlyDataPlan(ZonedDateTime start, long limitBytes) {
         return SubscriptionPlan.Builder
                 .createRecurringMonthly(start)
diff --git a/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java
rename to services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
index c004074..6bd8011 100644
--- a/services/tests/servicestests/src/com/android/server/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/ColorDisplayServiceTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server;
+package com.android.server.display;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
@@ -32,8 +32,8 @@
 
 import com.android.internal.app.ColorDisplayController;
 import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.server.display.DisplayTransformManager;
-import com.android.server.display.ColorDisplayService;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
 import com.android.server.twilight.TwilightState;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 142b950..94e02bc 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -448,6 +448,39 @@
         assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
     }
 
+    public void testgetHashFactorPrimaryUser() throws RemoteException {
+        final String password = "password";
+        mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+        final byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
+        assertNotNull(hashFactor);
+
+        mService.setLockCredential(null, LockPatternUtils.CREDENTIAL_TYPE_NONE, password,
+                PASSWORD_QUALITY_UNSPECIFIED, PRIMARY_USER_ID);
+        final byte[] newHashFactor = mService.getHashFactor(null, PRIMARY_USER_ID);
+        assertNotNull(newHashFactor);
+        // Hash factor should never change after password change/removal
+        assertArrayEquals(hashFactor, newHashFactor);
+    }
+
+    public void testgetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
+        final String pattern = "1236";
+        mService.setLockCredential(pattern, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, null,
+                PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
+        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
+        assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
+    }
+
+    public void testgetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
+        final String primaryPassword = "primary";
+        final String profilePassword = "profile";
+        mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+        mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+                PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID);
+        assertNotNull(mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID));
+    }
+
     public void testPasswordData_serializeDeserialize() {
         PasswordData data = new PasswordData();
         data.scryptN = 11;
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index dd9a8ab..7bcb571 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -170,6 +170,31 @@
     }
 
     @MediumTest
+    public void testSetUserAdmin() throws Exception {
+        UserInfo userInfo = createUser("SecondaryUser", /*flags=*/ 0);
+
+        // Assert user is not admin and has SMS and calls restrictions.
+        assertFalse(userInfo.isAdmin());
+        assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS,
+                userInfo.getUserHandle()));
+        assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
+                userInfo.getUserHandle()));
+
+        // Assign admin privileges.
+        mUserManager.setUserAdmin(userInfo.id);
+
+        // Refresh.
+        userInfo = mUserManager.getUserInfo(userInfo.id);
+
+        // Verify user became admin and SMS and call restrictions are lifted.
+        assertTrue(userInfo.isAdmin());
+        assertFalse(mUserManager.hasUserRestriction(UserManager.DISALLOW_SMS,
+                userInfo.getUserHandle()));
+        assertFalse(mUserManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS,
+                userInfo.getUserHandle()));
+    }
+
+    @MediumTest
     public void testGetProfileParent() throws Exception {
         final int primaryUserId = mUserManager.getPrimaryUser().id;
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 845095a..ac196f9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -329,6 +329,21 @@
         assertEquals(window1, sWm.mRoot.computeFocusedWindow());
     }
 
+    @Test
+    public void testKeyguard_preventsSecondaryDisplayFocus() throws Exception {
+        final WindowState keyguard = createWindow(null, TYPE_STATUS_BAR,
+                sWm.getDefaultDisplayContentLocked(), "keyguard");
+        assertEquals(keyguard, sWm.mRoot.computeFocusedWindow());
+
+        // Add a window to a second display, and it should be focused
+        final DisplayContent dc = createNewDisplay();
+        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
+        assertEquals(win, sWm.mRoot.computeFocusedWindow());
+
+        mWmRule.getWindowManagerPolicy().keyguardShowingAndNotOccluded = true;
+        assertEquals(keyguard, sWm.mRoot.computeFocusedWindow());
+    }
+
     /**
      * This tests setting the maximum ui width on a display.
      */
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 765b3d5..50f3fbe 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -51,6 +51,7 @@
     private final Supplier<WindowManagerService> mWmSupplier;
 
     int rotationToReport = 0;
+    boolean keyguardShowingAndNotOccluded = false;
 
     private Runnable mRunnableWhenAddingSplashScreen;
 
@@ -338,7 +339,7 @@
 
     @Override
     public boolean isKeyguardLocked() {
-        return false;
+        return keyguardShowingAndNotOccluded;
     }
 
     @Override
@@ -358,7 +359,7 @@
 
     @Override
     public boolean isKeyguardShowingAndNotOccluded() {
-        return false;
+        return keyguardShowingAndNotOccluded;
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
index 32bfda32..d91079e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
@@ -59,6 +59,7 @@
 public class WindowManagerServiceRule implements TestRule {
 
     private WindowManagerService mService;
+    private TestWindowManagerPolicy mPolicy;
 
     @Override
     public Statement apply(Statement base, Description description) {
@@ -108,7 +109,7 @@
                 }
 
                 mService = WindowManagerService.main(context, ims, true, false,
-                        false, new TestWindowManagerPolicy(
+                        false, mPolicy = new TestWindowManagerPolicy(
                                 WindowManagerServiceRule.this::getWindowManagerService));
 
                 mService.onInitReady();
@@ -132,6 +133,7 @@
                 waitUntilWindowManagerHandlersIdle();
                 removeServices();
                 mService = null;
+                mPolicy = null;
             }
         };
     }
@@ -140,6 +142,10 @@
         return mService;
     }
 
+    public TestWindowManagerPolicy getWindowManagerPolicy() {
+        return mPolicy;
+    }
+
     public void waitUntilWindowManagerHandlersIdle() {
         final WindowManagerService wm = getWindowManagerService();
         if (wm != null) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 3dde7f1..41b4718 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -91,10 +91,12 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.MediaStore;
 import android.provider.Settings.Secure;
 import android.service.notification.Adjustment;
+import android.service.notification.INotificationListener;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
 import android.service.notification.NotifyingApp;
@@ -160,6 +162,8 @@
     @Mock
     private NotificationUsageStats mUsageStats;
     @Mock
+    private UsageStatsManagerInternal mAppUsageStats;
+    @Mock
     private AudioManager mAudioManager;
     @Mock
     ActivityManager mActivityManager;
@@ -276,7 +280,7 @@
                     mPackageManager, mPackageManagerClient, mockLightsManager,
                     mListeners, mAssistants, mConditionProviders,
                     mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
-                    mGroupHelper, mAm, mock(UsageStatsManagerInternal.class),
+                    mGroupHelper, mAm, mAppUsageStats,
                     mock(DevicePolicyManagerInternal.class));
         } catch (SecurityException e) {
             if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
@@ -3019,4 +3023,46 @@
 
         assertEquals(true, mService.canUseManagedServices("d"));
     }
+
+    @Test
+    public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
+        final NotificationRecord r = generateNotificationRecord(
+                mTestNotificationChannel, 1, null, true);
+        r.setTextChanged(true);
+        mService.addNotification(r);
+
+        mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
+                {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
+                new NotificationVisibility[]{});
+
+        verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
+    }
+
+    @Test
+    public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
+            throws RemoteException {
+        final NotificationRecord r = generateNotificationRecord(
+                mTestNotificationChannel, 1, null, true);
+        r.setTextChanged(true);
+        mService.addNotification(r);
+
+        mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
+
+        verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
+    }
+
+    @Test
+    public void testMybeRecordInterruptionLocked_doesNotRecordTwice()
+            throws RemoteException {
+        final NotificationRecord r = generateNotificationRecord(
+                mTestNotificationChannel, 1, null, true);
+        r.setInterruptive(true);
+        mService.addNotification(r);
+
+        mService.maybeRecordInterruptionLocked(r);
+        mService.maybeRecordInterruptionLocked(r);
+
+        verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
+                anyString(), anyString(), anyInt());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index e3289ab..c1868e7 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -602,4 +602,45 @@
         record.setIsAppImportanceLocked(false);
         assertEquals(false, record.getIsAppImportanceLocked());
     }
+
+    @Test
+    public void testIsInterruptive_textChanged_notSeen() {
+        StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        assertEquals(false, record.isInterruptive());
+
+        record.setTextChanged(true);
+        assertEquals(false, record.isInterruptive());
+    }
+
+    @Test
+    public void testIsInterruptive_textChanged_seen() {
+        StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        assertEquals(false, record.isInterruptive());
+
+        record.setTextChanged(true);
+        record.setSeen();
+        assertEquals(true, record.isInterruptive());
+    }
+
+    @Test
+    public void testIsInterruptive_textNotChanged_seen() {
+        StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        assertEquals(false, record.isInterruptive());
+
+        record.setTextChanged(false);
+        record.setSeen();
+        assertEquals(false, record.isInterruptive());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 8905950..98c6ec4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -33,8 +33,10 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -115,7 +117,9 @@
     @Mock PackageManager mPm;
     @Mock IContentProvider mTestIContentProvider;
     @Mock Context mContext;
+    @Mock ZenModeHelper mMockZenModeHelper;
 
+    private NotificationManager.Policy mTestNotificationPolicy;
     private Notification mNotiGroupGSortA;
     private Notification mNotiGroupGSortB;
     private Notification mNotiNoGroup;
@@ -172,12 +176,12 @@
         when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
                 .thenReturn(SOUND_URI);
 
-        ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
-        mHelper = new RankingHelper(getContext(), mPm, mHandler, mockZenModeHelper,
+        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
+                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND);
+        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+        mHelper = new RankingHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mUsageStats, new String[] {ImportanceExtractor.class.getName()});
-
-        when(mockZenModeHelper.getNotificationPolicy()).thenReturn(new NotificationManager.Policy(
-                0, 0, 0));
+        resetZenModeHelper();
 
         mNotiGroupGSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setContentTitle("A")
@@ -299,6 +303,11 @@
         return null;
     }
 
+    private void resetZenModeHelper() {
+        reset(mMockZenModeHelper);
+        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+    }
+
     @Test
     public void testFindAfterRankingWithASplitGroup() throws Exception {
         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3);
@@ -1136,44 +1145,86 @@
     public void testCreateAndDeleteCanChannelsBypassDnd() throws Exception {
         // create notification channel that can't bypass dnd
         // expected result: areChannelsBypassingDnd = false
+        // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false
         NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW);
         mHelper.createNotificationChannel(PKG, UID, channel, true, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
+        resetZenModeHelper();
 
-        //  create notification channel that can bypass dnd
+        // create notification channel that can bypass dnd
         // expected result: areChannelsBypassingDnd = true
         NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
         channel2.setBypassDnd(true);
         mHelper.createNotificationChannel(PKG, UID, channel2, true, true);
         assertTrue(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
 
         // delete channels
         mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
         assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
+        resetZenModeHelper();
+
         mHelper.deleteNotificationChannel(PKG, UID, channel2.getId());
         assertFalse(mHelper.areChannelsBypassingDnd());
-
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
     }
 
     @Test
     public void testUpdateCanChannelsBypassDnd() throws Exception {
         // create notification channel that can't bypass dnd
         // expected result: areChannelsBypassingDnd = false
+        // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false
         NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW);
         mHelper.createNotificationChannel(PKG, UID, channel, true, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
+        resetZenModeHelper();
 
         // update channel so it CAN bypass dnd:
         // expected result: areChannelsBypassingDnd = true
         channel.setBypassDnd(true);
         mHelper.updateNotificationChannel(PKG, UID, channel, true);
         assertTrue(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
 
         // update channel so it can't bypass dnd:
         // expected result: areChannelsBypassingDnd = false
         channel.setBypassDnd(false);
         mHelper.updateNotificationChannel(PKG, UID, channel, true);
         assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
+    }
+
+    @Test
+    public void testSetupNewZenModeHelper_canBypass() {
+        // start notification policy off with mAreChannelsBypassingDnd = true, but
+        // RankingHelper should change to false
+        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
+                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND);
+        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+        mHelper = new RankingHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
+                mUsageStats, new String[] {ImportanceExtractor.class.getName()});
+        assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any());
+        resetZenModeHelper();
+    }
+
+    @Test
+    public void testSetupNewZenModeHelper_cannotBypass() {
+        // start notification policy off with mAreChannelsBypassingDnd = false
+        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0);
+        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
+        mHelper = new RankingHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
+                mUsageStats, new String[] {ImportanceExtractor.class.getName()});
+        assertFalse(mHelper.areChannelsBypassingDnd());
+        verify(mMockZenModeHelper, never()).setNotificationPolicy(any());
+        resetZenModeHelper();
     }
 
     @Test
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java
new file mode 100644
index 0000000..c6aea88
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT 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.slice;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import com.android.server.UiServiceTestCase;
+import com.android.server.slice.SliceManagerService.PackageMatchingCache;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.function.Supplier;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class PackageMatchingCacheTest extends UiServiceTestCase {
+
+    private final Supplier<String> supplier = mock(Supplier.class);
+    private final PackageMatchingCache cache = new PackageMatchingCache(supplier);
+
+    @Test
+    public void testNulls() {
+        // Doesn't get for a null input
+        cache.matches(null);
+        verify(supplier, never()).get();
+
+        // Gets once valid input in sent.
+        cache.matches("");
+        verify(supplier).get();
+    }
+
+    @Test
+    public void testCaching() {
+        when(supplier.get()).thenReturn("ret.pkg");
+
+        assertTrue(cache.matches("ret.pkg"));
+        assertTrue(cache.matches("ret.pkg"));
+        assertTrue(cache.matches("ret.pkg"));
+
+        verify(supplier, times(1)).get();
+    }
+
+    @Test
+    public void testGetOnFailure() {
+        when(supplier.get()).thenReturn("ret.pkg");
+        assertTrue(cache.matches("ret.pkg"));
+
+        when(supplier.get()).thenReturn("other.pkg");
+        assertTrue(cache.matches("other.pkg"));
+        verify(supplier, times(2)).get();
+    }
+}
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 271f813..4e99732 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -340,15 +340,27 @@
 
     public void setAppStandbyBucket(String packageName, int userId, long elapsedRealtime,
             int bucket, int reason) {
+        setAppStandbyBucket(packageName, userId, elapsedRealtime, bucket, reason, false);
+    }
+
+    public void setAppStandbyBucket(String packageName, int userId, long elapsedRealtime,
+            int bucket, int reason, boolean resetTimeout) {
         ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
         AppUsageHistory appUsageHistory =
                 getPackageHistory(userHistory, packageName, elapsedRealtime, true);
         appUsageHistory.currentBucket = bucket;
         appUsageHistory.bucketingReason = reason;
+
+        final long elapsed = getElapsedTime(elapsedRealtime);
+
         if ((reason & REASON_MAIN_MASK) == REASON_MAIN_PREDICTED) {
-            appUsageHistory.lastPredictedTime = getElapsedTime(elapsedRealtime);
+            appUsageHistory.lastPredictedTime = elapsed;
             appUsageHistory.lastPredictedBucket = bucket;
         }
+        if (resetTimeout) {
+            appUsageHistory.bucketActiveTimeoutTime = elapsed;
+            appUsageHistory.bucketWorkingSetTimeoutTime = elapsed;
+        }
         if (DEBUG) {
             Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
                     + ", reason=0x0" + Integer.toHexString(appUsageHistory.bucketingReason));
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 08b0496..3378897 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -113,6 +113,9 @@
 
 /**
  * Manages the standby state of an app, listening to various events.
+ *
+ * Unit test:
+   atest ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
  */
 public class AppStandbyController {
 
@@ -1106,6 +1109,11 @@
 
     void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
             int reason, long elapsedRealtime) {
+        setAppStandbyBucket(packageName, userId, newBucket, reason, elapsedRealtime, false);
+    }
+
+    void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
+            int reason, long elapsedRealtime, boolean resetTimeout) {
         synchronized (mAppIdleLock) {
             AppIdleHistory.AppUsageHistory app = mAppIdleHistory.getAppUsageHistory(packageName,
                     userId, elapsedRealtime);
@@ -1155,7 +1163,7 @@
             }
 
             mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
-                    reason);
+                    reason, resetTimeout);
         }
         maybeInformListeners(packageName, userId, elapsedRealtime, newBucket, reason, false);
     }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 71f9bb3..7d42eb3 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -900,6 +900,7 @@
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
+            final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID;
             final boolean systemCaller = UserHandle.isCore(callingUid);
             final int reason = systemCaller
                     ? UsageStatsManager.REASON_MAIN_FORCED
@@ -918,7 +919,7 @@
                                     + ")");
                 }
                 mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
-                        SystemClock.elapsedRealtime());
+                        SystemClock.elapsedRealtime(), shellCaller);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -985,7 +986,7 @@
                         throw new IllegalArgumentException("Cannot set your own standby bucket");
                     }
                     mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
-                            elapsedRealtime);
+                            elapsedRealtime, shellCaller);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index da897ae..a112fa6 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -56,6 +56,7 @@
 @SmallTest
 public class NetworkCapabilitiesTest {
     private static final String TEST_SSID = "TEST_SSID";
+    private static final String DIFFERENT_TEST_SSID = "DIFFERENT_TEST_SSID";
 
     @Test
     public void testMaybeMarkCapabilitiesRestricted() {
@@ -374,6 +375,12 @@
         assertFalse(nc1.satisfiedByNetworkCapabilities(nc2));
     }
 
+    private ArraySet<UidRange> uidRange(int from, int to) {
+        final ArraySet<UidRange> range = new ArraySet<>(1);
+        range.add(new UidRange(from, to));
+        return range;
+    }
+
     @Test
     public void testCombineCapabilities() {
         NetworkCapabilities nc1 = new NetworkCapabilities();
@@ -400,14 +407,30 @@
         nc2.combineCapabilities(nc1);
         assertTrue(TEST_SSID.equals(nc2.getSSID()));
 
-        // Because they now have the same SSID, the folllowing call should not throw
+        // Because they now have the same SSID, the following call should not throw
         nc2.combineCapabilities(nc1);
 
-        nc1.setSSID("different " + TEST_SSID);
+        nc1.setSSID(DIFFERENT_TEST_SSID);
         try {
             nc2.combineCapabilities(nc1);
             fail("Expected IllegalStateException: can't combine different SSIDs");
         } catch (IllegalStateException expected) {}
+        nc1.setSSID(TEST_SSID);
+
+        nc1.setUids(uidRange(10, 13));
+        assertNotEquals(nc1, nc2);
+        nc2.combineCapabilities(nc1);  // Everything + 10~13 is still everything.
+        assertNotEquals(nc1, nc2);
+        nc1.combineCapabilities(nc2);  // 10~13 + everything is everything.
+        assertEquals(nc1, nc2);
+        nc1.setUids(uidRange(10, 13));
+        nc2.setUids(uidRange(20, 23));
+        assertNotEquals(nc1, nc2);
+        nc1.combineCapabilities(nc2);
+        assertTrue(nc1.appliesToUid(12));
+        assertFalse(nc2.appliesToUid(12));
+        assertTrue(nc1.appliesToUid(22));
+        assertTrue(nc2.appliesToUid(22));
     }
 
     @Test
@@ -446,4 +469,38 @@
         p.setDataPosition(0);
         assertEquals(NetworkCapabilities.CREATOR.createFromParcel(p), netCap);
     }
+
+    @Test
+    public void testSet() {
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+
+        nc1.addUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+        nc1.addCapability(NET_CAPABILITY_NOT_ROAMING);
+        assertNotEquals(nc1, nc2);
+        nc2.set(nc1);
+        assertEquals(nc1, nc2);
+        assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
+
+        // This will effectively move NOT_ROAMING capability from required to unwanted for nc1.
+        nc1.addUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
+        nc1.setSSID(TEST_SSID);
+        nc2.set(nc1);
+        assertEquals(nc1, nc2);
+        // Contrary to combineCapabilities, set() will have removed the NOT_ROAMING capability
+        // from nc2.
+        assertFalse(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(TEST_SSID.equals(nc2.getSSID()));
+
+        nc1.setSSID(DIFFERENT_TEST_SSID);
+        nc2.set(nc1);
+        assertEquals(nc1, nc2);
+        assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSSID()));
+
+        nc1.setUids(uidRange(10, 13));
+        nc2.set(nc1);  // Overwrites, as opposed to combineCapabilities
+        assertEquals(nc1, nc2);
+    }
 }
diff --git a/tests/net/java/android/net/captiveportal/CaptivePortalProbeSpecTest.java b/tests/net/java/android/net/captiveportal/CaptivePortalProbeSpecTest.java
new file mode 100644
index 0000000..40a8b3e
--- /dev/null
+++ b/tests/net/java/android/net/captiveportal/CaptivePortalProbeSpecTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.captiveportal;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.ParseException;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class CaptivePortalProbeSpecTest {
+
+    @Test
+    public void testGetResult_Regex() throws MalformedURLException, ParseException {
+        // 2xx status or 404, with an empty (match everything) location regex
+        CaptivePortalProbeSpec statusRegexSpec = CaptivePortalProbeSpec.parseSpec(
+                "http://www.google.com@@/@@2[0-9]{2}|404@@/@@");
+
+        // 404, or 301/302 redirect to some HTTPS page under google.com
+        CaptivePortalProbeSpec redirectSpec = CaptivePortalProbeSpec.parseSpec(
+                "http://google.com@@/@@404|30[12]@@/@@https://([0-9a-z]+\\.)*google\\.com.*");
+
+        assertSuccess(statusRegexSpec.getResult(200, null));
+        assertSuccess(statusRegexSpec.getResult(299, "qwer"));
+        assertSuccess(statusRegexSpec.getResult(404, null));
+        assertSuccess(statusRegexSpec.getResult(404, ""));
+
+        assertPortal(statusRegexSpec.getResult(300, null));
+        assertPortal(statusRegexSpec.getResult(399, "qwer"));
+        assertPortal(statusRegexSpec.getResult(500, null));
+
+        assertSuccess(redirectSpec.getResult(404, null));
+        assertSuccess(redirectSpec.getResult(404, ""));
+        assertSuccess(redirectSpec.getResult(301, "https://www.google.com"));
+        assertSuccess(redirectSpec.getResult(301, "https://www.google.com/test?q=3"));
+        assertSuccess(redirectSpec.getResult(302, "https://google.com/test?q=3"));
+
+        assertPortal(redirectSpec.getResult(299, "https://google.com/test?q=3"));
+        assertPortal(redirectSpec.getResult(299, ""));
+        assertPortal(redirectSpec.getResult(499, null));
+        assertPortal(redirectSpec.getResult(301, "http://login.portal.example.com/loginpage"));
+        assertPortal(redirectSpec.getResult(302, "http://www.google.com/test?q=3"));
+    }
+
+    @Test(expected = ParseException.class)
+    public void testParseSpec_Empty() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec("");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testParseSpec_Null() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec(null);
+    }
+
+    @Test(expected = ParseException.class)
+    public void testParseSpec_MissingParts() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec("http://google.com/@@/@@123");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testParseSpec_TooManyParts() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec("http://google.com/@@/@@123@@/@@456@@/@@extra");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testParseSpec_InvalidStatusRegex() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec("http://google.com/@@/@@unmatched(parenthesis@@/@@456");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testParseSpec_InvalidLocationRegex() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec("http://google.com/@@/@@123@@/@@unmatched[[]bracket");
+    }
+
+    @Test(expected = MalformedURLException.class)
+    public void testParseSpec_EmptyURL() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec("@@/@@123@@/@@123");
+    }
+
+    @Test(expected = ParseException.class)
+    public void testParseSpec_NoParts() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec("invalid");
+    }
+
+    @Test(expected = MalformedURLException.class)
+    public void testParseSpec_RegexInvalidUrl() throws MalformedURLException, ParseException {
+        CaptivePortalProbeSpec.parseSpec("notaurl@@/@@123@@/@@123");
+    }
+
+    @Test
+    public void testParseSpecOrNull_UsesSpec() {
+        final String specUrl = "http://google.com/probe";
+        final String redirectUrl = "https://google.com/probe";
+        CaptivePortalProbeSpec spec = CaptivePortalProbeSpec.parseSpecOrNull(
+                specUrl + "@@/@@302@@/@@" + redirectUrl);
+        assertEquals(specUrl, spec.getUrl().toString());
+
+        assertPortal(spec.getResult(302, "http://portal.example.com"));
+        assertSuccess(spec.getResult(302, redirectUrl));
+    }
+
+    @Test
+    public void testParseSpecOrNull_UsesFallback() throws MalformedURLException {
+        CaptivePortalProbeSpec spec = CaptivePortalProbeSpec.parseSpecOrNull(null);
+        assertNull(spec);
+
+        spec = CaptivePortalProbeSpec.parseSpecOrNull("");
+        assertNull(spec);
+
+        spec = CaptivePortalProbeSpec.parseSpecOrNull("@@/@@ @@/@@ @@/@@");
+        assertNull(spec);
+
+        spec = CaptivePortalProbeSpec.parseSpecOrNull("invalid@@/@@123@@/@@456");
+        assertNull(spec);
+    }
+
+    @Test
+    public void testParseSpecOrUseStatusCodeFallback_EmptySpec() throws MalformedURLException {
+        CaptivePortalProbeSpec spec = CaptivePortalProbeSpec.parseSpecOrNull("");
+        assertNull(spec);
+    }
+
+    private void assertIsStatusSpec(CaptivePortalProbeSpec spec) {
+        assertSuccess(spec.getResult(204, null));
+        assertSuccess(spec.getResult(204, "1234"));
+
+        assertPortal(spec.getResult(200, null));
+        assertPortal(spec.getResult(301, null));
+        assertPortal(spec.getResult(302, "1234"));
+        assertPortal(spec.getResult(399, ""));
+
+        assertFailed(spec.getResult(404, null));
+        assertFailed(spec.getResult(500, "1234"));
+    }
+
+    private void assertPortal(CaptivePortalProbeResult result) {
+        assertTrue(result.isPortal());
+    }
+
+    private void assertSuccess(CaptivePortalProbeResult result) {
+        assertTrue(result.isSuccessful());
+    }
+
+    private void assertFailed(CaptivePortalProbeResult result) {
+        assertTrue(result.isFailed());
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 5b73bba..2208580 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -112,6 +112,8 @@
 import android.net.RouteInfo;
 import android.net.StringNetworkSpecifier;
 import android.net.UidRange;
+import android.net.VpnService;
+import android.net.captiveportal.CaptivePortalProbeResult;
 import android.net.metrics.IpConnectivityLog;
 import android.net.util.MultinetworkPolicyTracker;
 import android.os.ConditionVariable;
@@ -133,6 +135,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.net.VpnConfig;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.WakeupMessage;
 import com.android.internal.util.test.BroadcastInterceptingContext;
@@ -196,13 +199,13 @@
     private MockNetworkAgent mWiFiNetworkAgent;
     private MockNetworkAgent mCellNetworkAgent;
     private MockNetworkAgent mEthernetNetworkAgent;
+    private MockVpn mMockVpn;
     private Context mContext;
 
     @Mock IpConnectivityMetrics.Logger mMetricsService;
     @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
     @Mock INetworkManagementService mNetworkManagementService;
     @Mock INetworkStatsService mStatsService;
-    @Mock Vpn mMockVpn;
 
     private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class);
 
@@ -478,6 +481,14 @@
             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
         }
 
+        public void setNetworkCapabilities(NetworkCapabilities nc,
+                boolean sendToConnectivityService) {
+            mNetworkCapabilities.set(nc);
+            if (sendToConnectivityService) {
+                mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
+            }
+        }
+
         public void connectWithoutInternet() {
             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -593,6 +604,10 @@
             return mRedirectUrl;
         }
 
+        public NetworkAgent getNetworkAgent() {
+            return mNetworkAgent;
+        }
+
         public NetworkCapabilities getNetworkCapabilities() {
             return mNetworkCapabilities;
         }
@@ -725,6 +740,87 @@
         }
     }
 
+    private static Looper startHandlerThreadAndReturnLooper() {
+        final HandlerThread handlerThread = new HandlerThread("MockVpnThread");
+        handlerThread.start();
+        return handlerThread.getLooper();
+    }
+
+    private class MockVpn extends Vpn {
+        // TODO : the interactions between this mock and the mock network agent are too
+        // hard to get right at this moment, because it's unclear in which case which
+        // target needs to get a method call or both, and in what order. It's because
+        // MockNetworkAgent wants to manage its own NetworkCapabilities, but the Vpn
+        // parent class of MockVpn agent wants that responsibility.
+        // That being said inside the test it should be possible to make the interactions
+        // harder to get wrong with precise speccing, judicious comments, helper methods
+        // and a few sprinkled assertions.
+
+        private boolean mConnected = false;
+        // Careful ! This is different from mNetworkAgent, because MockNetworkAgent does
+        // not inherit from NetworkAgent.
+        private MockNetworkAgent mMockNetworkAgent;
+
+        public MockVpn(int userId) {
+            super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
+                    userId);
+        }
+
+        public void setNetworkAgent(MockNetworkAgent agent) {
+            waitForIdle(agent, TIMEOUT_MS);
+            mMockNetworkAgent = agent;
+            mNetworkAgent = agent.getNetworkAgent();
+            mNetworkCapabilities.set(agent.getNetworkCapabilities());
+        }
+
+        public void setUids(Set<UidRange> uids) {
+            mNetworkCapabilities.setUids(uids);
+            updateCapabilities();
+        }
+
+        @Override
+        public int getNetId() {
+            return mMockNetworkAgent.getNetwork().netId;
+        }
+
+        @Override
+        public boolean appliesToUid(int uid) {
+            return mConnected;  // Trickery to simplify testing.
+        }
+
+        @Override
+        protected boolean isCallerEstablishedOwnerLocked() {
+            return mConnected;  // Similar trickery
+        }
+
+        public void connect() {
+            mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
+            mConnected = true;
+            mConfig = new VpnConfig();
+        }
+
+        @Override
+        public void updateCapabilities() {
+            if (!mConnected) return;
+            super.updateCapabilities();
+            // Because super.updateCapabilities will update the capabilities of the agent but not
+            // the mock agent, the mock agent needs to know about them.
+            copyCapabilitiesToNetworkAgent();
+        }
+
+        private void copyCapabilitiesToNetworkAgent() {
+            if (null != mMockNetworkAgent) {
+                mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities,
+                        false /* sendToConnectivityService */);
+            }
+        }
+
+        public void disconnect() {
+            mConnected = false;
+            mConfig = null;
+        }
+    }
+
     private class FakeWakeupMessage extends WakeupMessage {
         private static final int UNREASONABLY_LONG_WAIT = 1000;
 
@@ -893,10 +989,12 @@
 
         public void mockVpn(int uid) {
             synchronized (mVpns) {
+                int userId = UserHandle.getUserId(uid);
+                mMockVpn = new MockVpn(userId);
                 // This has no effect unless the VPN is actually connected, because things like
                 // getActiveNetworkForUidInternal call getNetworkAgentInfoForNetId on the VPN
                 // netId, and check if that network is actually connected.
-                mVpns.put(UserHandle.getUserId(Process.myUid()), mMockVpn);
+                mVpns.put(userId, mMockVpn);
             }
         }
 
@@ -926,7 +1024,6 @@
 
         MockitoAnnotations.initMocks(this);
         when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
-        when(mMockVpn.appliesToUid(Process.myUid())).thenReturn(true);
 
         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
         // http://b/25897652 .
@@ -1548,7 +1645,8 @@
 
         void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
-            assertTrue(fn.test((NetworkCapabilities) cbi.arg));
+            assertTrue("Received capabilities don't match expectations : " + cbi.arg,
+                    fn.test((NetworkCapabilities) cbi.arg));
         }
 
         void assertNoCallback() {
@@ -2576,9 +2674,10 @@
         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
         final ArraySet<UidRange> ranges = new ArraySet<>();
         ranges.add(new UidRange(uid, uid));
-        when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
-        vpnNetworkAgent.setUids(ranges);
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.setUids(ranges);
         vpnNetworkAgent.connect(true);
+        mMockVpn.connect();
         defaultNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
         assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -4107,9 +4206,10 @@
         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
         final ArraySet<UidRange> ranges = new ArraySet<>();
         ranges.add(new UidRange(uid, uid));
-        when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
-        vpnNetworkAgent.setUids(ranges);
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.setUids(ranges);
         vpnNetworkAgent.connect(false);
+        mMockVpn.connect();
 
         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
         genericNotVpnNetworkCallback.assertNoCallback();
@@ -4141,7 +4241,7 @@
         defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
 
         ranges.add(new UidRange(uid, uid));
-        vpnNetworkAgent.setUids(ranges);
+        mMockVpn.setUids(ranges);
 
         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
         genericNotVpnNetworkCallback.assertNoCallback();
@@ -4191,9 +4291,10 @@
         MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
         final ArraySet<UidRange> ranges = new ArraySet<>();
         ranges.add(new UidRange(uid, uid));
-        when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
-        vpnNetworkAgent.setUids(ranges);
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.setUids(ranges);
         vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+        mMockVpn.connect();
 
         defaultCallback.assertNoCallback();
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -4202,9 +4303,10 @@
         defaultCallback.assertNoCallback();
 
         vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
-        when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
-        vpnNetworkAgent.setUids(ranges);
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.setUids(ranges);
         vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
+        mMockVpn.connect();
         defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -4213,13 +4315,111 @@
         defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
 
         vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
-        when(mMockVpn.getNetId()).thenReturn(vpnNetworkAgent.getNetwork().netId);
         ranges.clear();
-        vpnNetworkAgent.setUids(ranges);
-
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.setUids(ranges);
         vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
+        mMockVpn.connect();
         defaultCallback.assertNoCallback();
 
         mCm.unregisterNetworkCallback(defaultCallback);
     }
+
+    @Test
+    public void testVpnSetUnderlyingNetworks() {
+        final int uid = Process.myUid();
+
+        final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
+        final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN)
+                .addTransportType(TRANSPORT_VPN)
+                .build();
+        NetworkCapabilities nc;
+        mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
+        vpnNetworkCallback.assertNoCallback();
+
+        final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN);
+        final ArraySet<UidRange> ranges = new ArraySet<>();
+        ranges.add(new UidRange(uid, uid));
+        mMockVpn.setNetworkAgent(vpnNetworkAgent);
+        mMockVpn.connect();
+        mMockVpn.setUids(ranges);
+        vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+
+        vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
+        nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
+        assertTrue(nc.hasTransport(TRANSPORT_VPN));
+        assertFalse(nc.hasTransport(TRANSPORT_CELLULAR));
+        assertFalse(nc.hasTransport(TRANSPORT_WIFI));
+        // For safety reasons a VPN without underlying networks is considered metered.
+        assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+
+        // Connect cell and use it as an underlying network.
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.connect(true);
+
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mCellNetworkAgent.getNetwork() });
+
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
+        mWiFiNetworkAgent.connect(true);
+
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
+
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        // Don't disconnect, but note the VPN is not using wifi any more.
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mCellNetworkAgent.getNetwork() });
+
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        // Use Wifi but not cell. Note the VPN is now unmetered.
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mWiFiNetworkAgent.getNetwork() });
+
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
+                && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        // Use both again.
+        mService.setUnderlyingNetworksForVpn(
+                new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
+
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        // Disconnect cell. Receive update without even removing the dead network from the
+        // underlying networks – it's dead anyway. Not metered any more.
+        mCellNetworkAgent.disconnect();
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
+                && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        // Disconnect wifi too. No underlying networks means this is now metered.
+        mWiFiNetworkAgent.disconnect();
+        vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+                && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
+                && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+                vpnNetworkAgent);
+
+        mMockVpn.disconnect();
+    }
 }