Merge "com.android.mediadrm.signer is built with java_sdk_library"
diff --git a/api/current.txt b/api/current.txt
index 9d8db31..7787c1bfc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -70142,7 +70142,7 @@
     method public java.util.regex.Matcher reset();
     method public java.util.regex.Matcher reset(java.lang.CharSequence);
     method public int start();
-    method public int start(int) throws java.lang.IllegalStateException;
+    method public int start(int);
     method public int start(java.lang.String);
     method public java.util.regex.MatchResult toMatchResult();
     method public java.util.regex.Matcher useAnchoringBounds(boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index 54604a5..79a8d44 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -244,6 +244,7 @@
 package android.content.pm {
 
   public class ActivityInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
+    method public static boolean isTranslucentOrFloating(android.content.res.TypedArray);
     field public static final int RESIZE_MODE_RESIZEABLE = 2; // 0x2
   }
 
diff --git a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
index 37b7acf..8683ca1 100644
--- a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
+++ b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
@@ -211,10 +211,10 @@
                 mExtras.putBoolean(key, Boolean.valueOf(value));
 
             } else if (opt.equals("-f") || opt.equals("--foreground")) {
-                mExemptionFlag = ContentResolver.SYNC_EXEMPTION_ACTIVE;
+                mExemptionFlag = ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET;
 
             } else if (opt.equals("-F") || opt.equals("--top")) {
-                mExemptionFlag = ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP;
+                mExemptionFlag = ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP;
 
             } else {
                 System.err.println("Error: Unknown option: " + opt);
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 3172281..b11e843 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -182,8 +182,7 @@
     sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
     if (display == NULL) {
         fprintf(stderr, "Unable to get handle for display %d\n", displayId);
-        // b/36066697: Avoid running static destructors.
-        _exit(1);
+        return 1;
     }
 
     Vector<DisplayInfo> configs;
@@ -192,8 +191,7 @@
     if (static_cast<size_t>(activeConfig) >= configs.size()) {
         fprintf(stderr, "Active config %d not inside configs (size %zu)\n",
                 activeConfig, configs.size());
-        // b/36066697: Avoid running static destructors.
-        _exit(1);
+        return 1;
     }
     uint8_t displayOrientation = configs[activeConfig].orientation;
     uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];
@@ -204,14 +202,14 @@
             &outBuffer);
     if (result != NO_ERROR) {
         close(fd);
-        _exit(1);
+        return 1;
     }
 
     result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);
 
     if (base == NULL) {
         close(fd);
-        _exit(1);
+        return 1;
     }
 
     w = outBuffer->getWidth();
@@ -256,6 +254,5 @@
         munmap((void *)mapbase, mapsize);
     }
 
-    // b/36066697: Avoid running static destructors.
-    _exit(0);
+    return 0;
 }
\ No newline at end of file
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 091268e..5268ba2 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -141,10 +141,14 @@
 
 LOCAL_MODULE_CLASS := EXECUTABLES
 
-# Enable sanitizer and allow very verbose printing on eng builds
+# Enable sanitizer ONLY on eng builds.
 ifeq ($(TARGET_BUILD_VARIANT),eng)
     LOCAL_CLANG := true
     LOCAL_SANITIZE := address
+endif
+
+# Add a flag to enable stats log printing from statsd on debug builds.
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
     LOCAL_CFLAGS += \
         -DVERY_VERBOSE_PRINTING
 endif
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index e7f1caf..1378ce5 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -152,7 +152,7 @@
         if (is_create) {
             mUidMap->assignIsolatedUid(isolated_uid, parent_uid);
         } else {
-            mUidMap->removeIsolatedUid(isolated_uid, parent_uid);
+            mUidMap->removeIsolatedUid(isolated_uid);
         }
     } else {
         ALOGE("Failed to parse uid in the isolated uid change event.");
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index ab9c7e8..ca3786a 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1484,6 +1484,7 @@
 message IsolatedUidChanged {
     // The host UID. Generally, we should attribute metrics from the isolated uid to the host uid.
     // NOTE: DO NOT annotate uid field in this atom. This atom is specially handled in statsd.
+    // This field is ignored when event == REMOVED.
     optional int32 parent_uid = 1;
 
     optional int32 isolated_uid = 2;
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index fff909c..be94725 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -272,7 +272,7 @@
     mIsolatedUidMap[isolatedUid] = parentUid;
 }
 
-void UidMap::removeIsolatedUid(int isolatedUid, int parentUid) {
+void UidMap::removeIsolatedUid(int isolatedUid) {
     lock_guard<mutex> lock(mIsolatedMutex);
 
     auto it = mIsolatedUidMap.find(isolatedUid);
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 5e42cd1..514eec7 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -119,7 +119,7 @@
     void OnConfigRemoved(const ConfigKey& key);
 
     void assignIsolatedUid(int isolatedUid, int parentUid);
-    void removeIsolatedUid(int isolatedUid, int parentUid);
+    void removeIsolatedUid(int isolatedUid);
 
     // Returns the host uid if it exists. Otherwise, returns the same uid that was passed-in.
     virtual int getHostUidOrSelf(int uid) const;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 4d7bc00..67d60fa 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -261,6 +261,7 @@
 Landroid/app/ActivityThread;->mPackages:Landroid/util/ArrayMap;
 Landroid/app/ActivityThread;->mPendingConfiguration:Landroid/content/res/Configuration;
 Landroid/app/ActivityThread;->mProviderMap:Landroid/util/ArrayMap;
+Landroid/app/ActivityThread;->mProviderRefCountMap:Landroid/util/ArrayMap;
 Landroid/app/ActivityThread;->mResourcePackages:Landroid/util/ArrayMap;
 Landroid/app/ActivityThread;->mResourcesManager:Landroid/app/ResourcesManager;
 Landroid/app/ActivityThread;->mServices:Landroid/util/ArrayMap;
@@ -737,6 +738,7 @@
 Landroid/app/IWallpaperManager;->getWallpaper(Ljava/lang/String;Landroid/app/IWallpaperManagerCallback;ILandroid/os/Bundle;I)Landroid/os/ParcelFileDescriptor;
 Landroid/app/IWallpaperManager;->getWallpaperInfo(I)Landroid/app/WallpaperInfo;
 Landroid/app/IWallpaperManager;->getWidthHint()I
+Landroid/app/IWallpaperManager;->hasNamedWallpaper(Ljava/lang/String;)Z
 Landroid/app/IWallpaperManager;->setWallpaperComponent(Landroid/content/ComponentName;)V
 Landroid/app/IWallpaperManagerCallback$Stub;-><init>()V
 Landroid/app/IWallpaperManagerCallback;->onWallpaperChanged()V
@@ -905,9 +907,14 @@
 Landroid/app/SearchManager;->launchAssist(Landroid/os/Bundle;)V
 Landroid/app/SearchManager;->mSearchDialog:Landroid/app/SearchDialog;
 Landroid/app/SearchManager;->startSearch(Ljava/lang/String;ZLandroid/content/ComponentName;Landroid/os/Bundle;ZLandroid/graphics/Rect;)V
+Landroid/app/servertransaction/ActivityResultItem;->mResultInfoList:Ljava/util/List;
+Landroid/app/servertransaction/ClientTransaction;->getActivityToken()Landroid/os/IBinder;
+Landroid/app/servertransaction/ClientTransaction;->getCallbacks()Ljava/util/List;
+Landroid/app/servertransaction/ClientTransaction;->getLifecycleStateRequest()Landroid/app/servertransaction/ActivityLifecycleItem;
 Landroid/app/servertransaction/ClientTransaction;->mActivityCallbacks:Ljava/util/List;
 Landroid/app/servertransaction/LaunchActivityItem;->mInfo:Landroid/content/pm/ActivityInfo;
 Landroid/app/servertransaction/LaunchActivityItem;->mIntent:Landroid/content/Intent;
+Landroid/app/servertransaction/NewIntentItem;->mIntents:Ljava/util/List;
 Landroid/app/Service;->attach(Landroid/content/Context;Landroid/app/ActivityThread;Ljava/lang/String;Landroid/os/IBinder;Landroid/app/Application;Ljava/lang/Object;)V
 Landroid/app/Service;->mActivityManager:Landroid/app/IActivityManager;
 Landroid/app/Service;->mApplication:Landroid/app/Application;
@@ -919,6 +926,7 @@
 Landroid/app/ServiceConnectionLeaked;-><init>(Ljava/lang/String;)V
 Landroid/app/SharedPreferencesImpl;-><init>(Ljava/io/File;I)V
 Landroid/app/SharedPreferencesImpl;->mFile:Ljava/io/File;
+Landroid/app/SharedPreferencesImpl;->startLoadFromDisk()V
 Landroid/app/SharedPreferencesImpl;->startReloadIfChangedUnexpectedly()V
 Landroid/app/StatusBarManager;-><init>(Landroid/content/Context;)V
 Landroid/app/StatusBarManager;->collapsePanels()V
@@ -1691,6 +1699,12 @@
 Landroid/content/pm/PackageParser$ProviderIntentInfo;->provider:Landroid/content/pm/PackageParser$Provider;
 Landroid/content/pm/PackageParser$Service;->info:Landroid/content/pm/ServiceInfo;
 Landroid/content/pm/PackageParser$ServiceIntentInfo;->service:Landroid/content/pm/PackageParser$Service;
+Landroid/content/pm/PackageParser$SigningDetails$Builder;-><init>()V
+Landroid/content/pm/PackageParser$SigningDetails$Builder;->build()Landroid/content/pm/PackageParser$SigningDetails;
+Landroid/content/pm/PackageParser$SigningDetails$Builder;->setPastSigningCertificates([Landroid/content/pm/Signature;)Landroid/content/pm/PackageParser$SigningDetails$Builder;
+Landroid/content/pm/PackageParser$SigningDetails$Builder;->setPastSigningCertificatesFlags([I)Landroid/content/pm/PackageParser$SigningDetails$Builder;
+Landroid/content/pm/PackageParser$SigningDetails$Builder;->setSignatures([Landroid/content/pm/Signature;)Landroid/content/pm/PackageParser$SigningDetails$Builder;
+Landroid/content/pm/PackageParser$SigningDetails$Builder;->setSignatureSchemeVersion(I)Landroid/content/pm/PackageParser$SigningDetails$Builder;
 Landroid/content/pm/PackageParser$SigningDetails;->signatures:[Landroid/content/pm/Signature;
 Landroid/content/pm/PackageParser;-><init>()V
 Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Ljava/io/File;Z)V
@@ -5075,6 +5089,7 @@
 Landroid/service/wallpaper/WallpaperService$Engine;->mPendingXOffset:F
 Landroid/service/wallpaper/WallpaperService$Engine;->setFixedSizeAllowed(Z)V
 Landroid/service/wallpaper/WallpaperService;->MSG_WINDOW_RESIZED:I
+Landroid/speech/IRecognitionListener;->onEvent(ILandroid/os/Bundle;)V
 Landroid/speech/tts/TextToSpeech;->getCurrentEngine()Ljava/lang/String;
 Landroid/speech/tts/TextToSpeech;->mConnectingServiceConnection:Landroid/speech/tts/TextToSpeech$Connection;
 Landroid/speech/tts/TextToSpeech;->mCurrentEngine:Ljava/lang/String;
@@ -5392,6 +5407,7 @@
 Landroid/telephony/SmsMessage;->setSubId(I)V
 Landroid/telephony/SmsMessage;->useCdmaFormatForMoSms()Z
 Landroid/telephony/SmsMessage;->useCdmaFormatForMoSms(I)Z
+Landroid/telephony/SubscriptionInfo;->getNameSource()I
 Landroid/telephony/SubscriptionManager;-><init>(Landroid/content/Context;)V
 Landroid/telephony/SubscriptionManager;->CONTENT_URI:Landroid/net/Uri;
 Landroid/telephony/SubscriptionManager;->DEFAULT_SUBSCRIPTION_ID:I
@@ -5426,6 +5442,8 @@
 Landroid/telephony/TelephonyManager;->getDeviceSoftwareVersion(I)Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getGroupIdLevel1(I)Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getIccAuthentication(IIILjava/lang/String;)Ljava/lang/String;
+Landroid/telephony/TelephonyManager;->getImsConfig(II)Landroid/telephony/ims/aidl/IImsConfig;
+Landroid/telephony/TelephonyManager;->getImsRegistration(II)Landroid/telephony/ims/aidl/IImsRegistration;
 Landroid/telephony/TelephonyManager;->getIsimImpi()Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getIsimImpu()[Ljava/lang/String;
 Landroid/telephony/TelephonyManager;->getIsimPcscf()[Ljava/lang/String;
@@ -5814,6 +5832,7 @@
 Landroid/view/animation/TranslateAnimation;->mToYValue:F
 Landroid/view/animation/TranslateYAnimation;-><init>(IFIF)V
 Landroid/view/autofill/IAutoFillManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/view/autofill/IAutoFillManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/autofill/IAutoFillManager;
 Landroid/view/Choreographer$CallbackQueue;->addCallbackLocked(JLjava/lang/Object;Ljava/lang/Object;)V
 Landroid/view/Choreographer$CallbackRecord;->run(J)V
 Landroid/view/Choreographer;->doFrame(JI)V
@@ -9023,6 +9042,10 @@
 Lorg/w3c/dom/traversal/NodeFilter;->acceptNode(Lorg/w3c/dom/Node;)S
 Lorg/w3c/dom/traversal/NodeIterator;->detach()V
 Lorg/w3c/dom/traversal/NodeIterator;->nextNode()Lorg/w3c/dom/Node;
+Lorg/xml/sax/ext/Attributes2Impl;->declared:[Z
+Lorg/xml/sax/ext/Attributes2Impl;->specified:[Z
+Lorg/xml/sax/ext/Locator2Impl;->encoding:Ljava/lang/String;
+Lorg/xml/sax/ext/Locator2Impl;->version:Ljava/lang/String;
 Lorg/xml/sax/helpers/AttributesImpl;->badIndex(I)V
 Lorg/xml/sax/helpers/AttributesImpl;->data:[Ljava/lang/String;
 Lorg/xml/sax/helpers/AttributesImpl;->ensureCapacity(I)V
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7ddf006..973ca12 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1557,6 +1557,7 @@
         private final long[] mRejectTimes;
         private final int mDuration;
         private final int mProxyUid;
+        private final boolean mRunning;
         private final String mProxyPackageName;
 
         public OpEntry(int op, int mode, long time, long rejectTime, int duration,
@@ -1568,12 +1569,13 @@
             mTimes[0] = time;
             mRejectTimes[0] = rejectTime;
             mDuration = duration;
+            mRunning = duration == -1;
             mProxyUid = proxyUid;
             mProxyPackageName = proxyPackage;
         }
 
         public OpEntry(int op, int mode, long[] times, long[] rejectTimes, int duration,
-                int proxyUid, String proxyPackage) {
+                boolean running, int proxyUid, String proxyPackage) {
             mOp = op;
             mMode = mode;
             mTimes = new long[_NUM_UID_STATE];
@@ -1581,10 +1583,16 @@
             System.arraycopy(times, 0, mTimes, 0, _NUM_UID_STATE);
             System.arraycopy(rejectTimes, 0, mRejectTimes, 0, _NUM_UID_STATE);
             mDuration = duration;
+            mRunning = running;
             mProxyUid = proxyUid;
             mProxyPackageName = proxyPackage;
         }
 
+        public OpEntry(int op, int mode, long[] times, long[] rejectTimes, int duration,
+                int proxyUid, String proxyPackage) {
+            this(op, mode, times, rejectTimes, duration, duration == -1, proxyUid, proxyPackage);
+        }
+
         public int getOp() {
             return mOp;
         }
@@ -1634,7 +1642,7 @@
         }
 
         public boolean isRunning() {
-            return mDuration == -1;
+            return mRunning;
         }
 
         public int getDuration() {
@@ -1661,6 +1669,7 @@
             dest.writeLongArray(mTimes);
             dest.writeLongArray(mRejectTimes);
             dest.writeInt(mDuration);
+            dest.writeBoolean(mRunning);
             dest.writeInt(mProxyUid);
             dest.writeString(mProxyPackageName);
         }
@@ -1671,6 +1680,7 @@
             mTimes = source.createLongArray();
             mRejectTimes = source.createLongArray();
             mDuration = source.readInt();
+            mRunning = source.readBoolean();
             mProxyUid = source.readInt();
             mProxyPackageName = source.readString();
         }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c2ac923..d2338f8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6603,22 +6603,33 @@
      * Helper class for generating large-format notifications that include multiple back-and-forth
      * messages of varying types between any number of people.
      *
-     * <br>
+     * <p>
      * If the platform does not provide large-format notifications, this method has no effect. The
      * user will always see the normal notification view.
-     * <br>
-     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior, like
-     * so:
+     *
+     * <p>
+     * If the app is targeting Android P and above, it is required to use the {@link Person}
+     * class in order to get an optimal rendering of the notification and its avatars. For
+     * conversations involving multiple people, the app should also make sure that it marks the
+     * conversation as a group with {@link #setGroupConversation(boolean)}.
+     *
+     * <p>
+     * This class is a "rebuilder": It attaches to a Builder object and modifies its behavior.
+     * Here's an example of how this may be used:
      * <pre class="prettyprint">
      *
+     * Person user = new Person.Builder().setIcon(userIcon).setName(userName).build();
+     * MessagingStyle style = new MessagingStyle(user)
+     *      .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
+     *      .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
+     *      .setGroupConversation(hasMultiplePeople());
+     *
      * Notification noti = new Notification.Builder()
-     *     .setContentTitle(&quot;2 new messages wtih &quot; + sender.toString())
+     *     .setContentTitle(&quot;2 new messages with &quot; + sender.toString())
      *     .setContentText(subject)
      *     .setSmallIcon(R.drawable.new_message)
      *     .setLargeIcon(aBitmap)
-     *     .setStyle(new Notification.MessagingStyle(resources.getString(R.string.reply_name))
-     *         .addMessage(messages[0].getText(), messages[0].getTime(), messages[0].getSender())
-     *         .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getSender()))
+     *     .setStyle(style)
      *     .build();
      * </pre>
      */
@@ -6828,7 +6839,9 @@
         }
 
         /**
-         * Sets whether this conversation notification represents a group.
+         * Sets whether this conversation notification represents a group. If the app is targeting
+         * Android P, this is required if the app wants to display the largeIcon set with
+         * {@link Notification.Builder#setLargeIcon(Bitmap)}, otherwise it will be hidden.
          *
          * @param isGroupConversation {@code true} if the conversation represents a group,
          * {@code false} otherwise.
@@ -7050,12 +7063,21 @@
             CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
                     ? super.mBigContentTitle
                     : mConversationTitle;
-            boolean isOneToOne = TextUtils.isEmpty(conversationTitle);
+            boolean atLeastP = mBuilder.mContext.getApplicationInfo().targetSdkVersion
+                    >= Build.VERSION_CODES.P;
+            boolean isOneToOne;
             CharSequence nameReplacement = null;
-            if (hasOnlyWhiteSpaceSenders()) {
-                isOneToOne = true;
-                nameReplacement = conversationTitle;
-                conversationTitle = null;
+            Icon avatarReplacement = null;
+            if (!atLeastP) {
+                isOneToOne = TextUtils.isEmpty(conversationTitle);
+                avatarReplacement = mBuilder.mN.mLargeIcon;
+                if (hasOnlyWhiteSpaceSenders()) {
+                    isOneToOne = true;
+                    nameReplacement = conversationTitle;
+                    conversationTitle = null;
+                }
+            } else {
+                isOneToOne = !isGroupConversation();
             }
             TemplateBindResult bindResult = new TemplateBindResult();
             RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
@@ -7078,8 +7100,8 @@
                     mBuilder.getSecondaryTextColor());
             contentView.setBoolean(R.id.status_bar_latest_event_content, "setDisplayImagesAtEnd",
                     displayImagesAtEnd);
-            contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon",
-                    mBuilder.mN.mLargeIcon);
+            contentView.setIcon(R.id.status_bar_latest_event_content, "setAvatarReplacement",
+                    avatarReplacement);
             contentView.setCharSequence(R.id.status_bar_latest_event_content, "setNameReplacement",
                     nameReplacement);
             contentView.setBoolean(R.id.status_bar_latest_event_content, "setIsOneToOne",
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index d445965..e7ae32d 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -255,7 +255,7 @@
     /**
      * @deprecated Since Android P app can no longer request restoring of its backup.
      *
-     * <p>Restore the calling application from backup.  The data will be restored from the
+     * Restore the calling application from backup.  The data will be restored from the
      * current backup dataset if the application has stored data there, or from
      * the dataset used during the last full device setup operation if the current
      * backup dataset has no matching data.  If no backup data exists for this application
@@ -282,7 +282,7 @@
     /**
      * @deprecated Since Android P app can no longer request restoring of its backup.
      *
-     * <p>Restore the calling application from backup.  The data will be restored from the
+     * Restore the calling application from backup.  The data will be restored from the
      * current backup dataset if the application has stored data there, or from
      * the dataset used during the last full device setup operation if the current
      * backup dataset has no matching data.  If no backup data exists for this application
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index 5e75841..4c22c94 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -15,6 +15,8 @@
  */
 package android.app.slice;
 
+import static android.app.slice.Slice.SUBTYPE_COLOR;
+
 import android.annotation.NonNull;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -29,6 +31,7 @@
 import android.content.pm.ProviderInfo;
 import android.database.ContentObserver;
 import android.database.Cursor;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -39,6 +42,8 @@
 import android.os.StrictMode.ThreadPolicy;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -472,12 +477,25 @@
         }
         Slice.Builder parent = new Slice.Builder(sliceUri);
         Slice.Builder childAction = new Slice.Builder(parent)
+                .addIcon(Icon.createWithResource(context,
+                        com.android.internal.R.drawable.ic_permission), null,
+                        Collections.emptyList())
                 .addHints(Arrays.asList(Slice.HINT_TITLE, Slice.HINT_SHORTCUT))
                 .addAction(action, new Slice.Builder(parent).build(), null);
 
+        TypedValue tv = new TypedValue();
+        new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault_Light)
+                .getTheme().resolveAttribute(android.R.attr.colorAccent, tv, true);
+        int deviceDefaultAccent = tv.data;
+
         parent.addSubSlice(new Slice.Builder(sliceUri.buildUpon().appendPath("permission").build())
+                .addIcon(Icon.createWithResource(context,
+                        com.android.internal.R.drawable.ic_arrow_forward), null,
+                        Collections.emptyList())
                 .addText(getPermissionString(context, callingPackage), null,
                         Collections.emptyList())
+                .addInt(deviceDefaultAccent, SUBTYPE_COLOR,
+                        Collections.emptyList())
                 .addSubSlice(childAction.build(), null)
                 .build(), null);
         return parent.addHints(Arrays.asList(Slice.HINT_PERMISSION_REQUEST)).build();
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 503ca6c..3e90af3 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -399,16 +399,20 @@
      * {@hide}
      */
     public UsageEvents(Parcel in) {
-        mEventCount = in.readInt();
-        mIndex = in.readInt();
+        byte[] bytes = in.readBlob();
+        Parcel data = Parcel.obtain();
+        data.unmarshall(bytes, 0, bytes.length);
+        data.setDataPosition(0);
+        mEventCount = data.readInt();
+        mIndex = data.readInt();
         if (mEventCount > 0) {
-            mStringPool = in.createStringArray();
+            mStringPool = data.createStringArray();
 
-            final int listByteLength = in.readInt();
-            final int positionInParcel = in.readInt();
+            final int listByteLength = data.readInt();
+            final int positionInParcel = data.readInt();
             mParcel = Parcel.obtain();
             mParcel.setDataPosition(0);
-            mParcel.appendFrom(in, in.dataPosition(), listByteLength);
+            mParcel.appendFrom(data, data.dataPosition(), listByteLength);
             mParcel.setDataSize(mParcel.dataPosition());
             mParcel.setDataPosition(positionInParcel);
         }
@@ -586,10 +590,11 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mEventCount);
-        dest.writeInt(mIndex);
+        Parcel data = Parcel.obtain();
+        data.writeInt(mEventCount);
+        data.writeInt(mIndex);
         if (mEventCount > 0) {
-            dest.writeStringArray(mStringPool);
+            data.writeStringArray(mStringPool);
 
             if (mEventsToWrite != null) {
                 // Write out the events
@@ -604,31 +609,34 @@
                     final int listByteLength = p.dataPosition();
 
                     // Write the total length of the data.
-                    dest.writeInt(listByteLength);
+                    data.writeInt(listByteLength);
 
                     // Write our current position into the data.
-                    dest.writeInt(0);
+                    data.writeInt(0);
 
                     // Write the data.
-                    dest.appendFrom(p, 0, listByteLength);
+                    data.appendFrom(p, 0, listByteLength);
                 } finally {
                     p.recycle();
                 }
 
             } else if (mParcel != null) {
                 // Write the total length of the data.
-                dest.writeInt(mParcel.dataSize());
+                data.writeInt(mParcel.dataSize());
 
                 // Write out current position into the data.
-                dest.writeInt(mParcel.dataPosition());
+                data.writeInt(mParcel.dataPosition());
 
                 // Write the data.
-                dest.appendFrom(mParcel, 0, mParcel.dataSize());
+                data.appendFrom(mParcel, 0, mParcel.dataSize());
             } else {
                 throw new IllegalStateException(
                         "Either mParcel or mEventsToWrite must not be null");
             }
         }
+        // Data can be too large for a transact. Write the data as a Blob, which will be written to
+        // ashmem if too large.
+        dest.writeBlob(data.marshall());
     }
 
     public static final Creator<UsageEvents> CREATOR = new Creator<UsageEvents>() {
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 1b07784..72d209a 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -184,7 +184,11 @@
     /** @hide */
     public static final int REASON_SUB_USAGE_SLICE_PINNED_PRIV  = 0x000A;
     /** @hide */
-    public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000B;
+    public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE = 0x000B;
+    /** @hide */
+    public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C;
+    /** @hide */
+    public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;
 
     /** @hide */
     public static final int REASON_SUB_PREDICTED_RESTORED       = 0x0001;
@@ -669,13 +673,19 @@
                         sb.append("-sa");
                         break;
                     case REASON_SUB_USAGE_SLICE_PINNED:
-                        sb.append("slp");
+                        sb.append("-lp");
                         break;
                     case REASON_SUB_USAGE_SLICE_PINNED_PRIV:
-                        sb.append("slpp");
+                        sb.append("-lv");
+                        break;
+                    case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE:
+                        sb.append("-en");
+                        break;
+                    case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE:
+                        sb.append("-ed");
                         break;
                     case REASON_SUB_USAGE_EXEMPTED_SYNC_START:
-                        sb.append("es");
+                        sb.append("-es");
                         break;
                 }
                 break;
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index b8628a4..1a656ab 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -245,7 +245,15 @@
             int numDeferredJobs, long timeSinceLastJobRun);
 
     /**
-     * Report a sync that was scheduled by an active app is about to be executed.
+     * Report a sync is scheduled by a foreground app.
+     *
+     * @param packageName name of the package that owns the sync adapter.
+     * @param userId which user the app is associated with
+     */
+    public abstract void reportExemptedSyncScheduled(String packageName, @UserIdInt int userId);
+
+    /**
+     * Report a sync that was scheduled by a foreground app is about to be executed.
      *
      * @param packageName name of the package that owns the sync adapter.
      * @param userId which user the app is associated with
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f7908b6..32a6743 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -520,27 +520,36 @@
     public static final int SYNC_EXEMPTION_NONE = 0;
 
     /**
-     * When executing a sync with this exemption, we'll put the target app in the ACTIVE bucket
-     * for 10 minutes. This will allow the sync adapter to schedule/run further syncs and jobs.
+     * Exemption given to a sync request made by a foreground app (including
+     * PROCESS_STATE_IMPORTANT_FOREGROUND).
      *
-     * Note this will still *not* let RARE apps to run syncs, because they still won't get network
-     * connection.
+     * At the schedule time, we promote the sync adapter app for a higher bucket:
+     * - If the device is not dozing (so the sync will start right away)
+     *   promote to ACTIVE for 1 hour.
+     * - If the device is dozing (so the sync *won't* start right away),
+     * promote to WORKING_SET for 4 hours, so it'll get a higher chance to be started once the
+     * device comes out of doze.
+     * - When the sync actually starts, we promote the sync adapter app to ACTIVE for 10 minutes,
+     * so it can schedule and start more syncs without getting throttled, even when the first
+     * operation was canceled and now we're retrying.
+     *
+     *
      * @hide
      */
-    public static final int SYNC_EXEMPTION_ACTIVE = 1;
+    public static final int SYNC_EXEMPTION_PROMOTE_BUCKET = 1;
 
     /**
-     * In addition to {@link #SYNC_EXEMPTION_ACTIVE}, we put the sync adapter app in the
+     * In addition to {@link #SYNC_EXEMPTION_PROMOTE_BUCKET}, we put the sync adapter app in the
      * temp whitelist for 10 minutes, so that even RARE apps can run syncs right away.
      * @hide
      */
-    public static final int SYNC_EXEMPTION_ACTIVE_WITH_TEMP = 2;
+    public static final int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP = 2;
 
     /** @hide */
     @IntDef(flag = false, prefix = { "SYNC_EXEMPTION_" }, value = {
             SYNC_EXEMPTION_NONE,
-            SYNC_EXEMPTION_ACTIVE,
-            SYNC_EXEMPTION_ACTIVE_WITH_TEMP,
+            SYNC_EXEMPTION_PROMOTE_BUCKET,
+            SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SyncExemption {}
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 1461711..0e91a29 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1188,6 +1188,7 @@
      * Determines whether the {@link Activity} is considered translucent or floating.
      * @hide
      */
+    @TestApi
     public static boolean isTranslucentOrFloating(TypedArray attributes) {
         final boolean isTranslucent =
                 attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent,
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1268beb..aa0cacb 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1664,7 +1664,8 @@
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device includes at least one form of audio
-     * output, such as speakers, audio jack or streaming over bluetooth
+     * output, as defined in the Android Compatibility Definition Document (CDD)
+     * <a href="https://source.android.com/compatibility/android-cdd#7_8_audio">section 7.8 Audio</a>.
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 262de15..1275a85 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -813,6 +813,10 @@
     /**
      * <p>The camera device is a logical camera backed by two or more physical cameras that are
      * also exposed to the application.</p>
+     * <p>Camera application shouldn't assume that there are at most 1 rear camera and 1 front
+     * camera in the system. For an application that switches between front and back cameras,
+     * the recommendation is to switch between the first rear camera and the first front
+     * camera in the list of supported camera devices.</p>
      * <p>This capability requires the camera device to support the following:</p>
      * <ul>
      * <li>This camera device must list the following static metadata entries in {@link android.hardware.camera2.CameraCharacteristics }:<ul>
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 5890d98..7e7d617 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -138,6 +138,15 @@
     }
 
     /**
+     * Dump proxy debug information.
+     *
+     * @hide
+     */
+    public static void dumpProxyDebugInfo() {
+        BinderProxy.dumpProxyDebugInfo();
+    }
+
+    /**
      * Check if binder transaction tracing is enabled.
      *
      * @hide
@@ -942,8 +951,7 @@
                     // about to crash.
                     final int totalUnclearedSize = unclearedSize();
                     if (totalUnclearedSize >= CRASH_AT_SIZE) {
-                        dumpProxyInterfaceCounts();
-                        dumpPerUidProxyCounts();
+                        dumpProxyDebugInfo();
                         Runtime.getRuntime().gc();
                         throw new AssertionError("Binder ProxyMap has too many entries: "
                                 + totalSize + " (total), " + totalUnclearedSize + " (uncleared), "
@@ -1028,6 +1036,14 @@
     private static ProxyMap sProxyMap = new ProxyMap();
 
     /**
+      * @hide
+      */
+    public static void dumpProxyDebugInfo() {
+        sProxyMap.dumpProxyInterfaceCounts();
+        sProxyMap.dumpPerUidProxyCounts();
+    }
+
+    /**
      * Return a BinderProxy for IBinder.
      * This method is thread-hostile!  The (native) caller serializes getInstance() calls using
      * gProxyLock.
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index f1f6f41..d2d8f1e 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -72,12 +72,23 @@
     public @interface VibrationIntensity{}
 
     private final String mPackageName;
+    // The default vibration intensity level for haptic feedback.
+    @VibrationIntensity
+    private final int mDefaultHapticFeedbackIntensity;
+    // The default vibration intensity level for notifications.
+    @VibrationIntensity
+    private final int mDefaultNotificationVibrationIntensity;
 
     /**
      * @hide to prevent subclassing from outside of the framework
      */
     public Vibrator() {
         mPackageName = ActivityThread.currentPackageName();
+        final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
+        mDefaultHapticFeedbackIntensity = loadDefaultIntensity(ctx,
+                com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
+        mDefaultNotificationVibrationIntensity = loadDefaultIntensity(ctx,
+                com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
     }
 
     /**
@@ -85,6 +96,14 @@
      */
     protected Vibrator(Context context) {
         mPackageName = context.getOpPackageName();
+        mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context,
+                com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
+        mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context,
+                com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
+    }
+
+    private int loadDefaultIntensity(Context ctx, int resId) {
+        return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM;
     }
 
     /**
@@ -92,7 +111,7 @@
      * @hide
      */
     public int getDefaultHapticFeedbackIntensity() {
-        return VIBRATION_INTENSITY_MEDIUM;
+        return mDefaultHapticFeedbackIntensity;
     }
 
     /**
@@ -100,7 +119,7 @@
      * @hide
      */
     public int getDefaultNotificationVibrationIntensity() {
-        return VIBRATION_INTENSITY_HIGH;
+        return mDefaultNotificationVibrationIntensity;
     }
 
     /**
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 105cd38..0257891 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -70,7 +70,7 @@
         assertNotCalled();
         mCalled = true;
         try {
-            mCallback.onFailure(message);
+            mCallback.onFailure(mRequestId, message);
         } catch (RemoteException e) {
             e.rethrowAsRuntimeException();
         }
diff --git a/core/java/android/service/autofill/IFillCallback.aidl b/core/java/android/service/autofill/IFillCallback.aidl
index 2bb3e9a..1bad1d7 100644
--- a/core/java/android/service/autofill/IFillCallback.aidl
+++ b/core/java/android/service/autofill/IFillCallback.aidl
@@ -28,5 +28,5 @@
 interface IFillCallback {
     void onCancellable(in ICancellationSignal cancellation);
     void onSuccess(in FillResponse response);
-    void onFailure(CharSequence message);
+    void onFailure(int requestId, CharSequence message);
 }
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index a0cbfb6..ce334ae 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -38,11 +38,10 @@
     static {
         DEFAULT_FLAGS = new HashMap<>();
         DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
-        DEFAULT_FLAGS.put("settings_about_phone_v2", "true");
         DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
         DEFAULT_FLAGS.put("settings_data_usage_v2", "true");
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
-        DEFAULT_FLAGS.put("settings_systemui_theme", "false");
+        DEFAULT_FLAGS.put("settings_systemui_theme", "true");
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 8a7d004..7944319 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5060,9 +5060,9 @@
             child.assignParent(this);
         } else {
             child.mParent = this;
-            if (child.hasUnhandledKeyListener()) {
-                incrementChildUnhandledKeyListeners();
-            }
+        }
+        if (child.hasUnhandledKeyListener()) {
+            incrementChildUnhandledKeyListeners();
         }
 
         final boolean childHasFocus = child.hasFocus();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 364a4a5..d34b92b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -76,7 +76,6 @@
 import android.util.MergedConfiguration;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SparseBooleanArray;
 import android.util.TimeUtils;
 import android.util.TypedValue;
 import android.view.Surface.OutOfResourcesException;
@@ -1626,6 +1625,8 @@
                         contentInsets.top + outsets.top, contentInsets.right + outsets.right,
                         contentInsets.bottom + outsets.bottom);
             }
+            contentInsets = ensureInsetsNonNegative(contentInsets, "content");
+            stableInsets = ensureInsetsNonNegative(stableInsets, "stable");
             mLastWindowInsets = new WindowInsets(contentInsets,
                     null /* windowDecorInsets */, stableInsets,
                     mContext.getResources().getConfiguration().isScreenRound(),
@@ -1634,6 +1635,17 @@
         return mLastWindowInsets;
     }
 
+    private Rect ensureInsetsNonNegative(Rect insets, String kind) {
+        if (insets.left < 0  || insets.top < 0  || insets.right < 0  || insets.bottom < 0) {
+            Log.wtf(mTag, "Negative " + kind + "Insets: " + insets + ", mFirst=" + mFirst);
+            return new Rect(Math.max(0, insets.left),
+                    Math.max(0, insets.top),
+                    Math.max(0, insets.right),
+                    Math.max(0, insets.bottom));
+        }
+        return insets;
+    }
+
     void dispatchApplyInsets(View host) {
         WindowInsets insets = getWindowInsets(true /* forceConstruct */);
         final boolean dispatchCutout = (mWindowAttributes.layoutInDisplayCutoutMode
@@ -4972,10 +4984,7 @@
         private int processKeyEvent(QueuedInputEvent q) {
             final KeyEvent event = (KeyEvent)q.mEvent;
 
-            mUnhandledKeyManager.mDispatched = false;
-
-            if (mUnhandledKeyManager.hasFocus()
-                    && mUnhandledKeyManager.dispatchUnique(mView, event)) {
+            if (mUnhandledKeyManager.preViewDispatch(event)) {
                 return FINISH_HANDLED;
             }
 
@@ -4988,7 +4997,10 @@
                 return FINISH_NOT_HANDLED;
             }
 
-            if (mUnhandledKeyManager.dispatchUnique(mView, event)) {
+            // This dispatch is for windows that don't have a Window.Callback. Otherwise,
+            // the Window.Callback usually will have already called this (see
+            // DecorView.superDispatchKeyEvent) leaving this call a no-op.
+            if (mUnhandledKeyManager.dispatch(mView, event)) {
                 return FINISH_HANDLED;
             }
 
@@ -7026,6 +7038,10 @@
             stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
         }
 
+        if (q.mEvent instanceof KeyEvent) {
+            mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
+        }
+
         if (stage != null) {
             handleWindowFocusChanged();
             stage.deliver(q);
@@ -7794,7 +7810,7 @@
      * @param event
      * @return {@code true} if the event was handled, {@code false} otherwise.
      */
-    public boolean dispatchKeyFallbackEvent(KeyEvent event) {
+    public boolean dispatchUnhandledKeyEvent(KeyEvent event) {
         return mUnhandledKeyManager.dispatch(mView, event);
     }
 
@@ -8386,35 +8402,74 @@
     }
 
     private static class UnhandledKeyManager {
-
         // This is used to ensure that unhandled events are only dispatched once. We attempt
         // to dispatch more than once in order to achieve a certain order. Specifically, if we
         // are in an Activity or Dialog (and have a Window.Callback), the unhandled events should
-        // be dispatched after the view hierarchy, but before the Activity. However, if we aren't
+        // be dispatched after the view hierarchy, but before the Callback. However, if we aren't
         // in an activity, we still want unhandled keys to be dispatched.
-        boolean mDispatched = false;
+        private boolean mDispatched = true;
 
-        SparseBooleanArray mCapturedKeys = new SparseBooleanArray();
-        WeakReference<View> mCurrentReceiver = null;
+        // Keeps track of which Views have unhandled key focus for which keys. This doesn't
+        // include modifiers.
+        private final SparseArray<WeakReference<View>> mCapturedKeys = new SparseArray<>();
 
-        private void updateCaptureState(KeyEvent event) {
-            if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                mCapturedKeys.append(event.getKeyCode(), true);
+        // The current receiver. This value is transient and used between the pre-dispatch and
+        // pre-view phase to ensure that other input-stages don't interfere with tracking.
+        private WeakReference<View> mCurrentReceiver = null;
+
+        boolean dispatch(View root, KeyEvent event) {
+            if (mDispatched) {
+                return false;
             }
+            View consumer;
+            try {
+                Trace.traceBegin(Trace.TRACE_TAG_VIEW, "UnhandledKeyEvent dispatch");
+                mDispatched = true;
+
+                consumer = root.dispatchUnhandledKeyEvent(event);
+
+                // If an unhandled listener handles one, then keep track of it so that the
+                // consuming view is first to receive its repeats and release as well.
+                if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                    int keycode = event.getKeyCode();
+                    if (consumer != null && !KeyEvent.isModifierKey(keycode)) {
+                        mCapturedKeys.put(keycode, new WeakReference<>(consumer));
+                    }
+                }
+            } finally {
+                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+            }
+            return consumer != null;
+        }
+
+        /**
+         * Called before the event gets dispatched to anything
+         */
+        void preDispatch(KeyEvent event) {
+            // Always clean-up 'up' events since it's possible for earlier dispatch stages to
+            // consume them without consuming the corresponding 'down' event.
+            mCurrentReceiver = null;
             if (event.getAction() == KeyEvent.ACTION_UP) {
-                mCapturedKeys.delete(event.getKeyCode());
+                int idx = mCapturedKeys.indexOfKey(event.getKeyCode());
+                if (idx >= 0) {
+                    mCurrentReceiver = mCapturedKeys.valueAt(idx);
+                    mCapturedKeys.removeAt(idx);
+                }
             }
         }
 
-        boolean dispatch(View root, KeyEvent event) {
-            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "KeyFallback dispatch");
-            mDispatched = true;
-
-            updateCaptureState(event);
-
+        /**
+         * Called before the event gets dispatched to the view hierarchy
+         * @return {@code true} if an unhandled handler has focus and consumed the event
+         */
+        boolean preViewDispatch(KeyEvent event) {
+            mDispatched = false;
+            if (mCurrentReceiver == null) {
+                mCurrentReceiver = mCapturedKeys.get(event.getKeyCode());
+            }
             if (mCurrentReceiver != null) {
                 View target = mCurrentReceiver.get();
-                if (mCapturedKeys.size() == 0) {
+                if (event.getAction() == KeyEvent.ACTION_UP) {
                     mCurrentReceiver = null;
                 }
                 if (target != null && target.isAttachedToWindow()) {
@@ -8423,24 +8478,7 @@
                 // consume anyways so that we don't feed uncaptured key events to other views
                 return true;
             }
-
-            View consumer = root.dispatchUnhandledKeyEvent(event);
-            if (consumer != null) {
-                mCurrentReceiver = new WeakReference<>(consumer);
-            }
-            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-            return consumer != null;
-        }
-
-        boolean hasFocus() {
-            return mCurrentReceiver != null;
-        }
-
-        boolean dispatchUnique(View root, KeyEvent event) {
-            if (mDispatched) {
-                return false;
-            }
-            return dispatch(root, event);
+            return false;
         }
     }
 }
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 4c7dc11..7555fff 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1899,10 +1899,20 @@
     }
 
     private LogMaker newLog(int category) {
-        return new LogMaker(category)
-                .setPackageName(mContext.getPackageName())
-                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE,
-                        isCompatibilityModeEnabledLocked() ? 1 : 0);
+        final LogMaker log = new LogMaker(category)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SESSION_ID, mSessionId);
+
+        if (isCompatibilityModeEnabledLocked()) {
+            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, 1);
+        }
+        final AutofillClient client = getClient();
+        if (client == null) {
+            // Client should never be null here, but it doesn't hurt to check...
+            log.setPackageName(mContext.getPackageName());
+        } else {
+            log.setComponentName(client.autofillClientGetComponentName());
+        }
+        return log;
     }
 
     /**
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index d22b1e6..6cb0eaa 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -285,10 +285,14 @@
         final Layout layout = mTextView.getLayout();
 
         final Runnable onAnimationEndCallback = () -> {
-            if (result.mStart >= 0 && result.mEnd <= getText(mTextView).length()
+            final SelectionResult startSelectionResult;
+            if (result != null && result.mStart >= 0 && result.mEnd <= getText(mTextView).length()
                     && result.mStart <= result.mEnd) {
-                startSelectionActionMode(result);
+                startSelectionResult = result;
+            } else {
+                startSelectionResult = null;
             }
+            startSelectionActionMode(startSelectionResult);
         };
         // TODO do not trigger the animation if the change included only non-printable characters
         final boolean didSelectionChange =
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index 2940079..9171959 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -156,9 +156,12 @@
         if (activeServiceSupportsAssistGesture()) {
             return getActiveServiceComponentName();
         }
-
-        Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-                .getAssistIntent(false);
+        final SearchManager searchManager =
+            (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+        if (searchManager == null) {
+            return null;
+        }
+        final Intent intent = searchManager.getAssistIntent(false);
         PackageManager pm = mContext.getPackageManager();
         ResolveInfo info = pm.resolveActivityAsUser(intent, PackageManager.MATCH_DEFAULT_ONLY,
                 userId);
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 571878d..4f567d2 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -76,6 +76,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ResolverActivity;
 import com.android.internal.app.ResolverActivity.TargetInfo;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -932,7 +933,7 @@
         public static final int TARGET_SERVICE = 1;
         public static final int TARGET_STANDARD = 2;
 
-        private static final int MAX_SERVICE_TARGETS = 8;
+        private static final int MAX_SERVICE_TARGETS = 4;
         private static final int MAX_TARGETS_PER_SERVICE = 4;
 
         private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
@@ -1189,123 +1190,20 @@
         }
     }
 
-    static class RowScale {
-        private static final int DURATION = 400;
-
-        float mScale;
-        ChooserRowAdapter mAdapter;
-        private final ObjectAnimator mAnimator;
-
-        public static final FloatProperty<RowScale> PROPERTY =
-                new FloatProperty<RowScale>("scale") {
-            @Override
-            public void setValue(RowScale object, float value) {
-                object.mScale = value;
-                object.mAdapter.notifyDataSetChanged();
-            }
-
-            @Override
-            public Float get(RowScale object) {
-                return object.mScale;
-            }
-        };
-
-        public RowScale(@NonNull ChooserRowAdapter adapter, float from, float to) {
-            mAdapter = adapter;
-            mScale = from;
-            if (from == to) {
-                mAnimator = null;
-                return;
-            }
-
-            mAnimator = ObjectAnimator.ofFloat(this, PROPERTY, from, to)
-                .setDuration(DURATION);
-            mAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    mAdapter.onAnimationStart();
-                }
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mAdapter.onAnimationEnd();
-                }
-            });
-        }
-
-        public RowScale setInterpolator(Interpolator interpolator) {
-            if (mAnimator != null) {
-                mAnimator.setInterpolator(interpolator);
-            }
-            return this;
-        }
-
-        public float get() {
-            return mScale;
-        }
-
-        public void startAnimation() {
-            if (mAnimator != null) {
-                mAnimator.start();
-            }
-        }
-
-        public void cancelAnimation() {
-            if (mAnimator != null) {
-                mAnimator.cancel();
-            }
-        }
-    }
-
     class ChooserRowAdapter extends BaseAdapter {
         private ChooserListAdapter mChooserListAdapter;
         private final LayoutInflater mLayoutInflater;
         private final int mColumnCount = 4;
-        private RowScale[] mServiceTargetScale;
-        private final Interpolator mInterpolator;
         private int mAnimationCount = 0;
 
         public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) {
             mChooserListAdapter = wrappedAdapter;
             mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
 
-            mInterpolator = AnimationUtils.loadInterpolator(ChooserActivity.this,
-                    android.R.interpolator.decelerate_quint);
-
             wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
                 @Override
                 public void onChanged() {
                     super.onChanged();
-                    final int rcount = getServiceTargetRowCount();
-                    if (mServiceTargetScale == null
-                            || mServiceTargetScale.length != rcount) {
-                        RowScale[] old = mServiceTargetScale;
-                        int oldRCount = old != null ? old.length : 0;
-                        mServiceTargetScale = new RowScale[rcount];
-                        if (old != null && rcount > 0) {
-                            System.arraycopy(old, 0, mServiceTargetScale, 0,
-                                    Math.min(old.length, rcount));
-                        }
-
-                        for (int i = rcount; i < oldRCount; i++) {
-                            old[i].cancelAnimation();
-                        }
-
-                        for (int i = oldRCount; i < rcount; i++) {
-                            final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
-                                    .setInterpolator(mInterpolator);
-                            mServiceTargetScale[i] = rs;
-                        }
-
-                        // Start the animations in a separate loop.
-                        // The process of starting animations will result in
-                        // binding views to set up initial values, and we must
-                        // have ALL of the new RowScale objects created above before
-                        // we get started.
-                        for (int i = oldRCount; i < rcount; i++) {
-                            mServiceTargetScale[i].startAnimation();
-                        }
-                    }
-
                     notifyDataSetChanged();
                 }
 
@@ -1313,39 +1211,10 @@
                 public void onInvalidated() {
                     super.onInvalidated();
                     notifyDataSetInvalidated();
-                    if (mServiceTargetScale != null) {
-                        for (RowScale rs : mServiceTargetScale) {
-                            rs.cancelAnimation();
-                        }
-                    }
                 }
             });
         }
 
-        private float getRowScale(int rowPosition) {
-            final int start = getCallerTargetRowCount();
-            final int end = start + getServiceTargetRowCount();
-            if (rowPosition >= start && rowPosition < end) {
-                return mServiceTargetScale[rowPosition - start].get();
-            }
-            return 1.f;
-        }
-
-        public void onAnimationStart() {
-            final boolean lock = mAnimationCount == 0;
-            mAnimationCount++;
-            if (lock) {
-                mResolverDrawerLayout.setDismissLocked(true);
-            }
-        }
-
-        public void onAnimationEnd() {
-            mAnimationCount--;
-            if (mAnimationCount == 0) {
-                mResolverDrawerLayout.setDismissLocked(false);
-            }
-        }
-
         @Override
         public int getCount() {
             return (int) (
@@ -1360,9 +1229,9 @@
                     (float) mChooserListAdapter.getCallerTargetCount() / mColumnCount);
         }
 
+        // There can be at most one row of service targets.
         public int getServiceTargetRowCount() {
-            return (int) Math.ceil(
-                    (float) mChooserListAdapter.getServiceTargetCount() / mColumnCount);
+            return (int) mChooserListAdapter.getServiceTargetCount() == 0 ? 0 : 1;
         }
 
         @Override
@@ -1485,8 +1354,7 @@
             }
 
             final int oldHeight = holder.row.getLayoutParams().height;
-            holder.row.getLayoutParams().height = Math.max(1,
-                    (int) (holder.measuredRowHeight * getRowScale(rowPosition)));
+            holder.row.getLayoutParams().height = Math.max(1, holder.measuredRowHeight);
             if (holder.row.getLayoutParams().height != oldHeight) {
                 holder.row.requestLayout();
             }
@@ -1728,7 +1596,7 @@
                 final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView);
                 int height = ((RowViewHolder) (v.getTag())).measuredRowHeight;
 
-                offset += (int) (height * mChooserRowAdapter.getRowScale(pos));
+                offset += (int) (height);
 
                 if (vt >= 0) {
                     mCachedViewType = vt;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 4cc91ec..c354634 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4029,8 +4029,6 @@
 
     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
         mIsolatedUids.put(isolatedUid, appUid);
-        StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, appUid, isolatedUid,
-                StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
         final Uid u = getUidStatsLocked(appUid);
         u.addIsolatedUid(isolatedUid);
     }
@@ -4054,9 +4052,6 @@
      */
     @GuardedBy("this")
     public void removeIsolatedUidLocked(int isolatedUid) {
-        StatsLog.write(
-                StatsLog.ISOLATED_UID_CHANGED, mIsolatedUids.get(isolatedUid, -1),
-                isolatedUid, StatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED);
         final int idx = mIsolatedUids.indexOfKey(isolatedUid);
         if (idx >= 0) {
             final int ownerUid = mIsolatedUids.valueAt(idx);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 9ea17d6..4697266 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -436,7 +436,7 @@
             return true;
         }
 
-        return (getViewRootImpl() != null) && getViewRootImpl().dispatchKeyFallbackEvent(event);
+        return (getViewRootImpl() != null) && getViewRootImpl().dispatchUnhandledKeyEvent(event);
     }
 
     public boolean superDispatchKeyShortcutEvent(KeyEvent event) {
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index d135040..c9a9161 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -100,7 +100,6 @@
         super.onFinishInflate();
         mMessageContainer = findViewById(R.id.group_message_container);
         mSenderName = findViewById(R.id.message_name);
-        mSenderName.addOnLayoutChangeListener(MessagingLayout.MESSAGING_PROPERTY_ANIMATOR);
         mAvatarView = findViewById(R.id.message_icon);
         mImageContainer = findViewById(R.id.messaging_group_icon_container);
         mSendingSpinner = findViewById(R.id.messaging_group_sending_progress);
@@ -190,73 +189,66 @@
     }
 
     public void removeMessage(MessagingMessage messagingMessage) {
-        ViewGroup messageParent = (ViewGroup) messagingMessage.getView().getParent();
-        messageParent.removeView(messagingMessage.getView());
+        View view = messagingMessage.getView();
+        boolean wasShown = view.isShown();
+        ViewGroup messageParent = (ViewGroup) view.getParent();
+        if (messageParent == null) {
+            return;
+        }
+        messageParent.removeView(view);
         Runnable recycleRunnable = () -> {
-            messageParent.removeTransientView(messagingMessage.getView());
+            messageParent.removeTransientView(view);
             messagingMessage.recycle();
-            if (mMessageContainer.getChildCount() == 0
-                    && mMessageContainer.getTransientViewCount() == 0
-                    && mImageContainer.getChildCount() == 0) {
-                ViewParent parent = getParent();
-                if (parent instanceof ViewGroup) {
-                    ((ViewGroup) parent).removeView(MessagingGroup.this);
-                }
-                setAvatar(null);
-                mAvatarView.setAlpha(1.0f);
-                mAvatarView.setTranslationY(0.0f);
-                mSenderName.setAlpha(1.0f);
-                mSenderName.setTranslationY(0.0f);
-                mIsolatedMessage = null;
-                mMessages = null;
-                sInstancePool.release(MessagingGroup.this);
-            }
         };
-        if (isShown()) {
-            messageParent.addTransientView(messagingMessage.getView(), 0);
-            performRemoveAnimation(messagingMessage.getView(), recycleRunnable);
-            if (mMessageContainer.getChildCount() == 0
-                    && mImageContainer.getChildCount() == 0) {
-                removeGroupAnimated(null);
-            }
+        if (wasShown && !MessagingLinearLayout.isGone(view)) {
+            messageParent.addTransientView(view, 0);
+            performRemoveAnimation(view, recycleRunnable);
         } else {
             recycleRunnable.run();
         }
-
     }
 
-    private void removeGroupAnimated(Runnable endAction) {
-        performRemoveAnimation(mAvatarView, null);
-        performRemoveAnimation(mSenderName, null);
-        boolean endActionTriggered = false;
-        for (int i = mMessageContainer.getChildCount() - 1; i >= 0; i--) {
-            View child = mMessageContainer.getChildAt(i);
-            if (child.getVisibility() == View.GONE) {
-                continue;
-            }
-            final ViewGroup.LayoutParams lp = child.getLayoutParams();
-            if (lp instanceof MessagingLinearLayout.LayoutParams
-                    && ((MessagingLinearLayout.LayoutParams) lp).hide
-                    && !((MessagingLinearLayout.LayoutParams) lp).visibleBefore) {
-                continue;
-            }
-            Runnable childEndAction = endActionTriggered ? null : endAction;
-            performRemoveAnimation(child, childEndAction);
-            endActionTriggered = true;
-        }
+    public void recycle() {
         if (mIsolatedMessage != null) {
-            performRemoveAnimation(mIsolatedMessage, !endActionTriggered ? endAction : null);
-            endActionTriggered = true;
+            mImageContainer.removeView(mIsolatedMessage);
         }
-        if (!endActionTriggered && endAction != null) {
-            endAction.run();
+        for (int i = 0; i < mMessages.size(); i++) {
+            MessagingMessage message = mMessages.get(i);
+            mMessageContainer.removeView(message.getView());
+            message.recycle();
         }
+        setAvatar(null);
+        mAvatarView.setAlpha(1.0f);
+        mAvatarView.setTranslationY(0.0f);
+        mSenderName.setAlpha(1.0f);
+        mSenderName.setTranslationY(0.0f);
+        setAlpha(1.0f);
+        mIsolatedMessage = null;
+        mMessages = null;
+        mAddedMessages.clear();
+        mFirstLayout = true;
+        MessagingPropertyAnimator.recycle(this);
+        sInstancePool.release(MessagingGroup.this);
+    }
+
+    public void removeGroupAnimated(Runnable endAction) {
+        performRemoveAnimation(this, () -> {
+            setAlpha(1.0f);
+            MessagingPropertyAnimator.setToLaidOutPosition(this);
+            if (endAction != null) {
+                endAction.run();
+            }
+        });
     }
 
     public void performRemoveAnimation(View message, Runnable endAction) {
-        MessagingPropertyAnimator.fadeOut(message, endAction);
-        MessagingPropertyAnimator.startLocalTranslationTo(message,
-                (int) (-getHeight() * 0.5f), MessagingLayout.FAST_OUT_LINEAR_IN);
+        performRemoveAnimation(message, -message.getHeight(), endAction);
+    }
+
+    private void performRemoveAnimation(View view, int disappearTranslation, Runnable endAction) {
+        MessagingPropertyAnimator.startLocalTranslationTo(view, disappearTranslation,
+                MessagingLayout.FAST_OUT_LINEAR_IN);
+        MessagingPropertyAnimator.fadeOut(view, endAction);
     }
 
     public CharSequence getSenderName() {
@@ -341,6 +333,11 @@
         }
     }
 
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
     public Icon getAvatarSymbolIfMatching(CharSequence avatarName, String avatarSymbol,
             int layoutColor) {
         if (mAvatarName.equals(avatarName) && mAvatarSymbol.equals(avatarSymbol)
@@ -458,6 +455,7 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         if (!mAddedMessages.isEmpty()) {
+            final boolean firstLayout = mFirstLayout;
             getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                 @Override
                 public boolean onPreDraw() {
@@ -466,7 +464,7 @@
                             continue;
                         }
                         MessagingPropertyAnimator.fadeIn(message.getView());
-                        if (!mFirstLayout) {
+                        if (!firstLayout) {
                             MessagingPropertyAnimator.startLocalTranslationFrom(message.getView(),
                                     message.getView().getHeight(),
                                     MessagingLayout.LINEAR_OUT_SLOW_IN);
diff --git a/core/java/com/android/internal/widget/MessagingImageMessage.java b/core/java/com/android/internal/widget/MessagingImageMessage.java
index 9db74e8..607a3a9 100644
--- a/core/java/com/android/internal/widget/MessagingImageMessage.java
+++ b/core/java/com/android/internal/widget/MessagingImageMessage.java
@@ -170,8 +170,6 @@
 
     public void recycle() {
         MessagingMessage.super.recycle();
-        setAlpha(1.0f);
-        setTranslationY(0);
         setImageBitmap(null);
         mDrawable = null;
         sInstancePool.release(this);
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index d468ce3..0fd6109 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -82,7 +82,7 @@
     private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private Paint mTextPaint = new Paint();
     private CharSequence mConversationTitle;
-    private Icon mLargeIcon;
+    private Icon mAvatarReplacement;
     private boolean mIsOneToOne;
     private ArrayList<MessagingGroup> mAddedGroups = new ArrayList<>();
     private Person mUser;
@@ -125,8 +125,8 @@
     }
 
     @RemotableViewMethod
-    public void setLargeIcon(Icon icon) {
-        mLargeIcon = icon;
+    public void setAvatarReplacement(Icon icon) {
+        mAvatarReplacement = icon;
     }
 
     @RemotableViewMethod
@@ -180,8 +180,13 @@
         List<MessagingMessage> historicMessages = createMessages(newHistoricMessages,
                 true /* isHistoric */);
         List<MessagingMessage> messages = createMessages(newMessages, false /* isHistoric */);
+
+        ArrayList<MessagingGroup> oldGroups = new ArrayList<>(mGroups);
         addMessagesToGroups(historicMessages, messages, showSpinner);
 
+        // Let's first check which groups were removed altogether and remove them in one animation
+        removeGroups(oldGroups);
+
         // Let's remove the remaining messages
         mMessages.forEach(REMOVE_MESSAGE);
         mHistoricMessages.forEach(REMOVE_MESSAGE);
@@ -193,6 +198,31 @@
         updateTitleAndNamesDisplay();
     }
 
+    private void removeGroups(ArrayList<MessagingGroup> oldGroups) {
+        int size = oldGroups.size();
+        for (int i = 0; i < size; i++) {
+            MessagingGroup group = oldGroups.get(i);
+            if (!mGroups.contains(group)) {
+                List<MessagingMessage> messages = group.getMessages();
+                Runnable endRunnable = () -> {
+                    mMessagingLinearLayout.removeTransientView(group);
+                    group.recycle();
+                };
+
+                boolean wasShown = group.isShown();
+                mMessagingLinearLayout.removeView(group);
+                if (wasShown && !MessagingLinearLayout.isGone(group)) {
+                    mMessagingLinearLayout.addTransientView(group, 0);
+                    group.removeGroupAnimated(endRunnable);
+                } else {
+                    endRunnable.run();
+                }
+                mMessages.removeAll(messages);
+                mHistoricMessages.removeAll(messages);
+            }
+        }
+    }
+
     private void updateTitleAndNamesDisplay() {
         ArrayMap<CharSequence, String> uniqueNames = new ArrayMap<>();
         ArrayMap<Character, CharSequence> uniqueCharacters = new ArrayMap<>();
@@ -228,7 +258,7 @@
             boolean isOwnMessage = group.getSender() == mUser;
             CharSequence senderName = group.getSenderName();
             if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)
-                    || (mIsOneToOne && mLargeIcon != null && !isOwnMessage)) {
+                    || (mIsOneToOne && mAvatarReplacement != null && !isOwnMessage)) {
                 continue;
             }
             String symbol = uniqueNames.get(senderName);
@@ -246,8 +276,8 @@
             if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)) {
                 continue;
             }
-            if (mIsOneToOne && mLargeIcon != null && group.getSender() != mUser) {
-                group.setAvatar(mLargeIcon);
+            if (mIsOneToOne && mAvatarReplacement != null && group.getSender() != mUser) {
+                group.setAvatar(mAvatarReplacement);
             } else {
                 Icon cachedIcon = cachedAvatars.get(senderName);
                 if (cachedIcon == null) {
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index 991e3e7..64b1f24 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -163,15 +163,6 @@
             }
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             MessagingChild messagingChild = (MessagingChild) child;
-            if (lp.hide) {
-                if (shown && lp.visibleBefore) {
-                    messagingChild.hideAnimated();
-                }
-                lp.visibleBefore = false;
-                continue;
-            } else {
-                lp.visibleBefore = true;
-            }
 
             final int childWidth = child.getMeasuredWidth();
             final int childHeight = child.getMeasuredHeight();
@@ -182,6 +173,19 @@
             } else {
                 childLeft = paddingLeft + lp.leftMargin;
             }
+            if (lp.hide) {
+                if (shown && lp.visibleBefore) {
+                    // We still want to lay out the child to have great animations
+                    child.layout(childLeft, childTop, childLeft + childWidth,
+                            childTop + lp.lastVisibleHeight);
+                    messagingChild.hideAnimated();
+                }
+                lp.visibleBefore = false;
+                continue;
+            } else {
+                lp.visibleBefore = true;
+                lp.lastVisibleHeight = childHeight;
+            }
 
             if (!first) {
                 childTop += mSpacing;
@@ -228,6 +232,18 @@
         return copy;
     }
 
+    public static boolean isGone(View view) {
+        if (view.getVisibility() == View.GONE) {
+            return true;
+        }
+        final ViewGroup.LayoutParams lp = view.getLayoutParams();
+        if (lp instanceof MessagingLinearLayout.LayoutParams
+                && ((MessagingLinearLayout.LayoutParams) lp).hide) {
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Sets how many lines should be displayed at most
      */
@@ -263,6 +279,7 @@
 
         public boolean hide = false;
         public boolean visibleBefore = false;
+        public int lastVisibleHeight;
 
         public LayoutParams(Context c, AttributeSet attrs) {
             super(c, attrs);
diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java
index ffcb503..74d0aae 100644
--- a/core/java/com/android/internal/widget/MessagingMessage.java
+++ b/core/java/com/android/internal/widget/MessagingMessage.java
@@ -124,8 +124,7 @@
     @Override
     default void hideAnimated() {
         setIsHidingAnimated(true);
-        getGroup().performRemoveAnimation(getState().getHostView(),
-                () -> setIsHidingAnimated(false));
+        getGroup().performRemoveAnimation(getView(), () -> setIsHidingAnimated(false));
     }
 
     default boolean hasOverlappingRendering() {
@@ -133,7 +132,7 @@
     }
 
     default void recycle() {
-        getState().reset();
+        getState().recycle();
     }
 
     default View getView() {
diff --git a/core/java/com/android/internal/widget/MessagingMessageState.java b/core/java/com/android/internal/widget/MessagingMessageState.java
index ac62472..1ba2b51 100644
--- a/core/java/com/android/internal/widget/MessagingMessageState.java
+++ b/core/java/com/android/internal/widget/MessagingMessageState.java
@@ -72,7 +72,10 @@
         return mHostView;
     }
 
-    public void reset() {
+    public void recycle() {
+        mHostView.setAlpha(1.0f);
+        mHostView.setTranslationY(0);
+        MessagingPropertyAnimator.recycle(mHostView);
         mIsHidingAnimated = false;
         mIsHistoric = false;
         mGroup = null;
diff --git a/core/java/com/android/internal/widget/MessagingPropertyAnimator.java b/core/java/com/android/internal/widget/MessagingPropertyAnimator.java
index 7c3ab7f..7703cb0 100644
--- a/core/java/com/android/internal/widget/MessagingPropertyAnimator.java
+++ b/core/java/com/android/internal/widget/MessagingPropertyAnimator.java
@@ -31,111 +31,125 @@
  * A listener that automatically starts animations when the layout bounds change.
  */
 public class MessagingPropertyAnimator implements View.OnLayoutChangeListener {
-    static final long APPEAR_ANIMATION_LENGTH = 210;
+    private static final long APPEAR_ANIMATION_LENGTH = 210;
     private static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
     public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
-    private static final int TAG_LOCAL_TRANSLATION_ANIMATOR = R.id.tag_local_translation_y_animator;
-    private static final int TAG_LOCAL_TRANSLATION_Y = R.id.tag_local_translation_y;
+    private static final int TAG_TOP_ANIMATOR = R.id.tag_top_animator;
+    private static final int TAG_TOP = R.id.tag_top_override;
     private static final int TAG_LAYOUT_TOP = R.id.tag_layout_top;
+    private static final int TAG_FIRST_LAYOUT = R.id.tag_is_first_layout;
     private static final int TAG_ALPHA_ANIMATOR = R.id.tag_alpha_animator;
     private static final ViewClippingUtil.ClippingParameters CLIPPING_PARAMETERS =
             view -> view.getId() == com.android.internal.R.id.notification_messaging;
-    private static final IntProperty<View> LOCAL_TRANSLATION_Y =
-            new IntProperty<View>("localTranslationY") {
+    private static final IntProperty<View> TOP =
+            new IntProperty<View>("top") {
                 @Override
                 public void setValue(View object, int value) {
-                    setLocalTranslationY(object, value);
+                    setTop(object, value);
                 }
 
                 @Override
                 public Integer get(View object) {
-                    return getLocalTranslationY(object);
+                    return getTop(object);
                 }
             };
 
     @Override
     public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
             int oldTop, int oldRight, int oldBottom) {
-        int oldHeight = oldBottom - oldTop;
-        Integer layoutTop = (Integer) v.getTag(TAG_LAYOUT_TOP);
-        if (layoutTop != null) {
-            oldTop = layoutTop;
-        }
-        int topChange = oldTop - top;
-        if (oldHeight == 0 || topChange == 0 || !v.isShown() || isGone(v)) {
-            // First layout
+        setLayoutTop(v, top);
+        if (isFirstLayout(v)) {
+            setFirstLayout(v, false /* first */);
+            setTop(v, top);
             return;
         }
-        if (layoutTop != null) {
-            v.setTagInternal(TAG_LAYOUT_TOP, top);
-        }
-        int newHeight = bottom - top;
-        int heightDifference = oldHeight - newHeight;
-        // Only add the difference if the height changes and it's getting smaller
-        heightDifference = Math.max(heightDifference, 0);
-        startLocalTranslationFrom(v, topChange + heightDifference + getLocalTranslationY(v));
+        startTopAnimation(v, getTop(v), top, MessagingLayout.FAST_OUT_SLOW_IN);
     }
 
-    private boolean isGone(View view) {
-        if (view.getVisibility() == View.GONE) {
-            return true;
-        }
-        final ViewGroup.LayoutParams lp = view.getLayoutParams();
-        if (lp instanceof MessagingLinearLayout.LayoutParams
-                && ((MessagingLinearLayout.LayoutParams) lp).hide) {
-            return true;
-        }
-        return false;
-    }
-
-    public static void startLocalTranslationFrom(View v, int startTranslation) {
-        startLocalTranslationFrom(v, startTranslation, MessagingLayout.FAST_OUT_SLOW_IN);
-    }
-
-    public static void startLocalTranslationFrom(View v, int startTranslation,
-            Interpolator interpolator) {
-        startLocalTranslation(v, startTranslation, 0, interpolator);
-    }
-
-    public static void startLocalTranslationTo(View v, int endTranslation,
-            Interpolator interpolator) {
-        startLocalTranslation(v, getLocalTranslationY(v), endTranslation, interpolator);
-    }
-
-    public static int getLocalTranslationY(View v) {
-        Integer tag = (Integer) v.getTag(TAG_LOCAL_TRANSLATION_Y);
+    private static boolean isFirstLayout(View view) {
+        Boolean tag = (Boolean) view.getTag(TAG_FIRST_LAYOUT);
         if (tag == null) {
-            return 0;
+            return true;
         }
         return tag;
     }
 
-    private static void setLocalTranslationY(View v, int value) {
-        v.setTagInternal(TAG_LOCAL_TRANSLATION_Y, value);
+    public static void recycle(View view) {
+        setFirstLayout(view, true /* first */);
+    }
+
+    private static void setFirstLayout(View view, boolean first) {
+        view.setTagInternal(TAG_FIRST_LAYOUT, first);
+    }
+
+    private static void setLayoutTop(View view, int top) {
+        view.setTagInternal(TAG_LAYOUT_TOP, top);
+    }
+
+    public static int getLayoutTop(View view) {
+        Integer tag = (Integer) view.getTag(TAG_LAYOUT_TOP);
+        if (tag == null) {
+            return getTop(view);
+        }
+        return tag;
+    }
+
+    /**
+     * Start a translation animation from a start offset to the laid out location
+     * @param view The view to animate
+     * @param startTranslation The starting translation to start from.
+     * @param interpolator The interpolator to use.
+     */
+    public static void startLocalTranslationFrom(View view, int startTranslation,
+            Interpolator interpolator) {
+        startTopAnimation(view, getTop(view) + startTranslation, getLayoutTop(view), interpolator);
+    }
+
+    /**
+     * Start a translation animation from a start offset to the laid out location
+     * @param view The view to animate
+     * @param endTranslation The end translation to go to.
+     * @param interpolator The interpolator to use.
+     */
+    public static void startLocalTranslationTo(View view, int endTranslation,
+            Interpolator interpolator) {
+        int top = getTop(view);
+        startTopAnimation(view, top, top + endTranslation, interpolator);
+    }
+
+    public static int getTop(View v) {
+        Integer tag = (Integer) v.getTag(TAG_TOP);
+        if (tag == null) {
+            return v.getTop();
+        }
+        return tag;
+    }
+
+    private static void setTop(View v, int value) {
+        v.setTagInternal(TAG_TOP, value);
         updateTopAndBottom(v);
     }
 
     private static void updateTopAndBottom(View v) {
-        int layoutTop = (int) v.getTag(TAG_LAYOUT_TOP);
-        int localTranslation = getLocalTranslationY(v);
+        int top = getTop(v);
         int height = v.getHeight();
-        v.setTop(layoutTop + localTranslation);
-        v.setBottom(layoutTop + height + localTranslation);
+        v.setTop(top);
+        v.setBottom(height + top);
     }
 
-    private static void startLocalTranslation(final View v, int start, int end,
+    private static void startTopAnimation(final View v, int start, int end,
             Interpolator interpolator) {
-        ObjectAnimator existing = (ObjectAnimator) v.getTag(TAG_LOCAL_TRANSLATION_ANIMATOR);
+        ObjectAnimator existing = (ObjectAnimator) v.getTag(TAG_TOP_ANIMATOR);
         if (existing != null) {
             existing.cancel();
         }
-        ObjectAnimator animator = ObjectAnimator.ofInt(v, LOCAL_TRANSLATION_Y, start, end);
-        Integer layoutTop = (Integer) v.getTag(TAG_LAYOUT_TOP);
-        if (layoutTop == null) {
-            layoutTop = v.getTop();
-            v.setTagInternal(TAG_LAYOUT_TOP, layoutTop);
+        if (!v.isShown() || start == end
+                || (MessagingLinearLayout.isGone(v) && !isHidingAnimated(v))) {
+            setTop(v, end);
+            return;
         }
-        setLocalTranslationY(v, start);
+        ObjectAnimator animator = ObjectAnimator.ofInt(v, TOP, start, end);
+        setTop(v, start);
         animator.setInterpolator(interpolator);
         animator.setDuration(APPEAR_ANIMATION_LENGTH);
         animator.addListener(new AnimatorListenerAdapter() {
@@ -143,12 +157,8 @@
 
             @Override
             public void onAnimationEnd(Animator animation) {
-                v.setTagInternal(TAG_LOCAL_TRANSLATION_ANIMATOR, null);
+                v.setTagInternal(TAG_TOP_ANIMATOR, null);
                 setClippingDeactivated(v, false);
-                if (!mCancelled) {
-                    setLocalTranslationY(v, 0);
-                    v.setTagInternal(TAG_LAYOUT_TOP, null);
-                }
             }
 
             @Override
@@ -157,10 +167,17 @@
             }
         });
         setClippingDeactivated(v, true);
-        v.setTagInternal(TAG_LOCAL_TRANSLATION_ANIMATOR, animator);
+        v.setTagInternal(TAG_TOP_ANIMATOR, animator);
         animator.start();
     }
 
+    private static boolean isHidingAnimated(View v) {
+        if (v instanceof MessagingLinearLayout.MessagingChild) {
+            return ((MessagingLinearLayout.MessagingChild) v).isHidingAnimated();
+        }
+        return false;
+    }
+
     public static void fadeIn(final View v) {
         ObjectAnimator existing = (ObjectAnimator) v.getTag(TAG_ALPHA_ANIMATOR);
         if (existing != null) {
@@ -199,6 +216,13 @@
         if (existing != null) {
             existing.cancel();
         }
+        if (!view.isShown() || (MessagingLinearLayout.isGone(view) && !isHidingAnimated(view))) {
+            view.setAlpha(0.0f);
+            if (endAction != null) {
+                endAction.run();
+            }
+            return;
+        }
         ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.ALPHA,
                 view.getAlpha(), 0.0f);
         animator.setInterpolator(ALPHA_OUT);
@@ -224,10 +248,14 @@
     }
 
     public static boolean isAnimatingTranslation(View v) {
-        return v.getTag(TAG_LOCAL_TRANSLATION_ANIMATOR) != null;
+        return v.getTag(TAG_TOP_ANIMATOR) != null;
     }
 
     public static boolean isAnimatingAlpha(View v) {
         return v.getTag(TAG_ALPHA_ANIMATOR) != null;
     }
+
+    public static void setToLaidOutPosition(View view) {
+        setTop(view, getLayoutTop(view));
+    }
 }
diff --git a/core/java/com/android/internal/widget/MessagingTextMessage.java b/core/java/com/android/internal/widget/MessagingTextMessage.java
index 219116e..4081a86 100644
--- a/core/java/com/android/internal/widget/MessagingTextMessage.java
+++ b/core/java/com/android/internal/widget/MessagingTextMessage.java
@@ -92,8 +92,6 @@
 
     public void recycle() {
         MessagingMessage.super.recycle();
-        setAlpha(1.0f);
-        setTranslationY(0);
         sInstancePool.release(this);
     }
 
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 7352324..e5aea97 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -62,7 +62,7 @@
     }
 
     bool valid() {
-        return mBitmap;
+        return mBitmap != nullptr;
     }
 
     Bitmap& bitmap() {
@@ -851,10 +851,9 @@
     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
 }
 
-static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
+static void Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
     LocalScopedBitmap bitmap(bitmapHandle);
     bitmap->freePixels();
-    return JNI_TRUE;
 }
 
 static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
@@ -1600,7 +1599,7 @@
     {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
         (void*)Bitmap_copyAshmemConfig },
     {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
-    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
+    {   "nativeRecycle",            "(J)V", (void*)Bitmap_recycle },
     {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
     {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
         (void*)Bitmap_compress },
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index c7ad2a4..fb571df 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -44,9 +44,9 @@
 
 struct NativeFamilyBuilder {
     NativeFamilyBuilder(uint32_t langId, int variant)
-        : langId(langId), variant(static_cast<minikin::FontFamily::Variant>(variant)) {}
+        : langId(langId), variant(static_cast<minikin::FamilyVariant>(variant)) {}
     uint32_t langId;
-    minikin::FontFamily::Variant variant;
+    minikin::FamilyVariant variant;
     std::vector<minikin::Font> fonts;
     std::vector<minikin::FontVariation> axes;
 };
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 0933e98..5d65aee 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -355,11 +355,6 @@
     bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
 }
 
-SkPixelRef* GraphicsJNI::refSkPixelRef(JNIEnv* env, jobject jbitmap) {
-    android::Bitmap& bitmap = android::bitmap::toBitmap(env, jbitmap);
-    bitmap.ref();
-    return &bitmap;
-}
 SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) {
     ALOG_ASSERT(env);
     if (NULL == jconfig) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index dcb81fa..7825f1d 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -63,7 +63,6 @@
 
     static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
     static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
-    static SkPixelRef* refSkPixelRef(JNIEnv*, jobject bitmap);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
 
     /*
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index e9c2e7a..d391de7 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -44,6 +44,7 @@
 #include <minikin/GraphemeBreak.h>
 #include <minikin/LocaleList.h>
 #include <minikin/Measurement.h>
+#include <minikin/MinikinPaint.h>
 #include <unicode/utf16.h>
 
 #include <cassert>
@@ -594,7 +595,7 @@
         // restore the original settings.
         paint->setTextSkewX(saveSkewX);
         paint->setFakeBoldText(savefakeBold);
-        if (paint->getFamilyVariant() == minikin::FontFamily::Variant::ELEGANT) {
+        if (paint->getFamilyVariant() == minikin::FamilyVariant::ELEGANT) {
             SkScalar size = paint->getTextSize();
             metrics->fTop = -size * kElegantTop / 2048;
             metrics->fBottom = -size * kElegantBottom / 2048;
@@ -893,13 +894,13 @@
 
     static jboolean isElegantTextHeight(jlong paintHandle) {
         Paint* obj = reinterpret_cast<Paint*>(paintHandle);
-        return obj->getFamilyVariant() == minikin::FontFamily::Variant::ELEGANT;
+        return obj->getFamilyVariant() == minikin::FamilyVariant::ELEGANT;
     }
 
     static void setElegantTextHeight(jlong paintHandle, jboolean aa) {
         Paint* obj = reinterpret_cast<Paint*>(paintHandle);
         obj->setFamilyVariant(
-                aa ? minikin::FontFamily::Variant::ELEGANT : minikin::FontFamily::Variant::DEFAULT);
+                aa ? minikin::FamilyVariant::ELEGANT : minikin::FamilyVariant::DEFAULT);
     }
 
     static jfloat getTextSize(jlong paintHandle) {
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 418e15b..9d24588 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -117,6 +117,7 @@
     optional bool visible = 4;
     optional bool front_of_task = 5;
     optional int32 proc_id = 6;
+    optional bool translucent = 7;
 }
 
 message KeyguardControllerProto {
diff --git a/core/proto/android/server/forceappstandbytracker.proto b/core/proto/android/server/forceappstandbytracker.proto
index 1113d6a..8c71b0b 100644
--- a/core/proto/android/server/forceappstandbytracker.proto
+++ b/core/proto/android/server/forceappstandbytracker.proto
@@ -25,7 +25,7 @@
 
 // Dump from com.android.server.ForceAppStandbyTracker.
 //
-// Next ID: 12
+// Next ID: 13
 message ForceAppStandbyTrackerProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -41,6 +41,9 @@
     // App ids that are in power-save whitelist.
     repeated int32 power_save_whitelist_app_ids = 3;
 
+    // App ids that are in power-save user whitelist.
+    repeated int32 power_save_user_whitelist_app_ids = 12;
+
     // App ids that are in temporary power-save whitelist.
     repeated int32 temp_power_save_whitelist_app_ids = 4;
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ee54ee1..1b41f99 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -850,7 +850,7 @@
 
     <!-- Used for permissions that are associated telephony features. -->
     <permission-group android:name="android.permission-group.CALL_LOG"
-        android:icon="@drawable/perm_group_phone_calls"
+        android:icon="@drawable/perm_group_call_log"
         android:label="@string/permgrouplab_calllog"
         android:description="@string/permgroupdesc_calllog"
         android:request="@string/permgrouprequest_calllog"
diff --git a/core/res/res/drawable/ic_arrow_forward.xml b/core/res/res/drawable/ic_arrow_forward.xml
new file mode 100644
index 0000000..f108570
--- /dev/null
+++ b/core/res/res/drawable/ic_arrow_forward.xml
@@ -0,0 +1,24 @@
+<!--
+    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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12.0,4.0l-1.41,1.41L16.17,11.0L4.0,11.0l0.0,2.0l12.17,0.0l-5.58,5.59L12.0,20.0l8.0,-8.0z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_permission.xml b/core/res/res/drawable/ic_permission.xml
new file mode 100644
index 0000000..0052350
--- /dev/null
+++ b/core/res/res/drawable/ic_permission.xml
@@ -0,0 +1,26 @@
+<!--
+    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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="16.0"
+        android:viewportHeight="16.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="
+        M9.0,12l-2.0,0.0l0.0,-2.0l2.0,0.0l0.0,2.0z
+        m0.0,-4.0l-2.0,0.0l0.0,-4.0l2.0,0.0l0.0,4.0z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_call_log.xml b/core/res/res/drawable/perm_group_call_log.xml
new file mode 100644
index 0000000..0dfdbee
--- /dev/null
+++ b/core/res/res/drawable/perm_group_call_log.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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#000000"
+        android:pathData="M16.01,14.48l-2.62,2.62c-2.75,-1.49 -5.01,-3.75 -6.5,-6.5l2.62,-2.62c0.24,-0.24 0.34,-0.58 0.27,-0.9L9.13,3.82c-0.09,-0.47 -0.5,-0.8 -0.98,-0.8L4,3.01c-0.56,0 -1.03,0.47 -1,1.03c0.17,2.91 1.04,5.63 2.43,8.01c1.57,2.69 3.81,4.93 6.5,6.5c2.38,1.39 5.1,2.26 8.01,2.43c0.56,0.03 1.03,-0.44 1.03,-1v-4.15c0,-0.48 -0.34,-0.89 -0.8,-0.98l-3.26,-0.65C16.58,14.14 16.24,14.24 16.01,14.48z"/>
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,8h10V6H12V8zM12,4h10V2H12V4zM22,10H12v2h10V10z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_camera.xml b/core/res/res/drawable/perm_group_camera.xml
index 61903a5..db7833f 100644
--- a/core/res/res/drawable/perm_group_camera.xml
+++ b/core/res/res/drawable/perm_group_camera.xml
@@ -22,10 +22,8 @@
 
     <path
         android:fillColor="#000000"
-        android:pathData="M 12 8.8 C 13.7673111995 8.8 15.2 10.2326888005 15.2 12 C 15.2 13.7673111995 13.7673111995 15.2 12 15.2 C 10.2326888005 15.2 8.8 13.7673111995 8.8 12 C 8.8 10.2326888005 10.2326888005 8.8 12 8.8 Z" />
+        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,19H4V7h16V19z"/>
     <path
         android:fillColor="#000000"
-        android:pathData="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1 0 2-.9
-2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5
-5-2.24 5-5 5z" />
-</vector>
\ No newline at end of file
+        android:pathData="M12,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>
diff --git a/core/res/res/drawable/perm_group_contacts.xml b/core/res/res/drawable/perm_group_contacts.xml
index 8f9dc3e..b834a27 100644
--- a/core/res/res/drawable/perm_group_contacts.xml
+++ b/core/res/res/drawable/perm_group_contacts.xml
@@ -22,8 +22,14 @@
 
     <path
         android:fillColor="#000000"
-        android:pathData="M20 0H4v2h16V0zM4 24h16v-2H4v2zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1
-0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 2.75c1.24 0 2.25 1.01 2.25 2.25s-1.01 2.25-2.25
-2.25S9.75 10.24 9.75 9 10.76 6.75 12 6.75zM17 17H7v-1.5c0-1.67 3.33-2.5 5-2.5s5
-.83 5 2.5V17z" />
-</vector>
\ No newline at end of file
+        android:pathData="M4,1h16v2h-16z"/>
+    <path
+        android:fillColor="#000000"
+        android:pathData="M4,21h16v2h-16z"/>
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20,5H4C2.9,5 2,5.9 2,7v10c0,1.1 0.9,2 2,2h2h12h2c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM8.21,17c0.7,-0.47 2.46,-1 3.79,-1s3.09,0.53 3.79,1H8.21zM20,17h-2c0,-1.99 -4,-3 -6,-3s-6,1.01 -6,3H4V7h16V17z"/>
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,13.5c1.66,0 3,-1.34 3,-3c0,-1.66 -1.34,-3 -3,-3s-3,1.34 -3,3C9,12.16 10.34,13.5 12,13.5zM12,9.5c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S11.45,9.5 12,9.5z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_location.xml b/core/res/res/drawable/perm_group_location.xml
index cc1ec90..a7fa524 100644
--- a/core/res/res/drawable/perm_group_location.xml
+++ b/core/res/res/drawable/perm_group_location.xml
@@ -22,6 +22,8 @@
 
     <path
         android:fillColor="#000000"
-        android:pathData="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0
-9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
-</vector>
\ No newline at end of file
+        android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_microphone.xml b/core/res/res/drawable/perm_group_microphone.xml
index d494e67..9b532c1 100644
--- a/core/res/res/drawable/perm_group_microphone.xml
+++ b/core/res/res/drawable/perm_group_microphone.xml
@@ -22,7 +22,8 @@
 
     <path
         android:fillColor="#000000"
-        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 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6
-6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z" />
-</vector>
\ No newline at end of file
+        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="#000000"
+        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/core/res/res/drawable/perm_group_sms.xml b/core/res/res/drawable/perm_group_sms.xml
index 47bca19e..ebcf3d1 100644
--- a/core/res/res/drawable/perm_group_sms.xml
+++ b/core/res/res/drawable/perm_group_sms.xml
@@ -22,6 +22,5 @@
 
     <path
         android:fillColor="#000000"
-        android:pathData="M20 2H4c-1.1 0-1.99 .9 -1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9
-11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z" />
-</vector>
\ No newline at end of file
+        android:pathData="M20,2H4C2.9,2 2,2.9 2,4v18l4.75,-4h14C21.1,18 22,17.1 22,16V4C22,2.9 21.1,2 20,2zM20,16H4V4h16V16zM9,11H7V9h2V11zM17,11h-2V9h2V11zM13,11h-2V9h2V11z"/>
+</vector>
diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml
index 1ff1693..4b8965b 100644
--- a/core/res/res/drawable/perm_group_storage.xml
+++ b/core/res/res/drawable/perm_group_storage.xml
@@ -22,6 +22,5 @@
 
     <path
         android:fillColor="#000000"
-        android:pathData="M10 4H4c-1.1 0-1.99 .9 -1.99 2L2 18c0 1.1 .9 2 2 2h16c1.1 0 2-.9
-2-2V8c0-1.1-.9-2-2-2h-8l-2-2z" />
-</vector>
\ No newline at end of file
+        android:pathData="M20,6h-8l-2,-2H4C2.9,4 2.01,4.9 2.01,6L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8C22,6.9 21.1,6 20,6zM20,18H4V8h16V18z"/>
+</vector>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b0ecb3e..c856ed8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1108,6 +1108,15 @@
     <string-array translatable="false" name="config_ringtoneEffectUris">
     </string-array>
 
+    <!-- The default intensity level for haptic feedback. See
+         Settings.System.HAPTIC_FEEDBACK_INTENSITY more details on the constant values and
+         meanings. -->
+    <integer name="config_defaultHapticFeedbackIntensity">2</integer>
+    <!-- The default intensity level for notification vibrations. See
+         Settings.System.NOTIFICATION_VIBRATION_INTENSITY more details on the constant values and
+         meanings. -->
+    <integer name="config_defaultNotificationVibrationIntensity">2</integer>
+
     <bool name="config_use_strict_phone_number_comparation">false</bool>
 
     <!-- Display low battery warning when battery level dips to this value.
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 47d04ed..bf7e068 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -140,15 +140,18 @@
   <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_MOVE_WINDOW}. -->
   <item type="id" name="accessibilityActionMoveWindow" />
 
-  <!-- A tag used to save an animator in local y translation -->
-  <item type="id" name="tag_local_translation_y_animator" />
+  <!-- A tag used to save an animator in top -->
+  <item type="id" name="tag_top_animator" />
 
-  <!-- A tag used to save the local translation y -->
-  <item type="id" name="tag_local_translation_y" />
+  <!-- A tag used to save the current top override -->
+  <item type="id" name="tag_top_override" />
 
   <!-- A tag used to save the original top of a view -->
   <item type="id" name="tag_layout_top" />
 
+  <!-- A tag used to save whether a view was laid out before -->
+  <item type="id" name="tag_is_first_layout" />
+
   <!-- A tag used to save an animator in alpha -->
   <item type="id" name="tag_alpha_animator" />
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3c5159c..8f469b0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3362,7 +3362,7 @@
     <string name="locale_replacement">""</string>
 
     <!-- Title of the pop-up dialog in which the user switches keyboard, also known as input method. -->
-    <string name="select_input_method">Change keyboard</string>
+    <string name="select_input_method">Choose input method</string>
     <!-- Summary text of a toggle switch to enable/disable use of the IME while a physical
          keyboard is connected -->
     <string name="show_ime">Keep it on screen while physical keyboard is active</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 42aad6a..833228b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3260,9 +3260,10 @@
   <java-symbol type="id" name="message_name" />
   <java-symbol type="id" name="message_icon" />
   <java-symbol type="id" name="group_message_container" />
-  <java-symbol type="id" name="tag_local_translation_y_animator" />
-  <java-symbol type="id" name="tag_local_translation_y" />
+  <java-symbol type="id" name="tag_top_animator" />
+  <java-symbol type="id" name="tag_top_override" />
   <java-symbol type="id" name="tag_layout_top" />
+  <java-symbol type="id" name="tag_is_first_layout" />
   <java-symbol type="id" name="tag_alpha_animator" />
   <java-symbol type="id" name="clip_children_set_tag" />
   <java-symbol type="id" name="clip_to_padding_tag" />
@@ -3389,4 +3390,9 @@
   <java-symbol type="attr" name="opticalInsetBottom" />
 
   <java-symbol type="drawable" name="ic_lock_lockdown" />
+  <java-symbol type="drawable" name="ic_arrow_forward" />
+  <java-symbol type="drawable" name="ic_permission" />
+
+  <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" />
+  <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" />
 </resources>
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
new file mode 100644
index 0000000..c8e46fc
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.view;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ViewRootImplTest {
+
+    private Context mContext;
+    private ViewRootImplAccessor mViewRootImpl;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            mViewRootImpl = new ViewRootImplAccessor(
+                    new ViewRootImpl(mContext, mContext.getDisplay()));
+        });
+    }
+
+    @Test
+    public void negativeInsets_areSetToZero() throws Exception {
+        mViewRootImpl.getAttachInfo().getContentInsets().set(-10, -20, -30 , -40);
+        mViewRootImpl.getAttachInfo().getStableInsets().set(-10, -20, -30 , -40);
+        final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
+
+        assertThat(insets.getSystemWindowInsets(), equalTo(new Rect()));
+        assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+                insets.getStableInsetRight(), insets.getStableInsetBottom()), equalTo(new Rect()));
+    }
+
+    @Test
+    public void negativeInsets_areSetToZero_positiveAreLeftAsIs() throws Exception {
+        mViewRootImpl.getAttachInfo().getContentInsets().set(-10, 20, -30 , 40);
+        mViewRootImpl.getAttachInfo().getStableInsets().set(10, -20, 30 , -40);
+        final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
+
+        assertThat(insets.getSystemWindowInsets(), equalTo(new Rect(0, 20, 0, 40)));
+        assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+                insets.getStableInsetRight(), insets.getStableInsetBottom()),
+                equalTo(new Rect(10, 0, 30, 0)));
+    }
+
+    @Test
+    public void positiveInsets_areLeftAsIs() throws Exception {
+        mViewRootImpl.getAttachInfo().getContentInsets().set(10, 20, 30 , 40);
+        mViewRootImpl.getAttachInfo().getStableInsets().set(10, 20, 30 , 40);
+        final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
+
+        assertThat(insets.getSystemWindowInsets(), equalTo(new Rect(10, 20, 30, 40)));
+        assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+                insets.getStableInsetRight(), insets.getStableInsetBottom()),
+                equalTo(new Rect(10, 20, 30, 40)));
+    }
+
+    private static class ViewRootImplAccessor {
+
+        private final ViewRootImpl mViewRootImpl;
+
+        ViewRootImplAccessor(ViewRootImpl viewRootImpl) {
+            mViewRootImpl = viewRootImpl;
+        }
+
+        public ViewRootImpl get() {
+            return mViewRootImpl;
+        }
+
+        AttachInfoAccessor getAttachInfo() throws Exception {
+            return new AttachInfoAccessor(
+                    getField(mViewRootImpl, ViewRootImpl.class.getDeclaredField("mAttachInfo")));
+        }
+
+        WindowInsets getWindowInsets(boolean forceConstruct) throws Exception {
+            return (WindowInsets) invokeMethod(mViewRootImpl,
+                    ViewRootImpl.class.getDeclaredMethod("getWindowInsets", boolean.class),
+                    forceConstruct);
+        }
+
+        class AttachInfoAccessor {
+
+            private final Class<?> mClass;
+            private final Object mAttachInfo;
+
+            AttachInfoAccessor(Object attachInfo) throws Exception {
+                mAttachInfo = attachInfo;
+                mClass = ViewRootImpl.class.getClassLoader().loadClass(
+                        "android.view.View$AttachInfo");
+            }
+
+            Rect getContentInsets() throws Exception {
+                return (Rect) getField(mAttachInfo, mClass.getDeclaredField("mContentInsets"));
+            }
+
+            Rect getStableInsets() throws Exception {
+                return (Rect) getField(mAttachInfo, mClass.getDeclaredField("mStableInsets"));
+            }
+        }
+
+        private static Object getField(Object o, Field field) throws Exception {
+            field.setAccessible(true);
+            return field.get(o);
+        }
+
+        private static Object invokeMethod(Object o, Method method, Object... args)
+                throws Exception {
+            method.setAccessible(true);
+            return method.invoke(o, args);
+        }
+    }
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index a6cbd49..df84a4c 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -186,8 +186,6 @@
             file="/system/framework/android.test.mock.jar" />
     <library name="android.test.runner"
             file="/system/framework/android.test.runner.jar" />
-    <library name="javax.obex"
-            file="/system/framework/javax.obex.jar" />
 
     <!-- These are the standard packages that are white-listed to always have internet
          access while in power save mode, even if they aren't in the foreground. -->
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index d6c119f..0ff958f 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -344,14 +344,9 @@
      * there are no more references to this bitmap.
      */
     public void recycle() {
-        if (!mRecycled && mNativePtr != 0) {
-            if (nativeRecycle(mNativePtr)) {
-                // return value indicates whether native pixel object was actually recycled.
-                // false indicates that it is still in use at the native level and these
-                // objects should not be collected now. They will be collected later when the
-                // Bitmap itself is collected.
-                mNinePatchChunk = null;
-            }
+        if (!mRecycled) {
+            nativeRecycle(mNativePtr);
+            mNinePatchChunk = null;
             mRecycled = true;
         }
     }
@@ -2052,7 +2047,7 @@
     private static native Bitmap nativeCopyAshmem(long nativeSrcBitmap);
     private static native Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig);
     private static native long nativeGetNativeFinalizer();
-    private static native boolean nativeRecycle(long nativeBitmap);
+    private static native void nativeRecycle(long nativeBitmap);
     private static native void nativeReconfigure(long nativeBitmap, int width, int height,
                                                  int config, boolean isPremultiplied);
 
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index a52263c..0022c93 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -22,6 +22,11 @@
 #include <SkTypeface.h>
 #include <log/log.h>
 
+#include <minikin/Font.h>
+#include <minikin/MinikinExtent.h>
+#include <minikin/MinikinPaint.h>
+#include <minikin/MinikinRect.h>
+
 namespace android {
 
 MinikinFontSkia::MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontData, size_t fontSize,
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index 002f759..31d3c0d 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -25,6 +25,7 @@
 #include <string>
 
 #include <minikin/FontFamily.h>
+#include <minikin/FamilyVariant.h>
 
 namespace android {
 
@@ -73,9 +74,9 @@
 
     uint32_t getMinikinLocaleListId() const { return mMinikinLocaleListId; }
 
-    void setFamilyVariant(minikin::FontFamily::Variant variant) { mFamilyVariant = variant; }
+    void setFamilyVariant(minikin::FamilyVariant variant) { mFamilyVariant = variant; }
 
-    minikin::FontFamily::Variant getFamilyVariant() const { return mFamilyVariant; }
+    minikin::FamilyVariant getFamilyVariant() const { return mFamilyVariant; }
 
     void setHyphenEdit(uint32_t hyphen) { mHyphenEdit = hyphen; }
 
@@ -90,7 +91,7 @@
     float mWordSpacing = 0;
     std::string mFontFeatureSettings;
     uint32_t mMinikinLocaleListId;
-    minikin::FontFamily::Variant mFamilyVariant;
+    minikin::FamilyVariant mFamilyVariant;
     uint32_t mHyphenEdit = 0;
     // The native Typeface object has the same lifetime of the Java Typeface
     // object. The Java Paint object holds a strong reference to the Java Typeface
diff --git a/libs/hwui/hwui/PaintImpl.cpp b/libs/hwui/hwui/PaintImpl.cpp
index ae9c475..29cc890 100644
--- a/libs/hwui/hwui/PaintImpl.cpp
+++ b/libs/hwui/hwui/PaintImpl.cpp
@@ -24,7 +24,7 @@
         , mWordSpacing(0)
         , mFontFeatureSettings()
         , mMinikinLocaleListId(0)
-        , mFamilyVariant(minikin::FontFamily::Variant::DEFAULT) {}
+        , mFamilyVariant(minikin::FamilyVariant::DEFAULT) {}
 
 Paint::Paint(const Paint& paint)
         : SkPaint(paint)
@@ -42,7 +42,7 @@
         , mWordSpacing(0)
         , mFontFeatureSettings()
         , mMinikinLocaleListId(0)
-        , mFamilyVariant(minikin::FontFamily::Variant::DEFAULT) {}
+        , mFamilyVariant(minikin::FamilyVariant::DEFAULT) {}
 
 Paint::~Paint() {}
 
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 00ba7130..14d31b2 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -114,7 +114,7 @@
         }
     }
 
-    return layerImage;
+    return layerImage != nullptr;
 }
 
 };  // namespace skiapipeline
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 02bf4e3..2207a2a 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2545,6 +2545,10 @@
             pattern = newPattern;
         }
 
+        private void setPattern(int blocksToEncrypt, int blocksToSkip) {
+            pattern = new Pattern(blocksToEncrypt, blocksToSkip);
+        }
+
         @Override
         public String toString() {
             StringBuilder builder = new StringBuilder();
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index a855526..15957c6 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -52,6 +52,7 @@
     jfieldID context;
 
     jmethodID cryptoInfoSetID;
+    jmethodID cryptoInfoSetPatternID;
 };
 
 static fields_t gFields;
@@ -654,6 +655,16 @@
             ivObj,
             mode);
 
+    int32_t encryptedByteBlock = 0, skipByteBlock = 0;
+    meta->findInt32(kKeyEncryptedByteBlock, &encryptedByteBlock);
+    meta->findInt32(kKeySkipByteBlock, &skipByteBlock);
+
+    env->CallVoidMethod(
+            cryptoInfoObj,
+            gFields.cryptoInfoSetPatternID,
+            encryptedByteBlock,
+            skipByteBlock);
+
     return JNI_TRUE;
 }
 
@@ -669,6 +680,9 @@
 
     gFields.cryptoInfoSetID =
         env->GetMethodID(clazz, "set", "(I[I[I[B[BI)V");
+
+    gFields.cryptoInfoSetPatternID =
+        env->GetMethodID(clazz, "setPattern", "(II)V");
 }
 
 static void android_media_MediaExtractor_native_setup(
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index 3185ea2..e50a375 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -24,7 +24,7 @@
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
 
-    <application>
+    <application android:networkSecurityConfig="@xml/network_security_config">
         <uses-library android:name="android.test.runner" />
         <activity android:label="@string/app_name"
                 android:name="MediaFrameworkTest"
diff --git a/media/tests/MediaFrameworkTest/res/xml/network_security_config.xml b/media/tests/MediaFrameworkTest/res/xml/network_security_config.xml
new file mode 100644
index 0000000..c15c09c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/res/xml/network_security_config.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+    <base-config cleartextTrafficPermitted="true"/>
+</network-security-config>
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 0704e35..9426148 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -33,6 +33,7 @@
     arch: {
         arm: {
             // TODO: This is to work around b/24465209. Remove after root cause is fixed
+            pack_relocations: false,
             ldflags: ["-Wl,--hash-style=both"],
         },
     },
diff --git a/obex/Android.bp b/obex/Android.bp
new file mode 100644
index 0000000..6558eb3
--- /dev/null
+++ b/obex/Android.bp
@@ -0,0 +1,21 @@
+//
+// 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.
+//
+
+java_sdk_library {
+    name: "javax.obex",
+    srcs: ["javax/**/*.java"],
+    api_packages: ["javax.obex"],
+}
diff --git a/obex/Android.mk b/obex/Android.mk
deleted file mode 100644
index e7c1fd3..0000000
--- a/obex/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_MODULE:= javax.obex
-
-include $(BUILD_JAVA_LIBRARY)
-
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_MODULE:= javax.obexstatic
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/obex/CleanSpec.mk b/obex/CleanSpec.mk
new file mode 100644
index 0000000..c104234
--- /dev/null
+++ b/obex/CleanSpec.mk
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+# runtime lib is renamed from javax.obex.jar to javax.obex.impl.jar
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/javax.obex.jar)
diff --git a/obex/api/current.txt b/obex/api/current.txt
new file mode 100644
index 0000000..1cd562f
--- /dev/null
+++ b/obex/api/current.txt
@@ -0,0 +1,12 @@
+package javax.obex {
+
+  public class ObexPacket {
+    method public static javax.obex.ObexPacket read(java.io.InputStream) throws java.io.IOException;
+    method public static javax.obex.ObexPacket read(int, java.io.InputStream) throws java.io.IOException;
+    field public int mHeaderId;
+    field public int mLength;
+    field public byte[] mPayload;
+  }
+
+}
+
diff --git a/obex/api/removed.txt b/obex/api/removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obex/api/removed.txt
diff --git a/obex/api/system-current.txt b/obex/api/system-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obex/api/system-current.txt
diff --git a/obex/api/system-removed.txt b/obex/api/system-removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obex/api/system-removed.txt
diff --git a/obex/api/test-current.txt b/obex/api/test-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obex/api/test-current.txt
diff --git a/obex/api/test-removed.txt b/obex/api/test-removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obex/api/test-removed.txt
diff --git a/packages/CtsShim/build/Android.mk b/packages/CtsShim/build/Android.mk
index 6186a78..e645adc 100644
--- a/packages/CtsShim/build/Android.mk
+++ b/packages/CtsShim/build/Android.mk
@@ -66,10 +66,11 @@
 LOCAL_MULTILIB := both
 LOCAL_JNI_SHARED_LIBRARIES := libshim_jni
 
-# Disable AAPT2 to fix:
+LOCAL_USE_AAPT2 := true
+# Disable AAPT2 manifest checks to fix:
 # out/target/common/obj/APPS/CtsShimPriv_intermediates/AndroidManifest.xml:25: error: unexpected element <restrict-update> found in <manifest>.
-# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
-LOCAL_USE_AAPT2 := false
+# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
+LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(BUILD_PACKAGE)
 
@@ -111,10 +112,11 @@
 
 LOCAL_MANIFEST_FILE := shim/AndroidManifest.xml
 
-# Disable AAPT2 to fix:
+LOCAL_USE_AAPT2 := true
+# Disable AAPT2 manifest checks to fix:
 # frameworks/base/packages/CtsShim/build/shim/AndroidManifest.xml:25: error: unexpected element <restrict-update> found in <manifest>.
-# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
-LOCAL_USE_AAPT2 := false
+# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
+LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(BUILD_PACKAGE)
 
diff --git a/packages/SettingsLib/res/drawable/ic_signal_location.xml b/packages/SettingsLib/res/drawable/ic_signal_location.xml
index 2f60580..1187093 100644
--- a/packages/SettingsLib/res/drawable/ic_signal_location.xml
+++ b/packages/SettingsLib/res/drawable/ic_signal_location.xml
@@ -19,11 +19,10 @@
     android:height="24dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0">
-    <group
-        android:translateX="0.02"
-        android:translateY="0.82">
-        <path
-            android:pathData="M12,2C8.13,2 5,5.13 5,9c0,4.17 4.42,9.92 6.24,12.11 0.4,0.48 1.13,0.48 1.53,0C14.58,18.92 19,13.17 19,9c0,-3.87 -3.13,-7 -7,-7zM12,11.5a2.5,2.5 0,0 1,0 -5,2.5 2.5,0 0,1 0,5z"
-            android:fillColor="#FFFFFFFF"/>
-    </group>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
 </vector>
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
index ee24bd0..8a1c4ef 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
@@ -16,17 +16,22 @@
 
 package com.android.settingslib.fuelgauge;
 
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.IDeviceIdleController;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.UserHandle;
-import androidx.annotation.VisibleForTesting;
+import android.telecom.DefaultDialerManager;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.telephony.SmsApplication;
 import com.android.internal.util.ArrayUtils;
 
+import androidx.annotation.VisibleForTesting;
+
 /**
  * Handles getting/changing the whitelist for the exceptions to battery saving features.
  */
@@ -38,19 +43,20 @@
 
     private static PowerWhitelistBackend sInstance;
 
+    private final Context mAppContext;
     private final IDeviceIdleController mDeviceIdleService;
     private final ArraySet<String> mWhitelistedApps = new ArraySet<>();
     private final ArraySet<String> mSysWhitelistedApps = new ArraySet<>();
     private final ArraySet<String> mSysWhitelistedAppsExceptIdle = new ArraySet<>();
 
-    public PowerWhitelistBackend() {
-        mDeviceIdleService = IDeviceIdleController.Stub.asInterface(
-                ServiceManager.getService(DEVICE_IDLE_SERVICE));
-        refreshList();
+    public PowerWhitelistBackend(Context context) {
+        this(context, IDeviceIdleController.Stub.asInterface(
+                ServiceManager.getService(DEVICE_IDLE_SERVICE)));
     }
 
     @VisibleForTesting
-    PowerWhitelistBackend(IDeviceIdleController deviceIdleService) {
+    PowerWhitelistBackend(Context context, IDeviceIdleController deviceIdleService) {
+        mAppContext = context.getApplicationContext();
         mDeviceIdleService = deviceIdleService;
         refreshList();
     }
@@ -64,7 +70,27 @@
     }
 
     public boolean isWhitelisted(String pkg) {
-        return mWhitelistedApps.contains(pkg);
+        if (mWhitelistedApps.contains(pkg)) {
+            return true;
+        }
+
+        // Additionally, check if pkg is default dialer/sms. They are considered essential apps and
+        // should be automatically whitelisted (otherwise user may be able to set restriction on
+        // them, leading to bad device behavior.)
+        if (!mAppContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            return false;
+        }
+        final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
+                true /* updateIfNeeded */);
+        if (defaultSms != null && TextUtils.equals(pkg, defaultSms.getPackageName())) {
+            return true;
+        }
+
+        final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mAppContext);
+        if (TextUtils.equals(pkg, defaultDialer)) {
+            return true;
+        }
+        return false;
     }
 
     public boolean isWhitelisted(String[] pkgs) {
@@ -120,16 +146,19 @@
         mSysWhitelistedApps.clear();
         mSysWhitelistedAppsExceptIdle.clear();
         mWhitelistedApps.clear();
+        if (mDeviceIdleService == null) {
+            return;
+        }
         try {
-            String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
+            final String[] whitelistedApps = mDeviceIdleService.getFullPowerWhitelist();
             for (String app : whitelistedApps) {
                 mWhitelistedApps.add(app);
             }
-            String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
+            final String[] sysWhitelistedApps = mDeviceIdleService.getSystemPowerWhitelist();
             for (String app : sysWhitelistedApps) {
                 mSysWhitelistedApps.add(app);
             }
-            String[] sysWhitelistedAppsExceptIdle =
+            final String[] sysWhitelistedAppsExceptIdle =
                     mDeviceIdleService.getSystemPowerWhitelistExceptIdle();
             for (String app : sysWhitelistedAppsExceptIdle) {
                 mSysWhitelistedAppsExceptIdle.add(app);
@@ -139,9 +168,9 @@
         }
     }
 
-    public static PowerWhitelistBackend getInstance() {
+    public static PowerWhitelistBackend getInstance(Context context) {
         if (sInstance == null) {
-            sInstance = new PowerWhitelistBackend();
+            sInstance = new PowerWhitelistBackend(context);
         }
         return sInstance;
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index 0af2c05..a23eebc 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -23,35 +23,52 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.IDeviceIdleController;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowDefaultDialerManager;
+import com.android.settingslib.testutils.shadow.ShadowSmsApplication;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowPackageManager;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowDefaultDialerManager.class, ShadowSmsApplication.class})
 public class PowerWhitelistBackendTest {
 
     private static final String PACKAGE_ONE = "com.example.packageone";
     private static final String PACKAGE_TWO = "com.example.packagetwo";
 
-    private PowerWhitelistBackend mPowerWhitelistBackend;
     @Mock
     private IDeviceIdleController mDeviceIdleService;
 
+    private PowerWhitelistBackend mPowerWhitelistBackend;
+    private ShadowPackageManager mPackageManager;
+    private Context mContext;
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
         doReturn(new String[] {}).when(mDeviceIdleService).getFullPowerWhitelist();
         doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelist();
         doReturn(new String[] {}).when(mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
         doNothing().when(mDeviceIdleService).addPowerSaveWhitelistApp(anyString());
         doNothing().when(mDeviceIdleService).removePowerSaveWhitelistApp(anyString());
-        mPowerWhitelistBackend = new PowerWhitelistBackend(mDeviceIdleService);
+        mPackageManager = Shadow.extract(mContext.getPackageManager());
+        mPackageManager.setSystemFeature(PackageManager.FEATURE_TELEPHONY, true);
+
+        mPowerWhitelistBackend = new PowerWhitelistBackend(mContext, mDeviceIdleService);
     }
 
     @Test
@@ -61,8 +78,8 @@
 
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
-        assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_ONE})).isTrue();
-        assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_TWO})).isFalse();
+        assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_ONE})).isTrue();
+        assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_TWO})).isFalse();
 
         mPowerWhitelistBackend.addApp(PACKAGE_TWO);
 
@@ -70,15 +87,15 @@
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isTrue();
         assertThat(mPowerWhitelistBackend.isWhitelisted(
-                new String[]{PACKAGE_ONE, PACKAGE_TWO})).isTrue();
+                new String[] {PACKAGE_ONE, PACKAGE_TWO})).isTrue();
 
         mPowerWhitelistBackend.removeApp(PACKAGE_TWO);
 
         verify(mDeviceIdleService, atLeastOnce()).removePowerSaveWhitelistApp(PACKAGE_TWO);
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
-        assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_ONE})).isTrue();
-        assertThat(mPowerWhitelistBackend.isWhitelisted(new String[]{PACKAGE_TWO})).isFalse();
+        assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_ONE})).isTrue();
+        assertThat(mPowerWhitelistBackend.isWhitelisted(new String[] {PACKAGE_TWO})).isFalse();
 
         mPowerWhitelistBackend.removeApp(PACKAGE_ONE);
 
@@ -86,7 +103,23 @@
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isFalse();
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_TWO)).isFalse();
         assertThat(mPowerWhitelistBackend.isWhitelisted(
-                new String[]{PACKAGE_ONE, PACKAGE_TWO})).isFalse();
+                new String[] {PACKAGE_ONE, PACKAGE_TWO})).isFalse();
+    }
+
+    @Test
+    public void isWhitelisted_shouldWhitelistDefaultSms() {
+        final String testSms = "com.android.test.defaultsms";
+        ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
+
+        assertThat(mPowerWhitelistBackend.isWhitelisted(testSms)).isTrue();
+    }
+
+    @Test
+    public void isWhitelisted_shouldWhitelistDefaultDialer() {
+        final String testDialer = "com.android.test.defaultdialer";
+        ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
+
+        assertThat(mPowerWhitelistBackend.isWhitelisted(testDialer)).isTrue();
     }
 
     @Test
@@ -101,7 +134,7 @@
 
     @Test
     public void testIsSystemWhitelistedExceptIdle_onePackage() throws Exception {
-        doReturn(new String[]{PACKAGE_TWO}).when(
+        doReturn(new String[] {PACKAGE_TWO}).when(
                 mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
         mPowerWhitelistBackend.refreshList();
 
@@ -111,7 +144,7 @@
 
     @Test
     public void testIsSystemWhitelistedExceptIdle_packageArray() throws Exception {
-        doReturn(new String[]{PACKAGE_TWO}).when(
+        doReturn(new String[] {PACKAGE_TWO}).when(
                 mDeviceIdleService).getSystemPowerWhitelistExceptIdle();
         mPowerWhitelistBackend.refreshList();
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java
new file mode 100644
index 0000000..f4afdb1
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java
@@ -0,0 +1,44 @@
+/*
+ * 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.settingslib.testutils.shadow;
+
+import android.content.Context;
+import android.telecom.DefaultDialerManager;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(DefaultDialerManager.class)
+public class ShadowDefaultDialerManager {
+
+    private static String sDefaultDailer;
+
+    @Resetter
+    public void reset() {
+        sDefaultDailer = null;
+    }
+
+    @Implementation
+    public static String getDefaultDialerApplication(Context context) {
+        return sDefaultDailer;
+    }
+
+    public static void setDefaultDialerApplication(String dialer) {
+        sDefaultDailer = dialer;
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowSmsApplication.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowSmsApplication.java
new file mode 100644
index 0000000..dd7b007
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowSmsApplication.java
@@ -0,0 +1,46 @@
+/*
+ * 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.settingslib.testutils.shadow;
+
+import android.content.ComponentName;
+import android.content.Context;
+
+import com.android.internal.telephony.SmsApplication;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(SmsApplication.class)
+public class ShadowSmsApplication {
+
+    private static ComponentName sDefaultSmsApplication;
+
+    @Resetter
+    public void reset() {
+        sDefaultSmsApplication = null;
+    }
+
+    @Implementation
+    public static ComponentName getDefaultSmsApplication(Context context, boolean updateIfNeeded) {
+        return sDefaultSmsApplication;
+    }
+
+    public static void setDefaultSmsApplication(ComponentName cn) {
+        sDefaultSmsApplication = cn;
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 28e8db9..e1a602b 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -214,4 +214,7 @@
 
     <!-- Default for Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS -->
     <string name="def_backup_agent_timeout_parameters"></string>
+
+    <!-- Default for Settings.System.VIBRATE_WHEN_RINGING -->
+    <bool name="def_vibrate_when_ringing">false</bool>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 85bbd59..960d305 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2935,7 +2935,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 167;
+            private static final int SETTINGS_VERSION = 169;
 
             private final int mUserId;
 
@@ -3792,6 +3792,34 @@
                     currentVersion = 167;
                 }
 
+                if (currentVersion == 167) {
+                    // Version 167: by default, vibrate for wireless charging
+                    final SettingsState globalSettings = getGlobalSettingsLocked();
+                    final Setting currentSetting = globalSettings.getSettingLocked(
+                            Global.CHARGING_VIBRATION_ENABLED);
+                    if (currentSetting.isNull()) {
+                        globalSettings.insertSettingLocked(
+                                Global.CHARGING_VIBRATION_ENABLED, "1",
+                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+                    currentVersion = 168;
+                }
+
+                if (currentVersion == 168) {
+                    // Version 168: by default, vibrate for phone calls
+                    final SettingsState systemSettings = getSystemSettingsLocked(userId);
+                    final Setting currentSetting = systemSettings.getSettingLocked(
+                            Settings.System.VIBRATE_WHEN_RINGING);
+                    if (currentSetting.isNull()) {
+                        systemSettings.insertSettingLocked(
+                                Settings.System.VIBRATE_WHEN_RINGING,
+                                getContext().getResources().getBoolean(
+                                        R.bool.def_vibrate_when_ringing) ? "1" : "0",
+                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+                    currentVersion = 169;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index a92df74..8eee0d5 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -211,6 +211,8 @@
     <!-- Permission necessary to change car audio volume through CarAudioManager -->
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME" />
 
+    <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" />
+
     <application
         android:name=".SystemUIApplication"
         android:persistent="true"
diff --git a/packages/SystemUI/res/drawable-hdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-hdpi/qs_scrubber_track.9.png
new file mode 100644
index 0000000..0899d35
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/qs_scrubber_track.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-mdpi/qs_scrubber_track.9.png
new file mode 100644
index 0000000..2266449
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/qs_scrubber_track.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-xhdpi/qs_scrubber_track.9.png
new file mode 100644
index 0000000..3328add
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/qs_scrubber_track.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-xxhdpi/qs_scrubber_track.9.png
new file mode 100644
index 0000000..ed651da
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/qs_scrubber_track.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-xxxhdpi/qs_scrubber_track.9.png
new file mode 100644
index 0000000..06e1202
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/qs_scrubber_track.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/car_add_circle_round.xml b/packages/SystemUI/res/drawable/car_add_circle_round.xml
index 5cf0c31..13c7dd1 100644
--- a/packages/SystemUI/res/drawable/car_add_circle_round.xml
+++ b/packages/SystemUI/res/drawable/car_add_circle_round.xml
@@ -1,4 +1,18 @@
 <?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.
+-->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
     <item>
         <shape android:shape="oval">
diff --git a/packages/SystemUI/res/drawable/car_ic_add_white.xml b/packages/SystemUI/res/drawable/car_ic_add_white.xml
index f24771d..d681860 100644
--- a/packages/SystemUI/res/drawable/car_ic_add_white.xml
+++ b/packages/SystemUI/res/drawable/car_ic_add_white.xml
@@ -1,3 +1,17 @@
+<!-- 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="@dimen/car_touch_target_size"
     android:height="@dimen/car_touch_target_size"
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
index 907be01..2cd7883 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
@@ -21,10 +21,12 @@
                 android:height="21dp"
                 android:viewportWidth="24.0"
                 android:viewportHeight="24.0">
-            <group android:name="icon" android:pivotX="12" android:pivotY="12">
+            <!-- Use scaleX to flip icon so arrows always point in the direction of motion -->
+            <group android:name="icon" android:pivotX="12" android:pivotY="12"
+                   android:scaleX="?attr/rotateButtonScaleX">
                 <!-- Tint color to be set directly -->
                 <path android:fillColor="#FFFFFFFF"
-                      android:pathData="M12,4c-0.06,0 -0.12,0.01 -0.18,0.01l1.09,-1.09L11.5,1.5L8,5l3.5,3.5l1.41,-1.41l-1.08,-1.08C11.89,6.01 11.95,6 12,6c3.31,0 6,2.69 6,6c0,1.7 -0.71,3.23 -1.85,4.32l1.41,1.41C19.06,16.28 20,14.25 20,12C20,7.59 16.41,4 12,4zM16,19l-3.5,3.5l-1.41,-1.41l1.1,-1.1C12.13,19.98 12.06,20 12,20c-4.41,0 -8,-3.59 -8,-8c0,-2.25 0.94,-4.28 2.43,-5.73l1.41,1.41C6.71,8.77 6,10.3 6,12c0,3.31 2.69,6 6,6c0.05,0 0.11,-0.01 0.16,-0.01l-1.07,-1.07l1.41,-1.41L16,19z"/>
+                      android:pathData="M19,12c0,1.72 -0.63,3.3 -1.66,4.52l-1.44,-1.44C16.58,14.23 17,13.17 17,12c0,-2.76 -2.24,-5 -5,-5c-0.06,0 -0.11,0.01 -0.17,0.01l1.08,1.08L11.5,9.5L8,6l3.5,-3.5l1.41,1.42l-1.09,1.09C11.88,5.01 11.94,5 12,5C15.87,5 19,8.13 19,12zM12.5,14.51l-1.41,1.41l1.06,1.06C12.1,16.99 12.05,17 12,17c-2.76,0 -5,-2.24 -5,-5c0,-1.17 0.42,-2.23 1.09,-3.08L6.66,7.48C5.62,8.7 5,10.28 5,12c0,3.87 3.13,7 7,7c0.06,0 0.13,-0.01 0.19,-0.01v0l-1.1,1.1l1.41,1.41L16,18L12.5,14.51z"/>
             </group>
         </vector>
     </aapt:attr>
diff --git a/packages/SystemUI/res/drawable/stat_sys_location.xml b/packages/SystemUI/res/drawable/stat_sys_location.xml
index 33ac5cd..bdb0b0c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_location.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_location.xml
@@ -19,11 +19,13 @@
         <vector
             android:width="17dp"
             android:height="17dp"
-            android:viewportWidth="48.0"
-            android:viewportHeight="48.0">
-
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M24.0,4.0c-7.7,0.0 -14.0,6.3 -14.0,14.0c0.0,10.5 14.0,26.0 14.0,26.0s14.0,-15.5 14.0,-26.0C38.0,10.3 31.7,4.0 24.0,4.0zM24.0,23.0c-2.8,0.0 -5.0,-2.2 -5.0,-5.0s2.2,-5.0 5.0,-5.0c2.8,0.0 5.0,2.2 5.0,5.0S26.8,23.0 24.0,23.0z"/>
+            android:viewportWidth="24.0"
+            android:viewportHeight="24.0">
+                <path
+                    android:fillColor="#FFFFFFFF"
+                    android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9z"/>
+                <path
+                    android:fillColor="#FFFFFFFF"
+                    android:pathData="M12,9m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
         </vector>
 </inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_onboarding.xml b/packages/SystemUI/res/layout/recents_onboarding.xml
index 093a7ce1..adf1e74 100644
--- a/packages/SystemUI/res/layout/recents_onboarding.xml
+++ b/packages/SystemUI/res/layout/recents_onboarding.xml
@@ -23,7 +23,7 @@
 
     <LinearLayout
         android:layout_width="wrap_content"
-        android:layout_height="40dp"
+        android:layout_height="wrap_content"
         android:paddingStart="24dp"
         android:paddingEnd="4dp"
         android:background="@drawable/recents_onboarding_toast_rounded_background"
@@ -33,8 +33,9 @@
 
         <TextView
             android:id="@+id/onboarding_text"
-            android:layout_width="wrap_content"
+            android:layout_width="0dp"
             android:layout_height="wrap_content"
+            android:layout_weight="1"
             android:layout_gravity="center_vertical"
             android:textColor="@android:color/white"
             android:textSize="16sp"/>
diff --git a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
index 7931dfe..8b56b68 100644
--- a/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/status_bar_mobile_signal_group.xml
@@ -29,7 +29,6 @@
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:gravity="center_vertical"
-        android:paddingStart="2dp"
         android:orientation="horizontal" >
 
         <FrameLayout
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index c70e829..e67bb60 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -93,7 +93,7 @@
                     android:layout_gravity="center"
                     android:contentDescription="@string/accessibility_volume_settings"
                     android:background="@drawable/ripple_drawable_20dp"
-                    android:tint="?android:attr/textColorHint"
+                    android:tint="?android:attr/textColorSecondary"
                     android:soundEffectsEnabled="false" />
             </FrameLayout>
         </LinearLayout>
diff --git a/packages/SystemUI/res/values-ldrtl/strings.xml b/packages/SystemUI/res/values-ldrtl/strings.xml
new file mode 100644
index 0000000..c93da69
--- /dev/null
+++ b/packages/SystemUI/res/values-ldrtl/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+ */
+-->
+<resources>
+    <!-- Recents: Text that shows above the navigation bar after launching several apps. [CHAR LIMIT=NONE] -->
+    <string name="recents_quick_scrub_onboarding">Drag left to quickly switch apps</string>
+</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 2ce9bfc..3f63f22 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -141,5 +141,7 @@
     <!-- Used to style rotate suggestion button AVD animations -->
     <attr name="rotateButtonStartAngle" format="float" />
     <attr name="rotateButtonEndAngle" format="float" />
+    <attr name="rotateButtonScaleX" format="float" />
+
 </resources>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d8607cc..975055c 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -125,9 +125,6 @@
     <color name="light_mode_icon_color_dual_tone_background">#4dffffff</color>
     <color name="light_mode_icon_color_dual_tone_fill">#ffffff</color>
 
-    <color name="volume_settings_icon_color">#7fffffff</color>
-    <color name="volume_slider_inactive">@*android:color/quaternary_device_default_settings</color>
-
     <color name="docked_divider_background">#ff000000</color>
     <color name="docked_divider_handle">#ffffff</color>
     <drawable name="forced_resizable_background">#59000000</drawable>
@@ -141,7 +138,7 @@
     <color name="remote_input_accent">#eeeeee</color>
 
     <color name="quick_step_track_background_dark">#61000000</color>
-    <color name="quick_step_track_background_light">#4DFFFFFF</color>
+    <color name="quick_step_track_background_light">#33FFFFFF</color>
 
     <!-- Keyboard shortcuts colors -->
     <color name="ksh_application_group_color">#fff44336</color>
diff --git a/packages/SystemUI/res/values/colors_car.xml b/packages/SystemUI/res/values/colors_car.xml
index cb3abb9..49bfb25 100644
--- a/packages/SystemUI/res/values/colors_car.xml
+++ b/packages/SystemUI/res/values/colors_car.xml
@@ -25,4 +25,7 @@
     <color name="car_user_switcher_name_text_color">@color/car_body1_light</color>
     <color name="car_user_switcher_add_user_background_color">@color/car_dark_blue_grey_600</color>
     <color name="car_user_switcher_add_user_add_sign_color">@color/car_body1_light</color>
+
+    <!-- colors for volume dialog tint -->
+    <color name="car_volume_dialog_tint">@color/car_tint</color>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 82869ca..9a3bdf2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -201,7 +201,7 @@
     <dimen name="status_bar_padding_start">6dp</dimen>
 
     <!-- the padding on the end of the statusbar -->
-    <dimen name="status_bar_padding_end">8dp</dimen>
+    <dimen name="status_bar_padding_end">6dp</dimen>
 
     <!-- the radius of the overflow dot in the status bar -->
     <dimen name="overflow_dot_radius">1dp</dimen>
@@ -867,6 +867,8 @@
 
     <!-- The size of corner radius of the arrow in the onboarding toast. -->
     <dimen name="recents_onboarding_toast_arrow_corner_radius">2dp</dimen>
+    <!-- The start margin of quick scrub onboarding toast. -->
+    <dimen name="recents_quick_scrub_onboarding_margin_start">8dp</dimen>
 
     <!-- The min alpha to apply to a task affiliation group color. -->
     <item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item>
@@ -939,7 +941,7 @@
     <dimen name="rounded_corner_content_padding">0dp</dimen>
     <dimen name="nav_content_padding">0dp</dimen>
     <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
-    <dimen name="nav_quick_scrub_track_thickness">2dp</dimen>
+    <dimen name="nav_quick_scrub_track_thickness">10dp</dimen>
 
     <!-- Navigation bar shadow params. -->
     <dimen name="nav_key_button_shadow_offset_x">0dp</dimen>
@@ -1007,4 +1009,7 @@
     <dimen name="logout_button_margin_bottom">12dp</dimen>
     <dimen name="logout_button_corner_radius">2dp</dimen>
 
+    <!-- How much into a DisplayCutout's bounds we can go, on each side -->
+    <dimen name="display_cutout_margin_consumption">0px</dimen>
+
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b3f4534..e4f5989 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -506,21 +506,25 @@
     <style name="RotateButtonCCWStart0">
         <item name="rotateButtonStartAngle">0</item>
         <item name="rotateButtonEndAngle">-90</item>
+        <item name="rotateButtonScaleX">1</item>
     </style>
 
     <style name="RotateButtonCCWStart90">
         <item name="rotateButtonStartAngle">90</item>
         <item name="rotateButtonEndAngle">0</item>
+        <item name="rotateButtonScaleX">1</item>
     </style>
 
     <style name="RotateButtonCWStart0">
         <item name="rotateButtonStartAngle">0</item>
         <item name="rotateButtonEndAngle">90</item>
+        <item name="rotateButtonScaleX">-1</item>
     </style>
 
     <style name="RotateButtonCWStart90">
         <item name="rotateButtonStartAngle">90</item>
         <item name="rotateButtonEndAngle">180</item>
+        <item name="rotateButtonScaleX">-1</item>
     </style>
 
 </resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 2de33f9..5a84fa5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -58,7 +58,7 @@
 
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
-import androidx.slice.SliceManager;
+import androidx.slice.SliceViewManager;
 import androidx.slice.core.SliceQuery;
 import androidx.slice.widget.ListContent;
 import androidx.slice.widget.RowContent;
@@ -374,7 +374,7 @@
     }
 
     public void refresh() {
-        Slice slice = SliceManager.getInstance(getContext()).bindSlice(mKeyguardSliceUri);
+        Slice slice = SliceViewManager.getInstance(getContext()).bindSlice(mKeyguardSliceUri);
         onChanged(slice);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 42bd66a..9fc71c8 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -166,9 +166,7 @@
             long token = Binder.clearCallingIdentity();
             try {
                 mHandler.post(() -> {
-                    for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
-                        mConnectionCallbacks.get(i).onBackButtonAlphaChanged(alpha, animate);
-                    }
+                    notifyBackButtonAlphaChanged(alpha, animate);
                 });
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -355,10 +353,17 @@
             mOverviewProxy.asBinder().unlinkToDeath(mOverviewServiceDeathRcpt, 0);
             mContext.unbindService(mOverviewServiceConnection);
             mOverviewProxy = null;
+            notifyBackButtonAlphaChanged(1f, false /* animate */);
             notifyConnectionChanged();
         }
     }
 
+    private void notifyBackButtonAlphaChanged(float alpha, boolean animate) {
+        for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+            mConnectionCallbacks.get(i).onBackButtonAlphaChanged(alpha, animate);
+        }
+    }
+
     private void notifyConnectionChanged() {
         for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
             mConnectionCallbacks.get(i).onConnectionChanged(mOverviewProxy != null);
diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
index e6ea2d8..6d79066 100644
--- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
@@ -14,6 +14,8 @@
 
 package com.android.systemui;
 
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.slice.SliceManager;
@@ -66,7 +68,9 @@
                     .setNegativeButton(R.string.slice_permission_deny, this)
                     .setPositiveButton(R.string.slice_permission_allow, this)
                     .setOnDismissListener(this)
-                    .show();
+                    .create();
+            dialog.getWindow().addPrivateFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+            dialog.show();
             TextView t1 = dialog.getWindow().getDecorView().findViewById(R.id.text1);
             t1.setText(getString(R.string.slice_permission_text_1, app2));
             TextView t2 = dialog.getWindow().getDecorView().findViewById(R.id.text2);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 31d8cbb..ad84130 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -225,9 +225,10 @@
      */
     boolean shouldDismissPip() {
         Point displaySize = new Point();
-        mContext.getDisplay().getSize(displaySize);
-        if (mBounds.bottom > displaySize.y) {
-            float offscreenFraction = (float) (mBounds.bottom - displaySize.y) / mBounds.height();
+        mContext.getDisplay().getRealSize(displaySize);
+        final int y = displaySize.y - mStableInsets.bottom;
+        if (mBounds.bottom > y) {
+            float offscreenFraction = (float) (mBounds.bottom - y) / mBounds.height();
             return offscreenFraction >= DISMISS_OFFSCREEN_FRACTION;
         }
         return false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 7afa82a..100751c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -184,9 +184,15 @@
             return;
         }
         boolean selected = mLastExpansion == 1f;
+
+        // Disable accessibility temporarily while we update selected state purely for the
+        // marquee. This will ensure that accessibility doesn't announce the TYPE_VIEW_SELECTED
+        // event on any of the children.
+        setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
         for (int i = 0; i < mPages.size(); i++) {
             mPages.get(i).setSelected(i == getCurrentItem() ? selected : false);
         }
+        setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
     }
 
     public void setPageListener(PageListener listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index fec76f2..8d8e206 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -173,7 +173,7 @@
                                             : SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS_BACK_OFF;
                             mNumAppsLaunchedSinceSwipeUpTipDismiss++;
                             if (mNumAppsLaunchedSinceSwipeUpTipDismiss
-                                    == swipeUpShowOnAppLauncherAfterDismiss) {
+                                    >= swipeUpShowOnAppLauncherAfterDismiss) {
                                 mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
                                 shouldLog = show(R.string.recents_swipe_up_onboarding);
                             }
@@ -188,7 +188,7 @@
                     if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
                         if (mHasDismissedQuickScrubTip) {
                             if (mOverviewOpenedCountSinceQuickScrubTipDismiss
-                                    == QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
+                                    >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
                                 mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
                                 shouldLog = show(R.string.recents_quick_scrub_onboarding);
                             }
@@ -393,7 +393,20 @@
         if (!mLayoutAttachedToWindow && orientation == Configuration.ORIENTATION_PORTRAIT) {
             mLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
 
-            mWindowManager.addView(mLayout, getWindowLayoutParams());
+            final int gravity;
+            final int x;
+            if (stringRes == R.string.recents_swipe_up_onboarding) {
+                gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+                x = 0;
+            } else {
+                int layoutDirection =
+                        mContext.getResources().getConfiguration().getLayoutDirection();
+                gravity = Gravity.BOTTOM | (layoutDirection == View.LAYOUT_DIRECTION_LTR
+                        ? Gravity.LEFT : Gravity.RIGHT);
+                x = mContext.getResources().getDimensionPixelSize(
+                        R.dimen.recents_quick_scrub_onboarding_margin_start);
+            }
+            mWindowManager.addView(mLayout, getWindowLayoutParams(gravity, x));
             mLayout.setAlpha(0);
             mLayout.animate()
                     .alpha(1f)
@@ -459,19 +472,19 @@
         pw.println("    }");
     }
 
-    private WindowManager.LayoutParams getWindowLayoutParams() {
+    private WindowManager.LayoutParams getWindowLayoutParams(int gravity, int x) {
         int flags = WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.WRAP_CONTENT,
-                0, -mNavBarHeight / 2,
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                x, -mNavBarHeight / 2,
                 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
                 flags,
                 PixelFormat.TRANSLUCENT);
         lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
         lp.setTitle("RecentsOnboarding");
-        lp.gravity = Gravity.BOTTOM;
+        lp.gravity = gravity;
         return lp;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index f30fa6b..d647e21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -710,6 +710,8 @@
         updateClickAndFocus();
         if (mNotificationParent != null) {
             setOverrideTintColor(NO_COLOR, 0.0f);
+            // Let's reset the distance to top roundness, as this isn't applied to group children
+            setDistanceToTopRoundness(NO_ROUNDNESS);
             mNotificationParent.updateBackgroundForGroupState();
         }
         updateIconVisibilities();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 29c3ebd..ae8d844 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -36,6 +36,7 @@
  */
 public abstract class ExpandableView extends FrameLayout {
 
+    public static final float NO_ROUNDNESS = -1;
     protected OnHeightChangedListener mOnHeightChangedListener;
     private int mActualHeight;
     protected int mClipTopAmount;
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 03791c7..91a4dda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -182,6 +182,9 @@
             }
         }
         if (mReplyAction != null) {
+            // Let's reset the view on update, assuming the new pending intent isn't cancelled
+            // anymore. The color filter automatically resets when it's updated.
+            mReplyAction.setEnabled(true);
             performOnPendingIntentCancellation(mReplyAction, () -> {
                 if (mReplyAction != null && mReplyAction.isEnabled()) {
                     mReplyAction.setEnabled(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 8ede224..879ac92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -16,11 +16,8 @@
 
 package com.android.systemui.statusbar.notification;
 
-import android.util.ArraySet;
 import android.util.Pools;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.view.animation.Interpolator;
 import android.widget.ImageView;
 import android.widget.ProgressBar;
@@ -411,7 +408,8 @@
         mOwnPosition[1] -= (1.0f - mTransformedView.getScaleY()) * mTransformedView.getPivotY();
 
         // Remove local translations
-        mOwnPosition[1] -= MessagingPropertyAnimator.getLocalTranslationY(mTransformedView);
+        mOwnPosition[1] -= MessagingPropertyAnimator.getTop(mTransformedView)
+                - MessagingPropertyAnimator.getLayoutTop(mTransformedView);
         return mOwnPosition;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 3c0b226..894ea62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -114,6 +114,10 @@
         return mVisibility != null ? mVisibility : View.VISIBLE;
     }
 
+    public boolean isVisible() {
+        return getVisibility() == View.VISIBLE;
+    }
+
     public float getAlpha() {
         return mAlpha != null ? mAlpha : 1;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index e2fec85..e096f3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -90,6 +90,11 @@
     private ViewGroup mStatusIconArea;
     private int mLayoutState = LAYOUT_NONE;
 
+    /**
+     * Draw this many pixels into the left/right side of the cutout to optimally use the space
+     */
+    private int mCutoutSideNudge = 0;
+
     public KeyguardStatusBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
@@ -158,6 +163,8 @@
                 R.dimen.system_icons_switcher_hidden_expanded_margin);
         mSystemIconsBaseMargin = res.getDimensionPixelSize(
                 R.dimen.system_icons_super_container_avatarless_margin_end);
+        mCutoutSideNudge = getResources().getDimensionPixelSize(
+                R.dimen.display_cutout_margin_consumption);
     }
 
     private void updateVisibilities() {
@@ -266,6 +273,8 @@
 
         mCutoutSpace.setVisibility(View.VISIBLE);
         RelativeLayout.LayoutParams lp = (LayoutParams) mCutoutSpace.getLayoutParams();
+        bounds.left = bounds.left + mCutoutSideNudge;
+        bounds.right = bounds.right - mCutoutSideNudge;
         lp.width = bounds.width();
         lp.height = bounds.height();
         lp.addRule(RelativeLayout.CENTER_IN_PARENT);
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 cfc8715..f9a540c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -1144,6 +1144,8 @@
             mRoot.postOnAnimationDelayed(mRipple, RIPPLE_OFFSET_MS);
             mRoot.postOnAnimationDelayed(mRipple, RIPPLE_INTERVAL_MS);
             mRoot.postOnAnimationDelayed(mRipple, 2*RIPPLE_INTERVAL_MS);
+            mRoot.postOnAnimationDelayed(mRipple, 3*RIPPLE_INTERVAL_MS);
+            mRoot.postOnAnimationDelayed(mRipple, 4*RIPPLE_INTERVAL_MS);
         }
 
         public void stop() {
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 f631ef8..a3cba2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -336,13 +336,14 @@
                 int x = (int) event.getX();
                 int y = (int) event.getY();
                 mDownHitTarget = HIT_TARGET_NONE;
-                if (mBackButtonBounds.contains(x, y)) {
+                if (getBackButton().isVisible() && mBackButtonBounds.contains(x, y)) {
                     mDownHitTarget = HIT_TARGET_BACK;
-                } else if (mHomeButtonBounds.contains(x, y)) {
+                } else if (getHomeButton().isVisible() && mHomeButtonBounds.contains(x, y)) {
                     mDownHitTarget = HIT_TARGET_HOME;
-                } else if (mRecentsButtonBounds.contains(x, y)) {
+                } else if (getRecentsButton().isVisible() && mRecentsButtonBounds.contains(x, y)) {
                     mDownHitTarget = HIT_TARGET_OVERVIEW;
-                } else if (mRotationButtonBounds.contains(x, y)) {
+                } else if (getRotateSuggestionButton().isVisible()
+                        && mRotationButtonBounds.contains(x, y)) {
                     mDownHitTarget = HIT_TARGET_ROTATION;
                 }
                 break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 01582d0..5477f88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -74,6 +74,10 @@
     private View mCutoutSpace;
     @Nullable
     private DisplayCutout mDisplayCutout;
+    /**
+     * Draw this many pixels into the left/right side of the cutout to optimally use the space
+     */
+    private int mCutoutSideNudge = 0;
 
     public PhoneStatusBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -98,6 +102,8 @@
         mBarTransitions.init();
         mBattery = findViewById(R.id.battery);
         mCutoutSpace = findViewById(R.id.cutout_space_view);
+
+        updateResources();
     }
 
     @Override
@@ -280,6 +286,9 @@
     }
 
     public void updateResources() {
+        mCutoutSideNudge = getResources().getDimensionPixelSize(
+                R.dimen.display_cutout_margin_consumption);
+
         ViewGroup.LayoutParams layoutParams = getLayoutParams();
         layoutParams.height = getResources().getDimensionPixelSize(
                 R.dimen.status_bar_height);
@@ -311,6 +320,8 @@
         Rect bounds = new Rect();
         boundsFromDirection(mDisplayCutout, Gravity.TOP, bounds);
 
+        bounds.left = bounds.left + mCutoutSideNudge;
+        bounds.right = bounds.right - mCutoutSideNudge;
         lp.width = bounds.width();
         lp.height = bounds.height();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index bdd96d5..ea1b980 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -29,14 +29,13 @@
 import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Matrix;
-import android.graphics.Paint;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.FloatProperty;
@@ -55,6 +54,7 @@
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.utilities.Utilities;
 import com.android.systemui.shared.system.NavigationBarCompat;
+import com.android.internal.graphics.ColorUtils;
 
 /**
  * Class to detect gestures on the navigation bar and implement quick scrub.
@@ -63,7 +63,8 @@
 
     private static final String TAG = "QuickStepController";
     private static final int ANIM_IN_DURATION_MS = 150;
-    private static final int ANIM_OUT_DURATION_MS = 100;
+    private static final int ANIM_OUT_DURATION_MS = 134;
+    private static final float TRACK_SCALE = 0.95f;
 
     private NavigationBarView mNavigationBarView;
 
@@ -76,6 +77,7 @@
     private boolean mIsVertical;
     private boolean mIsRTL;
     private float mTrackAlpha;
+    private float mTrackScale = TRACK_SCALE;
     private int mLightTrackColor;
     private int mDarkTrackColor;
     private float mDarkIntensity;
@@ -85,7 +87,7 @@
 
     private final Handler mHandler = new Handler();
     private final Rect mTrackRect = new Rect();
-    private final Paint mTrackPaint = new Paint();
+    private final Drawable mTrackDrawable;
     private final OverviewProxyService mOverviewEventSender;
     private final int mTrackThickness;
     private final int mTrackEndPadding;
@@ -108,6 +110,20 @@
         }
     };
 
+    private final FloatProperty<QuickStepController> mTrackScaleProperty =
+            new FloatProperty<QuickStepController>("TrackScale") {
+        @Override
+        public void setValue(QuickStepController controller, float scale) {
+            mTrackScale = scale;
+            mNavigationBarView.invalidate();
+        }
+
+        @Override
+        public Float get(QuickStepController controller) {
+            return mTrackScale;
+        }
+    };
+
     private final FloatProperty<QuickStepController> mNavBarAlphaProperty =
             new FloatProperty<QuickStepController>("NavBarAlpha") {
         @Override
@@ -139,7 +155,7 @@
         mOverviewEventSender = Dependency.get(OverviewProxyService.class);
         mTrackThickness = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_thickness);
         mTrackEndPadding = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_edge_padding);
-        mTrackPaint.setAlpha(0);
+        mTrackDrawable = context.getDrawable(R.drawable.qs_scrubber_track).mutate();
     }
 
     public void setComponents(NavigationBarView navigationBarView) {
@@ -296,9 +312,17 @@
         }
         int color = (int) mTrackColorEvaluator.evaluate(mDarkIntensity, mLightTrackColor,
                 mDarkTrackColor);
-        mTrackPaint.setColor(color);
-        mTrackPaint.setAlpha((int) (mTrackPaint.getAlpha() * mTrackAlpha));
-        canvas.drawRect(mTrackRect, mTrackPaint);
+        int colorAlpha = ColorUtils.setAlphaComponent(color,
+                (int) (Color.alpha(color) * mTrackAlpha));
+        mTrackDrawable.setTint(colorAlpha);
+
+        // Scale the track, but apply the inverse scale from the nav bar
+        canvas.save();
+        canvas.scale(mTrackScale / mNavigationBarView.getScaleX(),
+                1f / mNavigationBarView.getScaleY(),
+                mTrackRect.centerX(), mTrackRect.centerY());
+        mTrackDrawable.draw(canvas);
+        canvas.restore();
     }
 
     @Override
@@ -322,6 +346,7 @@
             x2 = x1 + width - 2 * mTrackEndPadding;
         }
         mTrackRect.set(x1, y1, x2, y2);
+        mTrackDrawable.setBounds(mTrackRect);
     }
 
     @Override
@@ -387,7 +412,9 @@
             mLightTrackColor = mContext.getColor(R.color.quick_step_track_background_light);
             mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
 
-            ObjectAnimator trackAnimator = ObjectAnimator.ofFloat(this, mTrackAlphaProperty, 1f);
+            ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
+                    PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 1f),
+                    PropertyValuesHolder.ofFloat(mTrackScaleProperty, 1f));
             trackAnimator.setInterpolator(ALPHA_IN);
             trackAnimator.setDuration(ANIM_IN_DURATION_MS);
             ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 0f);
@@ -438,7 +465,9 @@
             mTrackAnimator.cancel();
         }
 
-        ObjectAnimator trackAnimator = ObjectAnimator.ofFloat(this, mTrackAlphaProperty, 0f);
+        ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
+                PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 0f),
+                PropertyValuesHolder.ofFloat(mTrackScaleProperty, TRACK_SCALE));
         trackAnimator.setInterpolator(ALPHA_OUT);
         trackAnimator.setDuration(ANIM_OUT_DURATION_MS);
         ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 1f);
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 4bda017..fe86378 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -174,11 +174,13 @@
                 || mStatusBar.isFullScreenUserSwitcherState()) {
             mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
         } else if (mShowing && !mDozing) {
-            mBouncer.setExpansion(expansion);
+            if (!isWakeAndUnlocking()) {
+                mBouncer.setExpansion(expansion);
+            }
             if (expansion != KeyguardBouncer.EXPANSION_HIDDEN && tracking
                     && mStatusBar.isKeyguardCurrentlySecure()
                     && !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
-                mBouncer.show(false /* resetSecuritySelection */, false /* animated */);
+                mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 7cd433a..384a6e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -148,16 +148,31 @@
         boolean in = activityIn && mActivityEnabled && visible;
         boolean out = activityOut && mActivityEnabled && visible;
 
-        mWifiIconState.visible = visible;
-        mWifiIconState.resId = statusIcon.icon;
-        mWifiIconState.activityIn = in;
-        mWifiIconState.activityOut = out;
-        mWifiIconState.slot = mSlotWifi;
-        mWifiIconState.airplaneSpacerVisible = mIsAirplaneMode;
-        mWifiIconState.contentDescription = statusIcon.contentDescription;
+        WifiIconState newState = mWifiIconState.copy();
 
-        if (mWifiIconState.visible && mWifiIconState.resId > 0) {
-            mIconController.setSignalIcon(mSlotWifi, mWifiIconState.copy());
+        newState.visible = visible;
+        newState.resId = statusIcon.icon;
+        newState.activityIn = in;
+        newState.activityOut = out;
+        newState.slot = mSlotWifi;
+        newState.airplaneSpacerVisible = mIsAirplaneMode;
+        newState.contentDescription = statusIcon.contentDescription;
+
+        MobileIconState first = getFirstMobileState();
+        newState.signalSpacerVisible = first != null && first.typeId != 0;
+
+        updateWifiIconWithState(newState);
+        mWifiIconState = newState;
+    }
+
+    private void updateShowWifiSignalSpacer(WifiIconState state) {
+        MobileIconState first = getFirstMobileState();
+        state.signalSpacerVisible = first != null && first.typeId != 0;
+    }
+
+    private void updateWifiIconWithState(WifiIconState state) {
+        if (state.visible && state.resId > 0) {
+            mIconController.setSignalIcon(mSlotWifi, state);
             mIconController.setIconVisibility(mSlotWifi, true);
         } else {
             mIconController.setIconVisibility(mSlotWifi, false);
@@ -173,6 +188,9 @@
             return;
         }
 
+        // Visibility of the data type indicator changed
+        boolean typeChanged = statusType != state.typeId && (statusType == 0 || state.typeId == 0);
+
         state.visible = statusIcon.visible && !mBlockMobile;
         state.strengthId = statusIcon.icon;
         state.typeId = statusType;
@@ -184,6 +202,15 @@
 
         // Always send a copy to maintain value type semantics
         mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates));
+
+        if (typeChanged) {
+            WifiIconState wifiCopy = mWifiIconState.copy();
+            updateShowWifiSignalSpacer(wifiCopy);
+            if (!Objects.equals(wifiCopy, mWifiIconState)) {
+                updateWifiIconWithState(wifiCopy);
+                mWifiIconState = wifiCopy;
+            }
+        }
     }
 
     private MobileIconState getState(int subId) {
@@ -196,6 +223,14 @@
         return null;
     }
 
+    private MobileIconState getFirstMobileState() {
+        if (mMobileStates.size() > 0) {
+            return mMobileStates.get(0);
+        }
+
+        return null;
+    }
+
 
     /**
      * It is expected that a call to setSubs will be immediately followed by setMobileDataIndicators
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 4ec9ae8..b814478 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -565,10 +565,12 @@
 
         @Override
         public boolean onKeyPreIme(int keyCode, KeyEvent event) {
-            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
-                mRemoteInputView.mRemoteInputQuickSettingsDisabler.setRemoteInputActive(false);
+            // When BACK key is pressed, this method would be invoked twice.
+            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK &&
+                    event.getAction() == KeyEvent.ACTION_UP) {
+                defocusIfNeeded(true /* animate */);
             }
-            return super.dispatchKeyEvent(event);
+            return super.onKeyPreIme(keyCode, event);
         }
 
         @Override
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 f91016a..7b9e711 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -388,6 +388,7 @@
                     return object.getDarkAmount();
                 }
             };
+    private ObjectAnimator mDarkAmountAnimator;
     private boolean mUsingLightTheme;
     private boolean mQsExpanded;
     private boolean mForwardScrollable;
@@ -775,7 +776,8 @@
             boolean clip = clipStart > start && clipStart < end
                     || clipEnd >= start && clipEnd <= end;
             clip &= !(first && mOwnScrollY == 0);
-            child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0) : -1);
+            child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0)
+                    : ExpandableView.NO_ROUNDNESS);
             first = false;
         }
     }
@@ -3401,7 +3403,7 @@
                             .animateY(mShelf));
             ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex;
             mAnimationEvents.add(ev);
-            startBackgroundFade();
+            startDarkAmountAnimation();
         }
         mDarkNeedsAnimation = false;
     }
@@ -3979,6 +3981,9 @@
             mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation);
             mNeedsAnimation =  true;
         } else {
+            if (mDarkAmountAnimator != null) {
+                mDarkAmountAnimator.cancel();
+            }
             setDarkAmount(dark ? 1f : 0f);
             updateBackground();
         }
@@ -4023,12 +4028,22 @@
         return mDarkAmount;
     }
 
-    private void startBackgroundFade() {
-        ObjectAnimator fadeAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount,
+    private void startDarkAmountAnimation() {
+        ObjectAnimator darkAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount,
                 mAmbientState.isDark() ? 1f : 0);
-        fadeAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
-        fadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
-        fadeAnimator.start();
+        darkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
+        darkAnimator.setInterpolator(Interpolators.ALPHA_IN);
+        darkAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mDarkAmountAnimator = null;
+            }
+        });
+        if (mDarkAmountAnimator != null) {
+            mDarkAmountAnimator.cancel();
+        }
+        mDarkAmountAnimator = darkAnimator;
+        mDarkAmountAnimator.start();
     }
 
     private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 8034345..bf962b8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -344,13 +344,17 @@
       int supplementalIconId, @Nullable View.OnClickListener supplementalIconOnClickListener) {
     SeekbarListItem listItem = new SeekbarListItem(mContext);
     listItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId));
+    int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint);
     int progress = getSeekbarValue(mCarAudioManager, volumeGroupId);
     listItem.setProgress(progress);
     listItem.setOnSeekBarChangeListener(
         new CarVolumeDialogImpl.VolumeSeekBarChangeListener(volumeGroupId, mCarAudioManager));
-    listItem.setPrimaryActionIcon(mContext.getResources().getDrawable(volumeItem.icon));
+    Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon);
+    primaryIcon.setTint(color);
+    listItem.setPrimaryActionIcon(primaryIcon);
     if (supplementalIconId != 0) {
       Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId);
+      supplementalIcon.setTint(color);
       listItem.setSupplementalIcon(supplementalIcon, true,
           supplementalIconOnClickListener);
     } else {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 4588675..955939c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -43,8 +43,10 @@
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
 import android.graphics.drawable.ColorDrawable;
 import android.media.AudioManager;
 import android.media.AudioSystem;
@@ -90,6 +92,7 @@
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.plugins.VolumeDialogController.State;
 import com.android.systemui.plugins.VolumeDialogController.StreamState;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
@@ -131,8 +134,10 @@
     private final AccessibilityManagerWrapper mAccessibilityMgr;
     private final Object mSafetyWarningLock = new Object();
     private final Accessibility mAccessibility = new Accessibility();
-    private final ColorStateList mActiveTint;
-    private final ColorStateList mInactiveTint;
+    private ColorStateList mActiveTint;
+    private int mActiveAlpha;
+    private ColorStateList mInactiveTint;
+    private int mInactiveAlpha;
 
     private boolean mShowing;
     private boolean mShowA11yStream;
@@ -150,8 +155,6 @@
         mController = Dependency.get(VolumeDialogController.class);
         mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
         mAccessibilityMgr = Dependency.get(AccessibilityManagerWrapper.class);
-        mActiveTint = Utils.getColorAccent(mContext);
-        mInactiveTint = loadColorStateList(R.color.volume_slider_inactive);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
     }
 
@@ -224,6 +227,11 @@
             return true;
         });
 
+        mActiveTint = Utils.getColorAccent(mContext);
+        mActiveAlpha = Color.alpha(mActiveTint.getDefaultColor());
+        mInactiveTint = Utils.getColorAttr(mContext, android.R.attr.colorForeground);
+        mInactiveAlpha = getAlphaAttr(android.R.attr.secondaryContentAlpha);
+
         mDialogRowsView = mDialog.findViewById(R.id.volume_dialog_rows);
         mRinger = mDialog.findViewById(R.id.ringer);
         mRingerIcon = mRinger.findViewById(R.id.ringer_icon);
@@ -263,8 +271,11 @@
         return mDialogView;
     }
 
-    private ColorStateList loadColorStateList(int colorResId) {
-        return ColorStateList.valueOf(mContext.getColor(colorResId));
+    private int getAlphaAttr(int attr) {
+        TypedArray ta = mContext.obtainStyledAttributes(new int[]{attr});
+        float alpha = ta.getFloat(0, 0);
+        ta.recycle();
+        return (int) (alpha * 255);
     }
 
     private boolean isLandscape() {
@@ -890,12 +901,16 @@
         if (isActive) {
             row.slider.requestFocus();
         }
-        final ColorStateList tint = isActive && row.slider.isEnabled() ? mActiveTint
-                : mInactiveTint;
+        boolean useActiveColoring = isActive && row.slider.isEnabled();
+        final ColorStateList tint = useActiveColoring ? mActiveTint : mInactiveTint;
+        final int alpha = useActiveColoring ? mActiveAlpha : mInactiveAlpha;
         if (tint == row.cachedTint) return;
         row.slider.setProgressTintList(tint);
         row.slider.setThumbTintList(tint);
+        row.slider.setProgressBackgroundTintList(tint);
+        row.slider.setAlpha(((float) alpha) / 255);
         row.icon.setImageTintList(tint);
+        row.icon.setImageAlpha(alpha);
         row.cachedTint = tint;
     }
 
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 8340ab2..85135ac 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
@@ -16,14 +16,12 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -170,6 +168,15 @@
         verify(mBouncer, never()).setExpansion(eq(0.5f));
     }
 
+    @Test
+    public void onPanelExpansionChanged_neverTranslatesBouncerWhenWakeAndUnlock() {
+        when(mFingerprintUnlockController.getMode())
+                .thenReturn(FingerprintUnlockController.MODE_WAKE_AND_UNLOCK);
+        mStatusBarKeyguardViewManager.onPanelExpansionChanged(KeyguardBouncer.EXPANSION_VISIBLE,
+                false /* tracking */);
+        verify(mBouncer, never()).setExpansion(anyFloat());
+    }
+
     private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
 
         public TestableStatusBarKeyguardViewManager(Context context,
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index c67a9f8..d2990de 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3986,27 +3986,44 @@
     // OS: O
     APP_TRANSITION_IS_EPHEMERAL = 905;
 
-    // An autofill session was started
+    // An autofill session was started.
+    // OS: O
     // Package: Package of app that is autofilled
     // NOTE: starting on OS MR1, it also added the following field:
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // NOTE: starting on OS P, it also added the following field:
-    // Tag FIELD_FLAGS - Flags used to start the session
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFIL_FLAGS: flags used to start the session.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session started.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SESSION_STARTED = 906;
 
     // An autofill request was processed by a service
-    // Type TYPE_SUCCESS: The request succeeded
-    // Type TYPE_FAILURE: The request failed
+    // Type TYPE_SUCCESS: service called FillCalback.onSuccess()
+    // Type TYPE_FAILURE: service called FillCallback.onFailure()
     // Package: Package of app that is autofilled
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets returned in the response, or -1 if
-    // the service returned a null response.
-    // NOTE: starting on OS P, it also added:
-    // Type TYPE_CLOSE: Service returned a null response.
+    // the service returned a null response
+    // NOTE: starting on OS P, it also added the following fields:
+    // TYPE_CLOSE: request timed out before service called a FillCallback method
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_REQUEST_ORDINAL: sequence number of the request inside a session; starts
+    //     with 1.
+    // Tag FIELD_AUTOFILL_FLAGS: flags used to request autofill
+    // Tag FIELD_AUTOFILL_DURATION: how long it took (in ms) to show the autofill UI after a field
+    //     was focused.
+    // Tag FIELD_AUTOFILL_AUTHENTICATION_STATUS: status of authenticated datasets or responses.
     // Tag FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS: if service requested field classification,
-    // number of entries field ids in the request.
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    //     number of entries field ids in the request.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: Prior to P, some of the fields above were logged by 5 different metrics:
+    // - AUTOFILL_UI_LATENCY
+    // - AUTOFILL_AUTHENTICATED;
+    // - AUTOFILL_DATASET_AUTHENTICATED
+    // - AUTOFILL_INVALID_AUTHENTICATION
+    // - AUTOFILL_INVALID_DATASET_AUTHENTICATION
     AUTOFILL_REQUEST = 907;
 
     // Tag of a field for a package of an autofill service
@@ -4023,9 +4040,11 @@
     // Package: Package of app that was autofilled
     // Tag FIELD_AUTOFILL_FILTERTEXT_LEN: The length of the filter text
     // Tag FIELD_AUTOFILL_NUM_DATASETS: The number of datasets shown
-    // NOTE: starting on OS P, it also added the following field:
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_FILL_UI = 910;
 
     // Tag of a field for the length of the filter text
@@ -4034,16 +4053,17 @@
     // An autofill authentication succeeded
     // Package: Package of app that was autofilled
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, this metric became a value for FIELD_AUTOFILL_AUTHENTICATION_STATUS
     AUTOFILL_AUTHENTICATED = 912;
 
     // An activity was autofilled and all values could be applied
     // Package: Package of app that is autofilled
     // Tag FIELD_AUTOFILL_NUM_VALUES: Number of values that were suggested to be autofilled
     // Tag FIELD_AUTOFILL_NUM_VIEWS_FILLED: Number of views that could be filled
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_DATASET_APPLIED = 913;
 
     // Tag of a field for the number values to be filled in
@@ -4058,28 +4078,37 @@
     // Type TYPE_ACTION: data was saved
     // Package: Package of app that was autofilled
     // Tag FIELD_AUTOFILL_NUM_IDS: The number of ids that are saved
-    // NOTE: starting on OS P, it also added the following field:
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SAVE_UI = 916;
 
     // Tag of a field for the number of saveable ids
     FIELD_AUTOFILL_NUM_IDS = 917;
 
-    // ACTION: An autofill service was reqiested to save data
+    // ACTION: An autofill service was requested to save data
     // Type TYPE_SUCCESS: The request succeeded right away
     // Type TYPE_OPEN: The request succeeded but the service launched an IntentSender
     // Type TYPE_FAILURE: The request failed
     // Package: Package of app that was autofilled
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_DATA_SAVE_REQUEST = 918;
 
     // An auto-fill session was finished
+    // OS: O
     // Package: Package of app that was autofilled
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_AUTOFILL_NUMBER_REQUESTS: number of requests made to the service (each request
+    //     is logged by a separate AUTOFILL_REQUEST metric)
     AUTOFILL_SESSION_FINISHED = 919;
 
     // meta-event: a reader has checkpointed the log here.
@@ -4206,7 +4235,7 @@
     // Tag FIELD_AUTOFILL_SERVICE: Package of the autofill service that processed the request
     // TAG FIELD_AUTOFILL_FORGED_COMPONENT_NAME: Component name being forged
     // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_FORGED_COMPONENT_ATTEMPT = 948;
 
     // FIELD - The component that an app tried tro forged.
@@ -4664,8 +4693,10 @@
     // OS: O MR
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_PREVIOUS_LENGTH: the previous length of the value
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_VALUE_RESET = 1124;
 
     // Tag of AUTOFILL_VALUE_RESET
@@ -4675,25 +4706,21 @@
     // An autofill dataset authentication succeeded
     // Package: Package of app that was autofilled
     // OS: O MR
-    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, this metric became a value for FIELD_AUTOFILL_AUTHENTICATION_STATUS
     AUTOFILL_DATASET_AUTHENTICATED = 1126;
 
     // An autofill service provided an invalid dataset authentication
     // Package: Package of app that was autofilled
     // OS: O MR
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, this metric became a value for FIELD_AUTOFILL_AUTHENTICATION_STATUS
     AUTOFILL_INVALID_DATASET_AUTHENTICATION = 1127;
 
     // An autofill service provided an invalid authentication extra
     // Package: Package of app that was autofilled
     // OS: O MR
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, this metric became a value for FIELD_AUTOFILL_AUTHENTICATION_STATUS
     AUTOFILL_INVALID_AUTHENTICATION = 1128;
 
     // An autofill service used a custom description (using RemoteViews) in the autofill save UI
@@ -4701,8 +4728,10 @@
     // OS: O MR
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SAVE_CUSTOM_DESCRIPTION = 1129;
 
     // FIELD - Type of save object passed by the service when the Save UI is shown
@@ -4714,8 +4743,10 @@
     // OS: O MR
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SAVE_CUSTOM_SUBTITLE = 1131;
 
     // User tapped a link in the custom description of the autofill save UI provided by an autofill service
@@ -4726,8 +4757,10 @@
     // Type TYPE_FAILURE: The link could not launc an activity
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SAVE_LINK_TAPPED = 1132;
 
     // Result of the validation on save when an autofill service provided a validator
@@ -4738,8 +4771,10 @@
     // Type TYPE_DISMISS: The validation failed
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SAVE_VALIDATION = 1133;
 
     // Result of an operation in the autofill save UI after the user tapped a link in the custom description
@@ -4749,8 +4784,10 @@
     // Type TYPE_OPEN: The autofill save UI was restored
     // Type TYPE_DISMISS: The autofill save UI was destroyed
     // Type TYPE_FAILURE: An invalid opperation was reported by the app's AutofillManager
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // NOTE: starting on OS P, it also added the following fields:
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_PENDING_SAVE_UI_OPERATION = 1134;
 
     // Autofill service called API that disables itself
@@ -4758,13 +4795,12 @@
     // OS: O MR
     AUTOFILL_SERVICE_DISABLED_SELF = 1135;
 
+    // DEPRECATED - on P it was merged with AUTOFILL_REQUEST
     // Reports how long it took to show the autofill UI after a field was focused
     // Tag FIELD_AUTOFILL_DURATION: Duration in ms
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Package: Package of the autofill service
     // OS: O MR
-    // NOTE: starting on OS P, it also added the following field:
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_UI_LATENCY = 1136;
 
     // Action: the snooze leave-behind was shown after the user clicked the snooze icon
@@ -4931,15 +4967,19 @@
     // An autofill service explicitly defined which view should commit the autofill context
     // Package: Package of app that is autofilled
     // OS: P
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_EXPLICIT_SAVE_TRIGGER_DEFINITION = 1228;
 
     // The autofill context was commited when the user clicked a view explicitly marked by the
     // service as committing it
     // Package: Package of app that is autofilled
     // OS: P
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SAVE_EXPLICITLY_TRIGGERED = 1229;
 
     // OPEN: Settings > Network & Internet > Mobile network > Wi-Fi calling
@@ -4952,7 +4992,8 @@
     // OS: P
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_DURATION: duration (in ms) that autofill will be disabled
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SERVICE_DISABLED_APP = 1231;
 
     // An autofill service asked to disable autofill for a given activity.
@@ -4961,7 +5002,8 @@
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_CLASS_NAME: Class name of the activity that is being disabled for autofill
     // Tag FIELD_AUTOFILL_DURATION: duration (in ms) that autofill will be disabled
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_SERVICE_DISABLED_ACTIVITY = 1232;
 
     // ACTION: Stop an app and turn on background check
@@ -5171,9 +5213,11 @@
     // Package: Package of app that is autofilled
     // Counter: number of matches found
     // OS: P
+    // Tag FIELD_CLASS_NAME: Class name of the activity that is autofilled.
     // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
     // Tag FIELD_AUTOFILL_MATCH_SCORE: Average score of the matches, in the range of 0 to 100
-    // Type FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
+    // Tag FIELD_AUTOFILL_SESSION_ID: id of the autofill session associated with this metric.
+    // Tag FIELD_AUTOFILL_COMPAT_MODE: package is being autofilled on compatibility mode.
     AUTOFILL_FIELD_CLASSIFICATION_MATCHES = 1273;
 
     // Tag used to report autofill field classification scores
@@ -5840,6 +5884,7 @@
     ACTION_STORAGE_MIGRATE_LATER = 1413;
 
     // Tag used to report whether an activity is being autofilled  on compatibility mode.
+    // OS: P
     FIELD_AUTOFILL_COMPAT_MODE = 1414;
 
     // OPEN: Settings > Sound > Switch a2dp devices dialog
@@ -6045,6 +6090,32 @@
     // OS: P
     ACTION_BATTERY_CAUSED_SHUTDOWN = 1451;
 
+    // FIELD: Flags used on autofill-related metrics
+    // OS: P
+    FIELD_AUTOFILL_FLAGS = 1452;
+
+    // Tag used when the service returned an authenticated dataset or response.
+    // Used to replace the following individual metrics, which now are logged as the value of this
+    // field in the AUTOFILL_REQUEST metric:
+    // - AUTOFILL_AUTHENTICATED;
+    // - AUTOFILL_DATASET_AUTHENTICATED
+    // - AUTOFILL_INVALID_AUTHENTICATION
+    // - AUTOFILL_INVALID_DATASET_AUTHENTICATION
+    // OS: P
+    FIELD_AUTOFILL_AUTHENTICATION_STATUS = 1453;
+
+    // FIELD: Index of the autofill request inside of a session.
+    // OS: P
+    FIELD_AUTOFILL_REQUEST_ORDINAL = 1454;
+
+    // FIELD: Number of requests made to an autofill service during a session.
+    // OS: P
+    FIELD_AUTOFILL_NUMBER_REQUESTS = 1455;
+
+    // FIELD: Id of the autofill session associated with this metric.
+    // OS: P
+    FIELD_AUTOFILL_SESSION_ID = 1456;
+
     // ---- End P Constants, all P constants go above this line ----
 
     // First Q constant in master goes here:
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index d97253e..1ccce17 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -537,11 +537,17 @@
             final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid;
             Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid
                     + ") passed component (" + componentName + ") owned by UID " + packageUid);
-            mMetricsLogger.write(
-                    Helper.newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT,
-                            callingPackage, getServicePackageName(), compatMode)
+
+            // NOTE: not using Helper.newLogMaker() because we don't have the session id
+            final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT)
+                    .setPackageName(callingPackage)
+                    .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, getServicePackageName())
                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME,
-                            componentName == null ? "null" : componentName.flattenToShortString()));
+                            componentName == null ? "null" : componentName.flattenToShortString());
+            if (compatMode) {
+                log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, 1);
+            }
+            mMetricsLogger.write(log);
 
             throw new SecurityException("Invalid component: " + componentName);
         }
@@ -780,10 +786,10 @@
             @Nullable ArrayList<String> changedDatasetIds,
             @Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
             @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
-            @NonNull String appPackageName, boolean compatMode) {
+            @NonNull ComponentName appComponentName, boolean compatMode) {
         logContextCommittedLocked(sessionId, clientState, selectedDatasets, ignoredDatasets,
                 changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
-                manuallyFilledDatasetIds, null, null, appPackageName, compatMode);
+                manuallyFilledDatasetIds, null, null, appComponentName, compatMode);
     }
 
     @GuardedBy("mLock")
@@ -796,7 +802,7 @@
             @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
             @Nullable ArrayList<AutofillId> detectedFieldIdsList,
             @Nullable ArrayList<FieldClassification> detectedFieldClassificationsList,
-            @NonNull String appPackageName, boolean compatMode) {
+            @NonNull ComponentName appComponentName, boolean compatMode) {
         if (isValidEventLocked("logDatasetNotSelected()", sessionId)) {
             if (sVerbose) {
                 Slog.v(TAG, "logContextCommitted() with FieldClassification: id=" + sessionId
@@ -807,6 +813,7 @@
                         + ", manuallyFilledFieldIds=" + manuallyFilledFieldIds
                         + ", detectedFieldIds=" + detectedFieldIdsList
                         + ", detectedFieldClassifications=" + detectedFieldClassificationsList
+                        + ", appComponentName=" + appComponentName.toShortString()
                         + ", compatMode=" + compatMode);
             }
             AutofillId[] detectedFieldsIds = null;
@@ -834,7 +841,7 @@
                 final int averageScore = (int) ((totalScore * 100) / totalSize);
                 mMetricsLogger.write(Helper
                         .newLogMaker(MetricsEvent.AUTOFILL_FIELD_CLASSIFICATION_MATCHES,
-                                appPackageName, getServicePackageName(), compatMode)
+                                appComponentName, getServicePackageName(), sessionId, compatMode)
                         .setCounterValue(numberFields)
                         .addTaggedData(MetricsEvent.FIELD_AUTOFILL_MATCH_SCORE,
                                 averageScore));
@@ -889,9 +896,11 @@
             }
             mUserData = userData;
             // Log it
-            int numberFields = mUserData == null ? 0: mUserData.getCategoryIds().length;
-            mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_USERDATA_UPDATED,
-                    getServicePackageName(), null)
+            final int numberFields = mUserData == null ? 0: mUserData.getCategoryIds().length;
+            // NOTE: contrary to most metrics, the service name is logged as the main package name
+            // here, not as MetricsEvent.FIELD_AUTOFILL_SERVICE
+            mMetricsLogger.write(new LogMaker(MetricsEvent.AUTOFILL_USERDATA_UPDATED)
+                    .setPackageName(getServicePackageName())
                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, numberFields));
         }
     }
@@ -1130,7 +1139,8 @@
     /**
      * Called by {@link Session} when service asked to disable autofill for an app.
      */
-    void disableAutofillForApp(@NonNull String packageName, long duration, boolean compatMode) {
+    void disableAutofillForApp(@NonNull String packageName, long duration, int sessionId,
+            boolean compatMode) {
         synchronized (mLock) {
             if (mDisabledApps == null) {
                 mDisabledApps = new ArrayMap<>(1);
@@ -1143,7 +1153,7 @@
             mDisabledApps.put(packageName, expiration);
             int intDuration = duration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) duration;
             mMetricsLogger.write(Helper.newLogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_APP,
-                    packageName, getServicePackageName(), compatMode)
+                    packageName, getServicePackageName(), sessionId, compatMode)
                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_DURATION, intDuration));
         }
     }
@@ -1152,7 +1162,7 @@
      * Called by {@link Session} when service asked to disable autofill an app.
      */
     void disableAutofillForActivity(@NonNull ComponentName componentName, long duration,
-            boolean compatMode) {
+            int sessionId, boolean compatMode) {
         synchronized (mLock) {
             if (mDisabledActivities == null) {
                 mDisabledActivities = new ArrayMap<>(1);
@@ -1163,14 +1173,20 @@
                 expiration = Long.MAX_VALUE;
             }
             mDisabledActivities.put(componentName, expiration);
-            final int intDuration = duration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) duration;
+            final int intDuration = duration > Integer.MAX_VALUE
+                    ? Integer.MAX_VALUE
+                    : (int) duration;
             // NOTE: not using Helper.newLogMaker() because we're setting the componentName instead
             // of package name
-            mMetricsLogger.write(new LogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_ACTIVITY)
+            final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_SERVICE_DISABLED_ACTIVITY)
                     .setComponentName(componentName)
                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, getServicePackageName())
                     .addTaggedData(MetricsEvent.FIELD_AUTOFILL_DURATION, intDuration)
-                    .addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, compatMode ? 1 : 0));
+                    .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SESSION_ID, sessionId);
+            if (compatMode) {
+                log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, 1);
+            }
+            mMetricsLogger.write(log);
         }
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index f781013..cf310e9 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.app.assist.AssistStructure;
 import android.app.assist.AssistStructure.ViewNode;
+import android.content.ComponentName;
 import android.metrics.LogMaker;
 import android.service.autofill.Dataset;
 import android.util.ArrayMap;
@@ -109,20 +110,29 @@
     }
 
     @NonNull
-    public static LogMaker newLogMaker(int category, String packageName,
-            String servicePackageName) {
-        final LogMaker log = new LogMaker(category).setPackageName(packageName);
-        if (servicePackageName != null) {
-            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+    private static LogMaker newLogMaker(int category, @NonNull String servicePackageName,
+            int sessionId, boolean compatMode) {
+        final LogMaker log = new LogMaker(category)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SESSION_ID, sessionId);
+        if (compatMode) {
+            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, 1);
         }
         return log;
     }
 
     @NonNull
-    public static LogMaker newLogMaker(int category, String packageName,
-            String servicePackageName, boolean compatMode) {
-        return newLogMaker(category, packageName, servicePackageName)
-                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE, compatMode ? 1 : 0);
+    public static LogMaker newLogMaker(int category, @NonNull String packageName,
+            @NonNull String servicePackageName, int sessionId, boolean compatMode) {
+        return newLogMaker(category, servicePackageName, sessionId, compatMode)
+                .setPackageName(packageName);
+    }
+
+    @NonNull
+    public static LogMaker newLogMaker(int category, @NonNull ComponentName componentName,
+            @NonNull String servicePackageName, int sessionId, boolean compatMode) {
+        return newLogMaker(category, servicePackageName, sessionId, compatMode)
+                .setComponentName(componentName);
     }
 
     public static void printlnRedactedText(@NonNull PrintWriter pw, @Nullable CharSequence text) {
@@ -193,6 +203,18 @@
         return urlBarNode;
     }
 
+    /**
+     * Gets the value of a metric tag, or {@code 0} if not found or NaN.
+     */
+    static int getNumericValue(@NonNull LogMaker log, int tag) {
+        final Object value = log.getTaggedData(tag);
+        if (!(value instanceof Number)) {
+            return 0;
+        } else {
+            return ((Number) value).intValue();
+        }
+    }
+
     private interface ViewNodeFilter {
         boolean matches(ViewNode node);
     }
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 4ded3fe..3e932e8 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -99,12 +99,14 @@
     private PendingRequest mPendingRequest;
 
     public interface FillServiceCallbacks {
-        void onFillRequestSuccess(int requestFlags, @Nullable FillResponse response,
+        void onFillRequestSuccess(int requestId, @Nullable FillResponse response,
+                @NonNull String servicePackageName, int requestFlags);
+        void onFillRequestFailure(int requestId, @Nullable CharSequence message,
                 @NonNull String servicePackageName);
-        void onFillRequestFailure(@Nullable CharSequence message,
-                @NonNull String servicePackageName);
+        void onFillRequestTimeout(int requestId, @NonNull String servicePackageName);
         void onSaveRequestSuccess(@NonNull String servicePackageName,
                 @Nullable IntentSender intentSender);
+        // TODO(b/80093094): add timeout here too?
         void onSaveRequestFailure(@Nullable CharSequence message,
                 @NonNull String servicePackageName);
         void onServiceDied(RemoteFillService service);
@@ -301,21 +303,31 @@
         mContext.unbindService(mServiceConnection);
     }
 
-    private void dispatchOnFillRequestSuccess(PendingRequest pendingRequest, int requestFlags,
-            FillResponse response) {
+    private void dispatchOnFillRequestSuccess(@NonNull PendingFillRequest pendingRequest,
+            @Nullable FillResponse response, int requestFlags) {
         mHandler.post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onFillRequestSuccess(requestFlags, response,
+                mCallbacks.onFillRequestSuccess(pendingRequest.mRequest.getId(), response,
+                        mComponentName.getPackageName(), requestFlags);
+            }
+        });
+    }
+
+    private void dispatchOnFillRequestFailure(@NonNull PendingFillRequest pendingRequest,
+            @Nullable CharSequence message) {
+        mHandler.post(() -> {
+            if (handleResponseCallbackCommon(pendingRequest)) {
+                mCallbacks.onFillRequestFailure(pendingRequest.mRequest.getId(), message,
                         mComponentName.getPackageName());
             }
         });
     }
 
-    private void dispatchOnFillRequestFailure(PendingRequest pendingRequest,
-            @Nullable CharSequence message) {
+    private void dispatchOnFillRequestTimeout(@NonNull PendingFillRequest pendingRequest) {
         mHandler.post(() -> {
             if (handleResponseCallbackCommon(pendingRequest)) {
-                mCallbacks.onFillRequestFailure(message, mComponentName.getPackageName());
+                mCallbacks.onFillRequestTimeout(pendingRequest.mRequest.getId(),
+                        mComponentName.getPackageName());
             }
         });
     }
@@ -538,18 +550,18 @@
                     final RemoteFillService remoteService = getService();
                     if (remoteService != null) {
                         remoteService.dispatchOnFillRequestSuccess(PendingFillRequest.this,
-                                request.getFlags(), response);
+                                response, request.getFlags());
                     }
                 }
 
                 @Override
-                public void onFailure(CharSequence message) {
+                public void onFailure(int requestId, CharSequence message) {
                     if (!finish()) return;
 
                     final RemoteFillService remoteService = getService();
                     if (remoteService != null) {
-                        remoteService.dispatchOnFillRequestFailure(
-                                PendingFillRequest.this, message);
+                        remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this,
+                                message);
                     }
                 }
             };
@@ -566,7 +578,7 @@
             if (cancellation != null) {
                 remoteService.dispatchOnFillTimeout(cancellation);
             }
-            remoteService.dispatchOnFillRequestFailure(PendingFillRequest.this, null);
+            remoteService.dispatchOnFillRequestTimeout(PendingFillRequest.this);
         }
 
         @Override
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 4b67bb1..09f4135 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -27,6 +27,7 @@
 import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static com.android.server.autofill.Helper.getNumericValue;
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sPartitionMaxCount;
 import static com.android.server.autofill.Helper.sVerbose;
@@ -93,6 +94,7 @@
 import com.android.server.autofill.ui.PendingUi;
 
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -176,7 +178,7 @@
 
     /**
      * Contexts read from the app; they will be updated (sanitized, change values for save) before
-     * sent to {@link AutofillService}. Ordered by the time they we read.
+     * sent to {@link AutofillService}. Ordered by the time they were read.
      */
     @GuardedBy("mLock")
     private ArrayList<FillContext> mContexts;
@@ -231,6 +233,12 @@
     private final LocalLog mWtfHistory;
 
     /**
+     * Map of {@link MetricsEvent#AUTOFILL_REQUEST} metrics, keyed by fill request id.
+     */
+    @GuardedBy("mLock")
+    private final SparseArray<LogMaker> mRequestLogs = new SparseArray<>(1);
+
+    /**
      * Receiver of assist data from the app's {@link Activity}.
      */
     private final IAssistDataReceiver mAssistReceiver = new IAssistDataReceiver.Stub() {
@@ -483,8 +491,18 @@
             requestId = sIdCounter.getAndIncrement();
         } while (requestId == INVALID_REQUEST_ID);
 
+        // Create a metrics log for the request
+        final int ordinal = mRequestLogs.size() + 1;
+        final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_REQUEST_ORDINAL, ordinal);
+        if (flags != 0) {
+            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags);
+        }
+        mRequestLogs.put(requestId, log);
+
         if (sVerbose) {
-            Slog.v(TAG, "Requesting structure for requestId=" + requestId + ", flags=" + flags);
+            Slog.v(TAG, "Requesting structure for request #" + ordinal + " ,requestId="
+                    + requestId + ", flags=" + flags);
         }
 
         // If the focus changes very quickly before the first request is returned each focus change
@@ -537,7 +555,7 @@
         setClientLocked(client);
 
         mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_STARTED)
-                .addTaggedData(MetricsEvent.FIELD_FLAGS, flags));
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FLAGS, flags));
     }
 
     /**
@@ -604,21 +622,30 @@
 
     // FillServiceCallbacks
     @Override
-    public void onFillRequestSuccess(int requestFlags, @Nullable FillResponse response,
-            @NonNull String servicePackageName) {
+    public void onFillRequestSuccess(int requestId, @Nullable FillResponse response,
+            @NonNull String servicePackageName, int requestFlags) {
         final AutofillId[] fieldClassificationIds;
 
+        final LogMaker requestLog;
+
         synchronized (mLock) {
             if (mDestroyed) {
                 Slog.w(TAG, "Call to Session#onFillRequestSuccess() rejected - session: "
                         + id + " destroyed");
                 return;
             }
+
+            requestLog = mRequestLogs.get(requestId);
+            if (requestLog != null) {
+                requestLog.setType(MetricsEvent.TYPE_SUCCESS);
+            } else {
+                Slog.w(TAG, "onFillRequestSuccess(): no request log for id " + requestId);
+            }
             if (response == null) {
+                if (requestLog != null) {
+                    requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1);
+                }
                 processNullResponseLocked(requestFlags);
-                mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
-                        .setType(MetricsEvent.TYPE_SUCCESS)
-                        .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS, -1));
                 return;
             }
 
@@ -645,10 +672,11 @@
                 Slog.d(TAG, message.toString());
             }
             if ((flags & FillResponse.FLAG_DISABLE_ACTIVITY_ONLY) != 0) {
-                mService.disableAutofillForActivity(mComponentName, disableDuration, mCompatMode);
+                mService.disableAutofillForActivity(mComponentName, disableDuration,
+                        id, mCompatMode);
             } else {
                 mService.disableAutofillForApp(mComponentName.getPackageName(), disableDuration,
-                        mCompatMode);
+                        id, mCompatMode);
             }
             sessionFinishedState = AutofillManager.STATE_DISABLED_BY_SERVICE;
         }
@@ -659,38 +687,54 @@
             // Response is "empty" from an UI point of view, need to notify client.
             notifyUnavailableToClient(sessionFinishedState);
         }
+
+        if (requestLog != null) {
+            requestLog.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
+                            response.getDatasets() == null ? 0 : response.getDatasets().size());
+            if (fieldClassificationIds != null) {
+                requestLog.addTaggedData(
+                        MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS,
+                        fieldClassificationIds.length);
+            }
+        }
+
         synchronized (mLock) {
             processResponseLocked(response, null, requestFlags);
         }
-
-        final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
-                .setType(MetricsEvent.TYPE_SUCCESS)
-                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
-                        response.getDatasets() == null ? 0 : response.getDatasets().size());
-        if (fieldClassificationIds != null) {
-            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS,
-                    fieldClassificationIds.length);
-        }
-        mMetricsLogger.write(log);
     }
 
     // FillServiceCallbacks
     @Override
-    public void onFillRequestFailure(@Nullable CharSequence message,
+    public void onFillRequestFailure(int requestId, @Nullable CharSequence message,
             @NonNull String servicePackageName) {
+        onFillRequestFailureOrTimeout(requestId, false, message, servicePackageName);
+    }
+
+    // FillServiceCallbacks
+    @Override
+    public void onFillRequestTimeout(int requestId, @NonNull String servicePackageName) {
+        onFillRequestFailureOrTimeout(requestId, true, null, servicePackageName);
+    }
+
+    private void onFillRequestFailureOrTimeout(int requestId, boolean timedOut,
+            @Nullable CharSequence message, @NonNull String servicePackageName) {
         synchronized (mLock) {
             if (mDestroyed) {
-                Slog.w(TAG, "Call to Session#onFillRequestFailure() rejected - session: "
-                        + id + " destroyed");
+                Slog.w(TAG, "Call to Session#onFillRequestFailureOrTimeout(req=" + requestId
+                        + ") rejected - session: " + id + " destroyed");
                 return;
             }
             mService.resetLastResponse();
+            final LogMaker requestLog = mRequestLogs.get(requestId);
+            if (requestLog == null) {
+                Slog.w(TAG, "onFillRequestFailureOrTimeout(): no log for id " + requestId);
+            } else {
+                requestLog.setType(timedOut ? MetricsEvent.TYPE_CLOSE : MetricsEvent.TYPE_FAILURE);
+            }
         }
-        LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
-                .setType(MetricsEvent.TYPE_FAILURE);
-        mMetricsLogger.write(log);
-
-        getUiForShowing().showError(message, this);
+        if (message != null) {
+            getUiForShowing().showError(message, this);
+        }
         removeSelf();
     }
 
@@ -973,11 +1017,12 @@
                     + ", clientState=" + newClientState);
         }
         if (result instanceof FillResponse) {
-            writeLog(MetricsEvent.AUTOFILL_AUTHENTICATED);
+            logAuthenticationStatusLocked(requestId, MetricsEvent.AUTOFILL_AUTHENTICATED);
             replaceResponseLocked(authenticatedResponse, (FillResponse) result, newClientState);
         } else if (result instanceof Dataset) {
             if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) {
-                writeLog(MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
+                logAuthenticationStatusLocked(requestId,
+                        MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
                 if (newClientState != null) {
                     if (sDebug) Slog.d(TAG,  "Updating client state from auth dataset");
                     mClientState = newClientState;
@@ -986,13 +1031,15 @@
                 authenticatedResponse.getDatasets().set(datasetIdx, dataset);
                 autoFill(requestId, datasetIdx, dataset, false);
             } else {
-                writeLog(MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION);
+                logAuthenticationStatusLocked(requestId,
+                        MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION);
             }
         } else {
             if (result != null) {
                 Slog.w(TAG, "service returned invalid auth type: " + result);
             }
-            writeLog(MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION);
+            logAuthenticationStatusLocked(requestId,
+                    MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION);
             processNullResponseLocked(0);
         }
     }
@@ -1253,7 +1300,7 @@
             mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
                     ignoredDatasets, changedFieldIds, changedDatasetIds,
                     manuallyFilledFieldIds, manuallyFilledDatasetIds,
-                    mComponentName.getPackageName(), mCompatMode);
+                    mComponentName, mCompatMode);
         }
     }
 
@@ -1308,7 +1355,7 @@
                 mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
                         ignoredDatasets, changedFieldIds, changedDatasetIds,
                         manuallyFilledFieldIds, manuallyFilledDatasetIds,
-                        mComponentName.getPackageName(), mCompatMode);
+                        mComponentName, mCompatMode);
                 return;
             }
             final Scores scores = result.getParcelable(EXTRA_SCORES);
@@ -1373,7 +1420,7 @@
             mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
                     ignoredDatasets, changedFieldIds, changedDatasetIds, manuallyFilledFieldIds,
                     manuallyFilledDatasetIds, detectedFieldIds, detectedFieldClassifications,
-                    mComponentName.getPackageName(), mCompatMode);
+                    mComponentName, mCompatMode);
         });
 
         fcStrategy.getScores(callback, algorithm, algorithmArgs, currentValues, userValues);
@@ -1404,7 +1451,7 @@
          *   the current values of all fields in the screen.
          */
         if (saveInfo == null) {
-            if (sVerbose) Slog.w(TAG, "showSaveLocked(): no saveInfo from service");
+            if (sVerbose) Slog.v(TAG, "showSaveLocked(): no saveInfo from service");
             return true;
         }
 
@@ -1603,8 +1650,7 @@
                 mPendingSaveUi = new PendingUi(mActivityToken, id, client);
                 getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(),
                         mService.getServicePackageName(), saveInfo, this,
-                        mComponentName.getPackageName(), this,
-                        mPendingSaveUi, mCompatMode);
+                        mComponentName, this, mPendingSaveUi, mCompatMode);
                 if (client != null) {
                     try {
                         client.setSaveUiState(id, true);
@@ -2065,7 +2111,7 @@
     }
 
     @Override
-    public void onFillReady(FillResponse response, AutofillId filledId,
+    public void onFillReady(@NonNull FillResponse response, @NonNull AutofillId filledId,
             @Nullable AutofillValue value) {
         synchronized (mLock) {
             if (mDestroyed) {
@@ -2081,8 +2127,8 @@
         }
 
         getUiForShowing().showFillUi(filledId, response, filterText,
-                mService.getServicePackageName(), mComponentName.getPackageName(),
-                mService.getServiceLabel(), mService.getServiceIcon(), this, mCompatMode);
+                mService.getServicePackageName(), mComponentName,
+                mService.getServiceLabel(), mService.getServiceIcon(), this, id, mCompatMode);
 
         synchronized (mLock) {
             if (mUiShownTime == 0) {
@@ -2103,9 +2149,8 @@
                 TimeUtils.formatDuration(duration, historyLog);
                 mUiLatencyHistory.log(historyLog.toString());
 
-                final LogMaker metricsLog = newLogMaker(MetricsEvent.AUTOFILL_UI_LATENCY)
-                        .addTaggedData(MetricsEvent.FIELD_AUTOFILL_DURATION, duration);
-                mMetricsLogger.write(metricsLog);
+                addTaggedDataToRequestLogLocked(response.getRequestId(),
+                        MetricsEvent.FIELD_AUTOFILL_DURATION, duration);
             }
         }
     }
@@ -2474,6 +2519,14 @@
             TimeUtils.formatDuration(mUiShownTime - mStartTime, pw);
             pw.println();
         }
+        final int requestLogsSizes = mRequestLogs.size();
+        pw.print(prefix); pw.print("mSessionLogs: "); pw.println(requestLogsSizes);
+        for (int i = 0; i < requestLogsSizes; i++) {
+            final int requestId = mRequestLogs.keyAt(i);
+            final LogMaker log = mRequestLogs.valueAt(i);
+            pw.print(prefix2); pw.print('#'); pw.print(i); pw.print(": req=");
+            pw.print(requestId); pw.print(", log=" ); dumpRequestLog(pw, log); pw.println();
+        }
         pw.print(prefix); pw.print("mResponses: ");
         if (mResponses == null) {
             pw.println("null");
@@ -2532,6 +2585,56 @@
         mRemoteFillService.dump(prefix, pw);
     }
 
+    private static void dumpRequestLog(@NonNull PrintWriter pw, @NonNull LogMaker log) {
+        pw.print("CAT="); pw.print(log.getCategory());
+        pw.print(", TYPE=");
+        final int type = log.getType();
+        switch (type) {
+            case MetricsEvent.TYPE_SUCCESS: pw.print("SUCCESS"); break;
+            case MetricsEvent.TYPE_FAILURE: pw.print("FAILURE"); break;
+            case MetricsEvent.TYPE_CLOSE: pw.print("CLOSE"); break;
+            default: pw.print("UNSUPPORTED");
+        }
+        pw.print('('); pw.print(type); pw.print(')');
+        pw.print(", PKG="); pw.print(log.getPackageName());
+        pw.print(", SERVICE="); pw.print(log
+                .getTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE));
+        pw.print(", ORDINAL="); pw.print(log
+                .getTaggedData(MetricsEvent.FIELD_AUTOFILL_REQUEST_ORDINAL));
+        dumpNumericValue(pw, log, "FLAGS", MetricsEvent.FIELD_AUTOFILL_FLAGS);
+        dumpNumericValue(pw, log, "NUM_DATASETS", MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS);
+        dumpNumericValue(pw, log, "UI_LATENCY", MetricsEvent.FIELD_AUTOFILL_DURATION);
+        final int authStatus =
+                getNumericValue(log, MetricsEvent.FIELD_AUTOFILL_AUTHENTICATION_STATUS);
+        if (authStatus != 0) {
+            pw.print(", AUTH_STATUS=");
+            switch (authStatus) {
+                case MetricsEvent.AUTOFILL_AUTHENTICATED:
+                    pw.print("AUTHENTICATED"); break;
+                case MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED:
+                    pw.print("DATASET_AUTHENTICATED"); break;
+                case MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION:
+                    pw.print("INVALID_AUTHENTICATION"); break;
+                case MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION:
+                    pw.print("INVALID_DATASET_AUTHENTICATION"); break;
+                default: pw.print("UNSUPPORTED");
+            }
+            pw.print('('); pw.print(authStatus); pw.print(')');
+        }
+        dumpNumericValue(pw, log, "FC_IDS",
+                MetricsEvent.FIELD_AUTOFILL_NUM_FIELD_CLASSIFICATION_IDS);
+        dumpNumericValue(pw, log, "COMPAT_MODE",
+                MetricsEvent.FIELD_AUTOFILL_COMPAT_MODE);
+    }
+
+    private static void dumpNumericValue(@NonNull PrintWriter pw, @NonNull LogMaker log,
+            @NonNull String field, int tag) {
+        final int value = getNumericValue(log, tag);
+        if (value != 0) {
+            pw.print(", "); pw.print(field); pw.print('='); pw.print(value);
+        }
+    }
+
     void autoFillApp(Dataset dataset) {
         synchronized (mLock) {
             if (mDestroyed) {
@@ -2610,7 +2713,19 @@
         mUi.destroyAll(mPendingSaveUi, this, true);
         mUi.clearCallback(this);
         mDestroyed = true;
-        writeLog(MetricsEvent.AUTOFILL_SESSION_FINISHED);
+
+        // Log metrics
+        final int totalRequests = mRequestLogs.size();
+        if (totalRequests > 0) {
+            if (sVerbose) Slog.v(TAG, "destroyLocked(): logging " + totalRequests + " requests");
+            for (int i = 0; i < totalRequests; i++) {
+                final LogMaker log = mRequestLogs.valueAt(i);
+                mMetricsLogger.write(log);
+            }
+        }
+        mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_SESSION_FINISHED)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUMBER_REQUESTS, totalRequests));
+
         return mRemoteFillService;
     }
 
@@ -2719,14 +2834,36 @@
     }
 
     private LogMaker newLogMaker(int category, String servicePackageName) {
-        return Helper.newLogMaker(category, mComponentName.getPackageName(), servicePackageName,
-                mCompatMode);
+        return Helper.newLogMaker(category, mComponentName, servicePackageName, id, mCompatMode);
     }
 
     private void writeLog(int category) {
         mMetricsLogger.write(newLogMaker(category));
     }
 
+    private void logAuthenticationStatusLocked(int requestId, int status) {
+        addTaggedDataToRequestLogLocked(requestId,
+                MetricsEvent.FIELD_AUTOFILL_AUTHENTICATION_STATUS, status);
+    }
+
+    private void addTaggedDataToRequestLogLocked(int requestId, int tag, @Nullable Object value) {
+        final LogMaker requestLog = mRequestLogs.get(requestId);
+        if (requestLog == null) {
+            Slog.w(TAG,
+                    "addTaggedDataToRequestLogLocked(tag=" + tag + "): no log for id " + requestId);
+            return;
+        }
+        requestLog.addTaggedData(tag, value);
+    }
+
+    private static String requestLogToString(@NonNull LogMaker log) {
+        final StringWriter sw = new StringWriter();
+        final PrintWriter pw = new PrintWriter(sw);
+        dumpRequestLog(pw, log);
+        pw.flush();
+        return sw.toString();
+    }
+
     private void wtf(@Nullable Exception e, String fmt, Object...args) {
         final String message = String.format(fmt, args);
         mWtfHistory.log(message);
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index cff1a84..bb97e4a 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -19,6 +19,7 @@
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static com.android.server.autofill.Helper.sDebug;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Rect;
 import android.service.autofill.FillResponse;
@@ -40,7 +41,7 @@
         /**
          * Called when the fill UI is ready to be shown for this view.
          */
-        void onFillReady(FillResponse fillResponse, AutofillId focusedId,
+        void onFillReady(@NonNull FillResponse fillResponse, @NonNull AutofillId focusedId,
                 @Nullable AutofillValue value);
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 811d87be..c5e838a 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.IntentSender;
 import android.graphics.drawable.Drawable;
@@ -162,22 +163,25 @@
      * @param response the current fill response
      * @param filterText text of the view to be filled
      * @param servicePackageName package name of the autofill service filling the activity
-     * @param packageName package name of the activity that is filled
+     * @param componentName component name of the activity that is filled
      * @param serviceLabel label of autofill service
      * @param serviceIcon icon of autofill service
-     * @param callback Identifier for the caller
+     * @param callback identifier for the caller
+     * @param sessionId id of the autofill session
+     * @param compatMode whether the app is being autofilled in compatibility mode.
      */
     public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response,
             @Nullable String filterText, @Nullable String servicePackageName,
-            @NonNull String packageName, @NonNull CharSequence serviceLabel,
-            @NonNull Drawable serviceIcon, @NonNull AutoFillUiCallback callback, boolean compatMode) {
+            @NonNull ComponentName componentName, @NonNull CharSequence serviceLabel,
+            @NonNull Drawable serviceIcon, @NonNull AutoFillUiCallback callback, int sessionId,
+            boolean compatMode) {
         if (sDebug) {
             final int size = filterText == null ? 0 : filterText.length();
             Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars");
         }
         final LogMaker log = Helper
-                .newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, packageName, servicePackageName,
-                        compatMode)
+                .newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, componentName, servicePackageName,
+                        sessionId, compatMode)
                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN,
                         filterText == null ? 0 : filterText.length())
                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
@@ -262,17 +266,19 @@
      */
     public void showSaveUi(@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
             @Nullable String servicePackageName, @NonNull SaveInfo info,
-            @NonNull ValueFinder valueFinder, @NonNull String packageName,
+            @NonNull ValueFinder valueFinder, @NonNull ComponentName componentName,
             @NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingSaveUi,
             boolean compatMode) {
-        if (sVerbose) Slog.v(TAG, "showSaveUi() for " + packageName + ": " + info);
+        if (sVerbose) {
+            Slog.v(TAG, "showSaveUi() for " + componentName.toShortString() + ": " + info);
+        }
         int numIds = 0;
         numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
         numIds += info.getOptionalIds() == null ? 0 : info.getOptionalIds().length;
 
         final LogMaker log = Helper
-                .newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, packageName, servicePackageName,
-                        compatMode)
+                .newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, componentName, servicePackageName,
+                        pendingSaveUi.sessionId, compatMode)
                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
 
         mHandler.post(() -> {
@@ -281,7 +287,7 @@
             }
             hideAllUiThread(callback);
             mSaveUi = new SaveUi(mContext, pendingSaveUi, serviceLabel, serviceIcon,
-                    servicePackageName, packageName, info, valueFinder, mOverlayControl,
+                    servicePackageName, componentName, info, valueFinder, mOverlayControl,
                     new SaveUi.OnSaveListener() {
                 @Override
                 public void onSave() {
@@ -409,7 +415,7 @@
         if (pendingSaveUi != null && notifyClient) {
             try {
                 if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): notifying client");
-                pendingSaveUi.client.setSaveUiState(pendingSaveUi.id, false);
+                pendingSaveUi.client.setSaveUiState(pendingSaveUi.sessionId, false);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error notifying client to set save UI state to hidden: " + e);
             }
diff --git a/services/autofill/java/com/android/server/autofill/ui/PendingUi.java b/services/autofill/java/com/android/server/autofill/ui/PendingUi.java
index d1dfb5c..091208b 100644
--- a/services/autofill/java/com/android/server/autofill/ui/PendingUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/PendingUi.java
@@ -35,7 +35,7 @@
 
     private final IBinder mToken;
     private int mState;
-    public final int id;
+    public final int sessionId;
     public final IAutoFillManagerClient client;
 
     /**
@@ -43,10 +43,11 @@
      *
      * @param token token used to identify this pending UI.
      */
-    public PendingUi(@NonNull IBinder token, int id, @NonNull IAutoFillManagerClient client) {
+    public PendingUi(@NonNull IBinder token, int sessionId,
+            @NonNull IAutoFillManagerClient client) {
         mToken = token;
         mState = STATE_CREATED;
-        this.id = id;
+        this.sessionId = sessionId;
         this.client = client;
     }
 
@@ -81,7 +82,7 @@
 
     @Override
     public String toString() {
-        return "PendingUi: [token=" + mToken + ", id=" + id + ", state="
+        return "PendingUi: [token=" + mToken + ", sessionId=" + sessionId + ", state="
                 + DebugUtils.flagsToString(PendingUi.class, "STATE_", mState) + "]";
     }
 }
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 a5311b2..dc84498 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -23,6 +23,7 @@
 import android.annotation.Nullable;
 import android.app.Dialog;
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -133,14 +134,14 @@
     private final CharSequence mSubTitle;
     private final PendingUi mPendingUi;
     private final String mServicePackageName;
-    private final String mPackageName;
+    private final ComponentName mComponentName;
     private final boolean mCompatMode;
 
     private boolean mDestroyed;
 
     SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi,
            @NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
-           @Nullable String servicePackageName, @NonNull String packageName,
+           @Nullable String servicePackageName, @NonNull ComponentName componentName,
            @NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
            @NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener,
            boolean compatMode) {
@@ -148,7 +149,7 @@
         mListener = new OneTimeListener(listener);
         mOverlayControl = overlayControl;
         mServicePackageName = servicePackageName;
-        mPackageName = packageName;
+        mComponentName = componentName;
         mCompatMode = compatMode;
 
         context = new ContextThemeWrapper(context, THEME_ID);
@@ -412,12 +413,12 @@
     }
 
     private LogMaker newLogMaker(int category, int saveType) {
-        return Helper.newLogMaker(category, mPackageName, mServicePackageName, mCompatMode)
-                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SAVE_TYPE, saveType);
+        return newLogMaker(category).addTaggedData(MetricsEvent.FIELD_AUTOFILL_SAVE_TYPE, saveType);
     }
 
     private LogMaker newLogMaker(int category) {
-        return Helper.newLogMaker(category, mPackageName, mServicePackageName, mCompatMode);
+        return Helper.newLogMaker(category, mComponentName, mServicePackageName,
+                mPendingUi.sessionId, mCompatMode);
     }
 
     private void writeLog(int category, int saveType) {
@@ -505,7 +506,7 @@
         pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle);
         pw.print(prefix); pw.print("pendingUi: "); pw.println(mPendingUi);
         pw.print(prefix); pw.print("service: "); pw.println(mServicePackageName);
-        pw.print(prefix); pw.print("app: "); pw.println(mPackageName);
+        pw.print(prefix); pw.print("app: "); pw.println(mComponentName.toShortString());
         pw.print(prefix); pw.print("compat mode: "); pw.println(mCompatMode);
 
         final View view = mDialog.getWindow().getDecorView();
diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
index dd6e6ab..ec21961 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
@@ -32,7 +32,7 @@
  * <p>The backup manager constants are encoded as a key value list separated by commas and stored as
  * a Settings.Secure.
  */
-class BackupManagerConstants extends KeyValueSettingObserver {
+public class BackupManagerConstants extends KeyValueSettingObserver {
     private static final String TAG = "BackupManagerConstants";
     private static final String SETTING = Settings.Secure.BACKUP_MANAGER_CONSTANTS;
 
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index d7db471..cd1bd67 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -353,6 +353,11 @@
         mAlarmManager = alarmManager;
     }
 
+    @VisibleForTesting
+    void setPowerManager(PowerManager powerManager) {
+        mPowerManager = powerManager;
+    }
+
     public void setBackupManagerBinder(IBackupManager backupManagerBinder) {
         mBackupManagerBinder = backupManagerBinder;
     }
@@ -2410,25 +2415,30 @@
     public void backupNow() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow");
 
-        final PowerSaveState result =
-                mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP);
-        if (result.batterySaverEnabled) {
-            if (DEBUG) Slog.v(TAG, "Not running backup while in battery save mode");
-            KeyValueBackupJob.schedule(mContext, mConstants);   // try again in several hours
-        } else {
-            if (DEBUG) Slog.v(TAG, "Scheduling immediate backup pass");
-            synchronized (mQueueLock) {
-                // Fire the intent that kicks off the whole shebang...
-                try {
-                    mRunBackupIntent.send();
-                } catch (PendingIntent.CanceledException e) {
-                    // should never happen
-                    Slog.e(TAG, "run-backup intent cancelled!");
-                }
+        long oldId = Binder.clearCallingIdentity();
+        try {
+            final PowerSaveState result =
+                    mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP);
+            if (result.batterySaverEnabled) {
+                if (DEBUG) Slog.v(TAG, "Not running backup while in battery save mode");
+                KeyValueBackupJob.schedule(mContext, mConstants);   // try again in several hours
+            } else {
+                if (DEBUG) Slog.v(TAG, "Scheduling immediate backup pass");
+                synchronized (mQueueLock) {
+                    // Fire the intent that kicks off the whole shebang...
+                    try {
+                        mRunBackupIntent.send();
+                    } catch (PendingIntent.CanceledException e) {
+                        // should never happen
+                        Slog.e(TAG, "run-backup intent cancelled!");
+                    }
 
-                // ...and cancel any pending scheduled job, because we've just superseded it
-                KeyValueBackupJob.cancel(mContext);
+                    // ...and cancel any pending scheduled job, because we've just superseded it
+                    KeyValueBackupJob.cancel(mContext);
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(oldId);
         }
     }
 
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index a62d973..99912d9 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1788,7 +1788,7 @@
             } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
                     || UserHandle.isSameApp(callingUid, mSystemUiUid)
                     || ((mAppStateTracker != null)
-                        && mAppStateTracker.isUidPowerSaveWhitelisted(callingUid)))) {
+                        && mAppStateTracker.isUidPowerSaveUserWhitelisted(callingUid)))) {
                 flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
                 flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
             }
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 3beebcb..aa86ea8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -812,11 +812,12 @@
             resOps = new ArrayList<>();
             for (int j=0; j<pkgOps.size(); j++) {
                 Op curOp = pkgOps.valueAt(j);
-                long duration = curOp.duration == -1
+                final boolean running = curOp.duration == -1;
+                long duration = running
                         ? (elapsedNow - curOp.startRealtime)
                         : curOp.duration;
                 resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
-                        curOp.rejectTime, (int) duration, curOp.proxyUid,
+                        curOp.rejectTime, (int) duration, running, curOp.proxyUid,
                         curOp.proxyPackageName));
             }
         } else {
@@ -826,11 +827,12 @@
                     if (resOps == null) {
                         resOps = new ArrayList<>();
                     }
-                    long duration = curOp.duration == -1
+                    final boolean running = curOp.duration == -1;
+                    final long duration = running
                             ? (elapsedNow - curOp.startRealtime)
                             : curOp.duration;
                     resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
-                            curOp.rejectTime, (int) duration, curOp.proxyUid,
+                            curOp.rejectTime, (int) duration, running, curOp.proxyUid,
                             curOp.proxyPackageName));
                 }
             }
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 9b001ce..3a7b5d6 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -117,6 +117,12 @@
     @GuardedBy("mLock")
     private int[] mPowerWhitelistedAllAppIds = new int[0];
 
+    /**
+     * User whitelisted apps in the device idle controller.
+     */
+    @GuardedBy("mLock")
+    private int[] mPowerWhitelistedUserAppIds = new int[0];
+
     @GuardedBy("mLock")
     private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;
 
@@ -983,13 +989,16 @@
      * Called by device idle controller to update the power save whitelists.
      */
     public void setPowerSaveWhitelistAppIds(
-            int[] powerSaveWhitelistAllAppIdArray, int[] tempWhitelistAppIdArray) {
+            int[] powerSaveWhitelistExceptIdleAppIdArray,
+            int[] powerSaveWhitelistUserAppIdArray,
+            int[] tempWhitelistAppIdArray) {
         synchronized (mLock) {
             final int[] previousWhitelist = mPowerWhitelistedAllAppIds;
             final int[] previousTempWhitelist = mTempWhitelistedAppIds;
 
-            mPowerWhitelistedAllAppIds = powerSaveWhitelistAllAppIdArray;
+            mPowerWhitelistedAllAppIds = powerSaveWhitelistExceptIdleAppIdArray;
             mTempWhitelistedAppIds = tempWhitelistAppIdArray;
+            mPowerWhitelistedUserAppIds = powerSaveWhitelistUserAppIdArray;
 
             if (isAnyAppIdUnwhitelisted(previousWhitelist, mPowerWhitelistedAllAppIds)) {
                 mHandler.notifyAllUnwhitelisted();
@@ -1194,6 +1203,16 @@
     }
 
     /**
+     * @param uid the uid to check for
+     * @return whether a UID is in the user defined power-save whitelist or not.
+     */
+    public boolean isUidPowerSaveUserWhitelisted(int uid) {
+        synchronized (mLock) {
+            return ArrayUtils.contains(mPowerWhitelistedUserAppIds, UserHandle.getAppId(uid));
+        }
+    }
+
+    /**
      * @return whether a UID is in the temp power-save whitelist or not.
      *
      * Note clients normally shouldn't need to access it. It's only for dumpsys.
@@ -1231,9 +1250,12 @@
             pw.print("Foreground uids: ");
             dumpUids(pw, mForegroundUids);
 
-            pw.print("Whitelist appids: ");
+            pw.print("Except-idle + user whitelist appids: ");
             pw.println(Arrays.toString(mPowerWhitelistedAllAppIds));
 
+            pw.print("User whitelist appids: ");
+            pw.println(Arrays.toString(mPowerWhitelistedUserAppIds));
+
             pw.print("Temp whitelist appids: ");
             pw.println(Arrays.toString(mTempWhitelistedAppIds));
 
@@ -1311,6 +1333,10 @@
                 proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
             }
 
+            for (int appId : mPowerWhitelistedUserAppIds) {
+                proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_USER_WHITELIST_APP_IDS, appId);
+            }
+
             for (int appId : mTempWhitelistedAppIds) {
                 proto.write(ForceAppStandbyTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
             }
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 74b4543..0f4702c 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1540,7 +1540,7 @@
 
                 mLocalActivityManager.registerScreenObserver(mScreenObserver);
 
-                passWhiteListToForceAppStandbyTrackerLocked();
+                passWhiteListsToForceAppStandbyTrackerLocked();
                 updateInteractivityLocked();
             }
             updateConnectivityState(null);
@@ -1631,7 +1631,7 @@
                             mPowerSaveWhitelistAppsExceptIdle, mPowerSaveWhitelistUserApps,
                             mPowerSaveWhitelistExceptIdleAppIds);
 
-                    passWhiteListToForceAppStandbyTrackerLocked();
+                    passWhiteListsToForceAppStandbyTrackerLocked();
                 }
                 return true;
             } catch (PackageManager.NameNotFoundException e) {
@@ -1650,7 +1650,7 @@
                         mPowerSaveWhitelistExceptIdleAppIds);
                 mPowerSaveWhitelistUserAppsExceptIdle.clear();
 
-                passWhiteListToForceAppStandbyTrackerLocked();
+                passWhiteListsToForceAppStandbyTrackerLocked();
             }
         }
     }
@@ -2589,7 +2589,7 @@
             }
             mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
         }
-        passWhiteListToForceAppStandbyTrackerLocked();
+        passWhiteListsToForceAppStandbyTrackerLocked();
     }
 
     private void updateTempWhitelistAppIdsLocked(int appId, boolean adding) {
@@ -2615,7 +2615,7 @@
             }
             mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
         }
-        passWhiteListToForceAppStandbyTrackerLocked();
+        passWhiteListsToForceAppStandbyTrackerLocked();
     }
 
     private void reportPowerSaveWhitelistChangedLocked() {
@@ -2630,9 +2630,10 @@
         getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
     }
 
-    private void passWhiteListToForceAppStandbyTrackerLocked() {
+    private void passWhiteListsToForceAppStandbyTrackerLocked() {
         mAppStateTracker.setPowerSaveWhitelistAppIds(
                 mPowerSaveWhitelistExceptIdleAppIdArray,
+                mPowerSaveWhitelistUserAppIdArray,
                 mTempWhitelistAppIdArray);
     }
 
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 7b02a4f..c5ab932 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1950,7 +1950,8 @@
             return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
                     + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground"
                     : " background")
-                    + ")" + " " + mRealRequest + "]";
+                    + ")" + " " + mRealRequest + " "
+                    + mReceiver.mWorkSource + "]";
         }
     }
 
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index ede870f..95e5518 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -76,17 +76,35 @@
 
     private static final long[] DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS = { 0, 30, 100, 30 };
 
-    private static final float GAMMA_SCALE_FACTOR_MINIMUM = 2.0f;
-    private static final float GAMMA_SCALE_FACTOR_LOW = 1.5f;
-    private static final float GAMMA_SCALE_FACTOR_HIGH = 0.5f;
-    private static final float GAMMA_SCALE_FACTOR_NONE = 1.0f;
+    // Scale levels. Each level is defined as the delta between the current setting and the default
+    // intensity for that type of vibration (i.e. current - default).
+    private static final int SCALE_VERY_LOW = -2;
+    private static final int SCALE_LOW = -1;
+    private static final int SCALE_NONE = 0;
+    private static final int SCALE_HIGH = 1;
+    private static final int SCALE_VERY_HIGH = 2;
 
-    private static final int MAX_AMPLITUDE_MINIMUM_INTENSITY = 168; // 2/3 * 255
-    private static final int MAX_AMPLITUDE_LOW_INTENSITY = 192; // 3/4 * 255
+    // Gamma adjustments for scale levels.
+    private static final float SCALE_VERY_LOW_GAMMA = 2.0f;
+    private static final float SCALE_LOW_GAMMA = 1.5f;
+    private static final float SCALE_NONE_GAMMA = 1.0f;
+    private static final float SCALE_HIGH_GAMMA = 0.5f;
+    private static final float SCALE_VERY_HIGH_GAMMA = 0.25f;
+
+    // Max amplitudes for scale levels. If one is not listed, then the max amplitude is the default
+    // max amplitude.
+    private static final int SCALE_VERY_LOW_MAX_AMPLITUDE = 168; // 2/3 * 255
+    private static final int SCALE_LOW_MAX_AMPLITUDE = 192; // 3/4 * 255
 
     // If a vibration is playing for longer than 5s, it's probably not haptic feedback.
     private static final long MAX_HAPTIC_FEEDBACK_DURATION = 5000;
 
+
+    // A mapping from the intensity adjustment to the scaling to apply, where the intensity
+    // adjustment is defined as the delta between the default intensity level and the user selected
+    // intensity level. It's important that we apply the scaling on the delta between the two so
+    // that the default intensity level applies no scaling to application provided effects.
+    private final SparseArray<ScaleLevel> mScaleLevels;
     private final LinkedList<VibrationInfo> mPreviousVibrations;
     private final int mPreviousVibrationsLimit;
     private final boolean mAllowPriorityVibrationsInLowPowerMode;
@@ -180,6 +198,8 @@
                     case VibrationEffect.EFFECT_DOUBLE_CLICK:
                     case VibrationEffect.EFFECT_HEAVY_CLICK:
                     case VibrationEffect.EFFECT_TICK:
+                    case VibrationEffect.EFFECT_POP:
+                    case VibrationEffect.EFFECT_THUD:
                         return true;
                     default:
                         Slog.w(TAG, "Unknown prebaked vibration effect, "
@@ -254,6 +274,25 @@
         }
     }
 
+    private static final class ScaleLevel {
+        public final float gamma;
+        public final int maxAmplitude;
+
+        public ScaleLevel(float gamma) {
+            this(gamma, VibrationEffect.MAX_AMPLITUDE);
+        }
+
+        public ScaleLevel(float gamma, int maxAmplitude) {
+            this.gamma = gamma;
+            this.maxAmplitude = maxAmplitude;
+        }
+
+        @Override
+        public String toString() {
+            return "ScaleLevel{gamma=" + gamma + ", maxAmplitude=" + maxAmplitude + "}";
+        }
+    }
+
     VibratorService(Context context) {
         vibratorInit();
         // Reset the hardware to a default state, in case this is a runtime
@@ -295,11 +334,19 @@
         VibrationEffect tickEffect = createEffectFromResource(
                 com.android.internal.R.array.config_clockTickVibePattern);
 
-        mFallbackEffects = new SparseArray<VibrationEffect>();
+        mFallbackEffects = new SparseArray<>();
         mFallbackEffects.put(VibrationEffect.EFFECT_CLICK, clickEffect);
         mFallbackEffects.put(VibrationEffect.EFFECT_DOUBLE_CLICK, doubleClickEffect);
         mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect);
         mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, heavyClickEffect);
+
+        mScaleLevels = new SparseArray<>();
+        mScaleLevels.put(SCALE_VERY_LOW,
+                new ScaleLevel(SCALE_VERY_LOW_GAMMA, SCALE_VERY_LOW_MAX_AMPLITUDE));
+        mScaleLevels.put(SCALE_LOW, new ScaleLevel(SCALE_LOW_GAMMA, SCALE_LOW_MAX_AMPLITUDE));
+        mScaleLevels.put(SCALE_NONE, new ScaleLevel(SCALE_NONE_GAMMA));
+        mScaleLevels.put(SCALE_HIGH, new ScaleLevel(SCALE_HIGH_GAMMA));
+        mScaleLevels.put(SCALE_VERY_HIGH, new ScaleLevel(SCALE_VERY_HIGH_GAMMA));
     }
 
     private VibrationEffect createEffectFromResource(int resId) {
@@ -675,41 +722,35 @@
             return;
         }
 
-        final float gamma;
-        final int maxAmplitude;
+        final int defaultIntensity;
         if (vib.isNotification() || vib.isRingtone()) {
-            if (intensity == Vibrator.VIBRATION_INTENSITY_LOW) {
-                gamma = GAMMA_SCALE_FACTOR_MINIMUM;
-                maxAmplitude = MAX_AMPLITUDE_MINIMUM_INTENSITY;
-            } else if (intensity == Vibrator.VIBRATION_INTENSITY_MEDIUM) {
-                gamma = GAMMA_SCALE_FACTOR_LOW;
-                maxAmplitude = MAX_AMPLITUDE_LOW_INTENSITY;
-            } else {
-                gamma = GAMMA_SCALE_FACTOR_NONE;
-                maxAmplitude = VibrationEffect.MAX_AMPLITUDE;
-            }
+            defaultIntensity = mVibrator.getDefaultNotificationVibrationIntensity();
+        } else if (vib.isHapticFeedback()) {
+            defaultIntensity = mVibrator.getDefaultHapticFeedbackIntensity();
         } else {
-            if (intensity == Vibrator.VIBRATION_INTENSITY_LOW) {
-                gamma = GAMMA_SCALE_FACTOR_LOW;
-                maxAmplitude = MAX_AMPLITUDE_LOW_INTENSITY;
-            } else if (intensity == Vibrator.VIBRATION_INTENSITY_HIGH) {
-                gamma = GAMMA_SCALE_FACTOR_HIGH;
-                maxAmplitude = VibrationEffect.MAX_AMPLITUDE;
-            } else {
-                gamma = GAMMA_SCALE_FACTOR_NONE;
-                maxAmplitude = VibrationEffect.MAX_AMPLITUDE;
-            }
+            // If we don't know what kind of vibration we're playing then just skip scaling for
+            // now.
+            return;
+        }
+
+        final ScaleLevel scale = mScaleLevels.get(intensity - defaultIntensity);
+        if (scale == null) {
+            // We should have scaling levels for all cases, so not being able to scale because of a
+            // missing level is unexpected.
+            Slog.e(TAG, "No configured scaling level!"
+                    + " (current=" + intensity + ", default= " + defaultIntensity + ")");
+            return;
         }
 
         VibrationEffect scaledEffect = null;
         if (vib.effect instanceof VibrationEffect.OneShot) {
             VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.effect;
             oneShot = oneShot.resolve(mDefaultVibrationAmplitude);
-            scaledEffect = oneShot.scale(gamma, maxAmplitude);
+            scaledEffect = oneShot.scale(scale.gamma, scale.maxAmplitude);
         } else if (vib.effect instanceof VibrationEffect.Waveform) {
             VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.effect;
             waveform = waveform.resolve(mDefaultVibrationAmplitude);
-            scaledEffect = waveform.scale(gamma, maxAmplitude);
+            scaledEffect = waveform.scale(scale.gamma, scale.maxAmplitude);
         } else {
             Slog.w(TAG, "Unable to apply intensity scaling, unknown VibrationEffect type");
         }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 4c2a940..ca715b5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -119,7 +119,7 @@
 
     // How long the startForegroundService() grace period is to get around to
     // calling startForeground() before we ANR + stop it.
-    static final int SERVICE_START_FOREGROUND_TIMEOUT = 5*1000;
+    static final int SERVICE_START_FOREGROUND_TIMEOUT = 10*1000;
 
     final ActivityManagerService mAm;
 
@@ -501,6 +501,18 @@
             }
         }
 
+        // At this point we've applied allowed-to-start policy based on whether this was
+        // an ordinary startService() or a startForegroundService().  Now, only require that
+        // the app follow through on the startForegroundService() -> startForeground()
+        // contract if it actually targets O+.
+        if (r.appInfo.targetSdkVersion < Build.VERSION_CODES.O && fgRequired) {
+            if (DEBUG_BACKGROUND_CHECK || DEBUG_FOREGROUND_SERVICE) {
+                Slog.i(TAG, "startForegroundService() but host targets "
+                        + r.appInfo.targetSdkVersion + " - not requiring startForeground()");
+            }
+            fgRequired = false;
+        }
+
         NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
                 callingUid, r.packageName, service, service.getFlags(), null, r.userId);
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8e87ebd..9bc5829 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12925,6 +12925,8 @@
             // about the process state of the isolated UID *before* it is registered with the
             // owning application.
             mBatteryStatsService.addIsolatedUid(uid, info.uid);
+            StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, info.uid, uid,
+                    StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
         }
         final ProcessRecord r = new ProcessRecord(this, stats, info, proc, uid);
         if (!mBooted && !mBooting
@@ -15174,6 +15176,7 @@
                         public void onLimitReached(int uid) {
                             Slog.wtf(TAG, "Uid " + uid + " sent too many Binders to uid "
                                     + Process.myUid());
+                            Binder.dumpProxyDebugInfo();
                             if (uid == Process.SYSTEM_UID) {
                                 Slog.i(TAG, "Skipping kill (uid is SYSTEM)");
                             } else {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index ef5a5a3..d456f62 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -115,6 +115,7 @@
 import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
 import static com.android.server.am.ActivityRecordProto.PROC_ID;
 import static com.android.server.am.ActivityRecordProto.STATE;
+import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
 import static com.android.server.am.ActivityRecordProto.VISIBLE;
 import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
@@ -2412,11 +2413,16 @@
         }
 
         // Compute configuration based on max supported width and height.
-        outBounds.set(0, 0, maxActivityWidth, maxActivityHeight);
-        // Position the activity frame on the opposite side of the nav bar.
-        final int navBarPosition = service.mWindowManager.getNavBarPosition();
-        final int left = navBarPosition == NAV_BAR_LEFT ? appBounds.right - outBounds.width() : 0;
-        outBounds.offsetTo(left, 0 /* top */);
+        // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
+        // away later in StackWindowController.adjustConfigurationForBounds(). Otherwise, the app
+        // bounds would end up too small.
+        outBounds.set(0, 0, maxActivityWidth + appBounds.left, maxActivityHeight + appBounds.top);
+
+        if (service.mWindowManager.getNavBarPosition() == NAV_BAR_LEFT) {
+            // Position the activity frame on the opposite side of the nav bar.
+            outBounds.left = appBounds.right - maxActivityWidth;
+            outBounds.right = appBounds.right;
+        }
     }
 
     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
@@ -2980,6 +2986,7 @@
         if (app != null) {
             proto.write(PROC_ID, app.pid);
         }
+        proto.write(TRANSLUCENT, !fullscreen);
         proto.end(token);
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index aaa5161..3ad461f 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1360,7 +1360,9 @@
     }
 
     void goToSleep() {
-        ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+        // Ensure visibility without updating configuration, as activities are about to sleep.
+        ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS,
+                false /* updateConfiguration */);
 
         // Make sure any paused or stopped but visible activities are now sleeping.
         // This ensures that the activity's onStop() is called.
@@ -1829,12 +1831,23 @@
     }
 
     /**
-     * Make sure that all activities that need to be visible (that is, they
-     * currently can be seen by the user) actually are.
+     * Make sure that all activities that need to be visible in the stack (that is, they
+     * currently can be seen by the user) actually are and update their configuration.
+     */
+    final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+            boolean preserveWindows) {
+        ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+                true /* updateConfiguration */);
+    }
+
+    /**
+     * Ensure visibility with an option to also update the configuration of visible activities.
+     * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
+     * @see ActivityStackSupervisor#ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
      */
     // TODO: Should be re-worked based on the fact that each task as a stack in most cases.
     final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
-            boolean preserveWindows) {
+            boolean preserveWindows, boolean updateConfiguration) {
         mTopActivityOccludesKeyguard = false;
         mTopDismissingKeyguardActivity = null;
         mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
@@ -1886,9 +1899,7 @@
                                 + " finishing=" + r.finishing + " state=" + r.getState());
                         // First: if this is not the current activity being started, make
                         // sure it matches the current configuration.
-                        if (r != starting) {
-                            // Ensure activity configuration ignoring stop state since we are
-                            // becoming visible.
+                        if (r != starting && updateConfiguration) {
                             r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
                                     true /* ignoreStopState */);
                         }
@@ -2608,25 +2619,16 @@
                 boolean notUpdated = true;
 
                 if (mStackSupervisor.isFocusedStack(this)) {
-
-                    // We have special rotation behavior when Keyguard is locked. Make sure all
-                    // activity visibilities are set correctly as well as the transition is updated
-                    // if needed to get the correct rotation behavior.
+                    // We have special rotation behavior when here is some active activity that
+                    // requests specific orientation or Keyguard is locked. Make sure all activity
+                    // visibilities are set correctly as well as the transition is updated if needed
+                    // to get the correct rotation behavior. Otherwise the following call to update
+                    // the orientation may cause incorrect configurations delivered to client as a
+                    // result of invisible window resize.
                     // TODO: Remove this once visibilities are set correctly immediately when
                     // starting an activity.
-                    if (mStackSupervisor.getKeyguardController().isKeyguardLocked()) {
-                        mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */,
-                                0 /* configChanges */, false /* preserveWindows */);
-                    }
-                    final Configuration config = mWindowManager.updateOrientationFromAppTokens(
-                            mStackSupervisor.getDisplayOverrideConfiguration(mDisplayId),
-                            next.mayFreezeScreenLocked(next.app) ? next.appToken : null,
-                                    mDisplayId);
-                    if (config != null) {
-                        next.frozenBeforeDestroy = true;
-                    }
-                    notUpdated = !mService.updateDisplayOverrideConfigurationLocked(config, next,
-                            false /* deferResume */, mDisplayId);
+                    notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
+                            true /* markFrozenIfConfigChanged */, false /* deferResume */);
                 }
 
                 if (notUpdated) {
@@ -3834,7 +3836,8 @@
             if (finishingActivityInNonFocusedStack) {
                 // Finishing activity that was in paused state and it was in not currently focused
                 // stack, need to make something visible in its place.
-                mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+                mStackSupervisor.ensureVisibilityAndConfig(null, mDisplayId,
+                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
             }
             if (activityRemoved) {
                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index afad0b1..257d79d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1409,15 +1409,11 @@
             // manager with a new orientation.  We don't care about that, because the activity is
             // not currently running so we are just restarting it anyway.
             if (checkConfig) {
-                final int displayId = r.getDisplayId();
-                final Configuration config = mWindowManager.updateOrientationFromAppTokens(
-                        getDisplayOverrideConfiguration(displayId),
-                        r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
                 // Deferring resume here because we're going to launch new activity shortly.
                 // We don't want to perform a redundant launch of the same record while ensuring
                 // configurations and trying to resume top activity of focused stack.
-                mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,
-                        displayId);
+                ensureVisibilityAndConfig(r, r.getDisplayId(),
+                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
             }
 
             if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
@@ -1630,6 +1626,31 @@
         return true;
     }
 
+    /**
+     * Ensure all activities visibility, update orientation and configuration.
+     */
+    boolean ensureVisibilityAndConfig(ActivityRecord r, int displayId,
+            boolean markFrozenIfConfigChanged, boolean deferResume) {
+        // First ensure visibility without updating the config just yet. We need this to know what
+        // activities are affecting configuration now.
+        ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+                false /* preserveWindows */, false /* updateConfiguration */);
+
+        // Force-update the orientation from the WindowManager, since we need the true configuration
+        // to send to the client now.
+        final Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                getDisplayOverrideConfiguration(displayId),
+                r != null && r.mayFreezeScreenLocked(r.app) ? r.appToken : null,
+                displayId, true /* forceUpdate */);
+        if (r != null && markFrozenIfConfigChanged && config != null) {
+            r.frozenBeforeDestroy = true;
+        }
+
+        // Update the configuration of the activities on the display.
+        return mService.updateDisplayOverrideConfigurationLocked(config, r,
+                deferResume, displayId);
+    }
+
     private void logIfTransactionTooLarge(Intent intent, Bundle icicle) {
         int extrasSize = 0;
         if (intent != null) {
@@ -2554,6 +2575,10 @@
             final int displayId = mTmpOrderedDisplayIds.get(i);
             // If a display is registered in WM, it must also be available in AM.
             final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
+            if (display == null) {
+                // Looks like the display no longer exists in the system...
+                continue;
+            }
             for (int j = display.getChildCount() - 1; j >= 0; --j) {
                 final ActivityStack stack = display.getChildAt(j);
                 if (ignoreCurrent && stack == currentFocus) {
@@ -3643,8 +3668,21 @@
         mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget();
     }
 
+    /**
+     * Make sure that all activities that need to be visible in the system actually are and update
+     * their configuration.
+     */
     void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
             boolean preserveWindows) {
+        ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+                true /* updateConfiguration */);
+    }
+
+    /**
+     * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
+     */
+    void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
+            boolean preserveWindows, boolean updateConfiguration) {
         getKeyguardController().beginActivityVisibilityUpdate();
         try {
             // First the front stacks. In case any are not fullscreen and are in front of home.
@@ -3652,7 +3690,8 @@
                 final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
                 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
                     final ActivityStack stack = display.getChildAt(stackNdx);
-                    stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows);
+                    stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+                            updateConfiguration);
                 }
             }
         } finally {
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 49fa902..094cf06 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -31,6 +31,7 @@
 import android.telephony.TelephonyManager;
 import android.util.IntArray;
 import android.util.Slog;
+import android.util.StatsLog;
 import android.util.TimeUtils;
 
 import com.android.internal.annotations.GuardedBy;
@@ -367,6 +368,8 @@
                 // Clean up any UIDs if necessary.
                 synchronized (mStats) {
                     for (int uid : uidsToRemove) {
+                        StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, -1, uid,
+                                StatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED);
                         mStats.removeIsolatedUidLocked(uid);
                     }
                     mStats.clearPendingRemovedUids();
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index cddb05e..9c0d4e0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -215,6 +215,10 @@
         return mPlatformType == AudioSystem.PLATFORM_TELEVISION;
     }
 
+    private boolean isPlatformAutomotive() {
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+    }
+
     /** The controller for the volume UI. */
     private final VolumeController mVolumeController = new VolumeController();
 
@@ -2380,8 +2384,11 @@
         if (DEBUG_VOL) {
             Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
         }
-        if (mUseFixedVolume) {
-            return; // If using fixed volume, we don't mute.
+        if (!isPlatformAutomotive() && mUseFixedVolume) {
+            // If using fixed volume, we don't mute.
+            // TODO: remove the isPlatformAutomotive check here.
+            // The isPlatformAutomotive check is added for safety but may not be necessary.
+            return;
         }
         if (getCurrentUserId() == userId) {
             if (mute != AudioSystem.getMasterMute()) {
@@ -3312,6 +3319,9 @@
                 .append(Binder.getCallingPid()).toString();
 
         synchronized (mBluetoothA2dpEnabledLock) {
+            if (mBluetoothA2dpEnabled == on) {
+                return;
+            }
             mBluetoothA2dpEnabled = on;
             sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
                     AudioSystem.FOR_MEDIA,
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index d7057f4..2c9a494 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1310,10 +1310,10 @@
                 : ActivityManager.PROCESS_STATE_NONEXISTENT;
 
         if (procState <= ActivityManager.PROCESS_STATE_TOP) {
-            return ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP;
+            return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP;
         }
         if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
-            return ContentResolver.SYNC_EXEMPTION_ACTIVE;
+            return ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET;
         }
         return ContentResolver.SYNC_EXEMPTION_NONE;
     }
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 33cf11b..0a640b8 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1656,7 +1656,7 @@
         }
 
         if (syncOperation.syncExemptionFlag
-                == ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP) {
+                == ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP) {
             DeviceIdleController.LocalService dic =
                     LocalServices.getService(DeviceIdleController.LocalService.class);
             if (dic != null) {
@@ -1668,6 +1668,15 @@
             }
         }
 
+        if (syncOperation.isAppStandbyExempted()) {
+            final UsageStatsManagerInternal usmi = LocalServices.getService(
+                    UsageStatsManagerInternal.class);
+            if (usmi != null) {
+                usmi.reportExemptedSyncScheduled(syncOperation.owningPackage,
+                        UserHandle.getUserId(syncOperation.owningUid));
+            }
+        }
+
         getJobScheduler().scheduleAsPackage(b.build(), syncOperation.owningPackage,
                 syncOperation.target.userId, syncOperation.wakeLockName());
     }
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index d097563..25edf40 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -390,10 +390,10 @@
         switch (syncExemptionFlag) {
             case ContentResolver.SYNC_EXEMPTION_NONE:
                 break;
-            case ContentResolver.SYNC_EXEMPTION_ACTIVE:
+            case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET:
                 sb.append(" STANDBY-EXEMPTED");
                 break;
-            case ContentResolver.SYNC_EXEMPTION_ACTIVE_WITH_TEMP:
+            case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP:
                 sb.append(" STANDBY-EXEMPTED(TOP)");
                 break;
             default:
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 6a343f8..11f0701 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -341,6 +341,7 @@
         boolean initialization;
         Bundle extras;
         int reason;
+        int syncExemptionFlag;
     }
 
     public static class DayStats {
@@ -1142,6 +1143,7 @@
             item.reason = op.reason;
             item.extras = op.extras;
             item.event = EVENT_START;
+            item.syncExemptionFlag = op.syncExemptionFlag;
             mSyncHistory.add(0, item);
             while (mSyncHistory.size() > MAX_HISTORY) {
                 mSyncHistory.remove(mSyncHistory.size()-1);
@@ -1262,6 +1264,20 @@
             SyncManager.formatDurationHMS(event, elapsedTime);
             event.append(" Reason=");
             event.append(SyncOperation.reasonToString(null, item.reason));
+            if (item.syncExemptionFlag != ContentResolver.SYNC_EXEMPTION_NONE) {
+                event.append(" Exemption=");
+                switch (item.syncExemptionFlag) {
+                    case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET:
+                        event.append("fg");
+                        break;
+                    case ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP:
+                        event.append("top");
+                        break;
+                    default:
+                        event.append(item.syncExemptionFlag);
+                        break;
+                }
+            }
             event.append(" Extras=");
             SyncOperation.extrasToStringBuilder(item.extras, event);
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 0cba76b..5681367 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -16,6 +16,7 @@
 
 package com.android.server.hdmi;
 
+import android.annotation.Nullable;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.input.InputManager;
 import android.os.Handler;
@@ -31,6 +32,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 
+import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -249,11 +251,11 @@
             case Constants.MESSAGE_SET_MENU_LANGUAGE:
                 return handleSetMenuLanguage(message);
             case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS:
-                return handleGivePhysicalAddress();
+                return handleGivePhysicalAddress(null);
             case Constants.MESSAGE_GIVE_OSD_NAME:
                 return handleGiveOsdName(message);
             case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID:
-                return handleGiveDeviceVendorId();
+                return handleGiveDeviceVendorId(null);
             case Constants.MESSAGE_GET_CEC_VERSION:
                 return handleGetCecVersion(message);
             case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS:
@@ -325,23 +327,23 @@
     }
 
     @ServiceThreadOnly
-    protected boolean handleGivePhysicalAddress() {
+    protected boolean handleGivePhysicalAddress(@Nullable SendMessageCallback callback) {
         assertRunOnServiceThread();
 
         int physicalAddress = mService.getPhysicalAddress();
         HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                 mAddress, physicalAddress, mDeviceType);
-        mService.sendCecCommand(cecMessage);
+        mService.sendCecCommand(cecMessage, callback);
         return true;
     }
 
     @ServiceThreadOnly
-    protected boolean handleGiveDeviceVendorId() {
+    protected boolean handleGiveDeviceVendorId(@Nullable SendMessageCallback callback) {
         assertRunOnServiceThread();
         int vendorId = mService.getVendorId();
         HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
                 mAddress, vendorId);
-        mService.sendCecCommand(cecMessage);
+        mService.sendCecCommand(cecMessage, callback);
         return true;
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index 8c00be5..4ad51de 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -22,7 +22,7 @@
 /**
  * A helper class to validates {@link HdmiCecMessage}.
  */
-public final class HdmiCecMessageValidator {
+public class HdmiCecMessageValidator {
     private static final String TAG = "HdmiCecMessageValidator";
 
     static final int OK = 0;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index ba6da05..a1753e5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -68,6 +68,7 @@
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
@@ -290,6 +291,9 @@
     @Nullable
     private PowerManager mPowerManager;
 
+    @Nullable
+    private Looper mIoLooper;
+
     // Last input port before switching to the MHL port. Should switch back to this port
     // when the mobile device sends the request one touch play with off.
     // Gets invalidated if we go to other port/input.
@@ -383,13 +387,18 @@
 
     @Override
     public void onStart() {
-        mIoThread.start();
+        if (mIoLooper == null) {
+            mIoThread.start();
+            mIoLooper = mIoThread.getLooper();
+        }
         mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
         mProhibitMode = false;
         mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true);
         mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true);
 
-        mCecController = HdmiCecController.create(this);
+        if (mCecController == null) {
+            mCecController = HdmiCecController.create(this);
+        }
         if (mCecController != null) {
             if (mHdmiControlEnabled) {
                 initializeCec(INITIATED_BY_BOOT_UP);
@@ -406,7 +415,9 @@
         mMhlDevices = Collections.emptyList();
 
         initPortInfo();
-        mMessageValidator = new HdmiCecMessageValidator(this);
+        if (mMessageValidator == null) {
+            mMessageValidator = new HdmiCecMessageValidator(this);
+        }
         publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
 
         if (mCecController != null) {
@@ -424,6 +435,11 @@
         mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, ENABLED);
     }
 
+    @VisibleForTesting
+    void setCecController(HdmiCecController cecController) {
+        mCecController = cecController;
+    }
+
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
@@ -747,8 +763,19 @@
      *
      * <p>Declared as package-private.
      */
+    @Nullable
     Looper getIoLooper() {
-        return mIoThread.getLooper();
+        return mIoLooper;
+    }
+
+    @VisibleForTesting
+    void setIoLooper(Looper ioLooper) {
+        mIoLooper = ioLooper;
+    }
+
+    @VisibleForTesting
+    void setMessageValidator(HdmiCecMessageValidator messageValidator) {
+        mMessageValidator = messageValidator;
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index b213ee60..b90c12a 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1016,26 +1016,25 @@
             locationListener = mFusedLocationListener;
         }
 
-        if (!locationManager.isProviderEnabled(provider)) {
-            Log.w(TAG, "Unable to request location since " + provider
-                    + " provider does not exist or is not enabled.");
-            return;
-        }
-
         Log.i(TAG,
                 String.format(
                         "GNSS HAL Requesting location updates from %s provider for %d millis.",
                         provider, durationMillis));
-        locationManager.requestLocationUpdates(provider,
-                LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /*minDistance=*/ 0,
-                locationListener, mHandler.getLooper());
-        locationListener.numLocationUpdateRequest++;
-        mHandler.postDelayed(() -> {
-            if (--locationListener.numLocationUpdateRequest == 0) {
-                Log.i(TAG, String.format("Removing location updates from %s provider.", provider));
-                locationManager.removeUpdates(locationListener);
-            }
-        }, durationMillis);
+        try {
+            locationManager.requestLocationUpdates(provider,
+                    LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /*minDistance=*/ 0,
+                    locationListener, mHandler.getLooper());
+            locationListener.numLocationUpdateRequest++;
+            mHandler.postDelayed(() -> {
+                if (--locationListener.numLocationUpdateRequest == 0) {
+                    Log.i(TAG,
+                            String.format("Removing location updates from %s provider.", provider));
+                    locationManager.removeUpdates(locationListener);
+                }
+            }, durationMillis);
+        } catch (IllegalArgumentException e) {
+            Log.w(TAG, "Unable to request location.", e);
+        }
     }
 
     private void injectBestLocation(Location location) {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 384efdd..a7df0e2 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -95,9 +95,8 @@
 
     // State guarded by mLock.
     private final Object mLock = new Object();
-    private final SparseArray<UserRecord> mUserRecords = new SparseArray<UserRecord>();
-    private final ArrayMap<IBinder, ClientRecord> mAllClientRecords =
-            new ArrayMap<IBinder, ClientRecord>();
+    private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
+    private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>();
     private int mCurrentUserId = -1;
     private final IAudioService mAudioService;
     private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
@@ -106,7 +105,7 @@
     private final IntArray mActivePlayerUidMinPriorityQueue = new IntArray();
 
     private final BroadcastReceiver mReceiver = new MediaRouterServiceBroadcastReceiver();
-    BluetoothDevice mBluetoothDevice;
+    BluetoothDevice mActiveBluetoothDevice;
     int mAudioRouteMainType = AudioRoutesInfo.MAIN_SPEAKER;
     boolean mGlobalBluetoothA2dpOn = false;
 
@@ -180,7 +179,8 @@
                                     | AudioRoutesInfo.MAIN_HEADPHONES
                                     | AudioRoutesInfo.MAIN_USB)) == 0) {
                                 // headset was plugged out.
-                                mGlobalBluetoothA2dpOn = mBluetoothDevice != null;
+                                mGlobalBluetoothA2dpOn = (newRoutes.bluetoothName != null
+                                        || mActiveBluetoothDevice != null);
                             } else {
                                 // headset was plugged in.
                                 mGlobalBluetoothA2dpOn = false;
@@ -197,7 +197,7 @@
             Slog.w(TAG, "RemoteException in the audio service.");
         }
 
-        IntentFilter intentFilter = new IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+        IntentFilter intentFilter = new IntentFilter(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
         context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
     }
 
@@ -406,12 +406,14 @@
 
     void restoreBluetoothA2dp() {
         try {
-            boolean a2dpOn = false;
+            boolean a2dpOn;
+            BluetoothDevice btDevice;
             synchronized (mLock) {
                 a2dpOn = mGlobalBluetoothA2dpOn;
+                btDevice = mActiveBluetoothDevice;
             }
             // We don't need to change a2dp status when bluetooth is not connected.
-            if (mBluetoothDevice != null) {
+            if (btDevice != null) {
                 Slog.v(TAG, "restoreBluetoothA2dp(" + a2dpOn + ")");
                 mAudioService.setBluetoothA2dpOn(a2dpOn);
             }
@@ -653,17 +655,11 @@
     final class MediaRouterServiceBroadcastReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
-                        BluetoothProfile.STATE_DISCONNECTED);
-                if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                    mGlobalBluetoothA2dpOn = false;
-                    mBluetoothDevice = null;
-                } else if (state == BluetoothProfile.STATE_CONNECTED) {
-                    mGlobalBluetoothA2dpOn = true;
-                    mBluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                    // To ensure that BT A2DP is on, call restoreBluetoothA2dp().
-                    restoreBluetoothA2dp();
+            if (intent.getAction().equals(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) {
+                BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+                synchronized (mLock) {
+                    mActiveBluetoothDevice = btDevice;
+                    mGlobalBluetoothA2dpOn = btDevice != null;
                 }
             }
         }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index aba75dd..60e9eaa 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -324,6 +324,7 @@
                 wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
                 new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(),
                 getDefaultSystemDir(), getDefaultBaseDir());
+        service.registerLocalService();
 
         HandlerThread handlerThread = new HandlerThread(TAG);
         Handler.Callback callback = new HandlerCallback(service);
@@ -333,6 +334,8 @@
         return service;
     }
 
+    // This must not be called outside of tests, even within the same package, as this constructor
+    // does not register the local service. Use the create() helper above.
     @VisibleForTesting
     NetworkStatsService(Context context, INetworkManagementService networkManager,
             AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
@@ -349,7 +352,9 @@
         mSystemDir = checkNotNull(systemDir, "missing systemDir");
         mBaseDir = checkNotNull(baseDir, "missing baseDir");
         mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
+    }
 
+    private void registerLocalService() {
         LocalServices.addService(NetworkStatsManagerInternal.class,
                 new NetworkStatsManagerInternalImpl());
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b698b92..ba73c7e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17294,17 +17294,6 @@
                                         + "Persistent apps are not updateable.");
                         return;
                     }
-                    // Prevent apps from downgrading their targetSandbox.
-                    final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion;
-                    final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion;
-                    if (oldTargetSandbox == 2 && newTargetSandbox != 2) {
-                        res.setError(PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
-                                "Package " + pkg.packageName + " new target sandbox "
-                                + newTargetSandbox + " is incompatible with the previous value of"
-                                + oldTargetSandbox + ".");
-                        return;
-                    }
-
                     // Prevent installing of child packages
                     if (oldPackage.parentPackage != null) {
                         res.setError(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 199098b..781faa7 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6153,7 +6153,9 @@
                     sendSystemKeyToStatusBarAsync(event.getKeyCode());
 
                     TelecomManager telecomManager = getTelecommService();
-                    if (telecomManager != null) {
+                    if (telecomManager != null && !mHandleVolumeKeysInWM) {
+                        // When {@link #mHandleVolumeKeysInWM} is set, volume key events
+                        // should be dispatched to WM.
                         if (telecomManager.isRinging()) {
                             // If an incoming call is ringing, either VOLUME key means
                             // "silence ringer".  We handle these keys here, rather than
@@ -6922,7 +6924,7 @@
             } else {
                 if (DEBUG_WAKEUP) Slog.d(TAG,
                         "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
-                finishKeyguardDrawn();
+                mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
             }
         }
     }
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index 91ef3d4..ed2b79e 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -392,7 +392,7 @@
         mForceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, true);
         mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true);
         mAodDisabled = parser.getBoolean(KEY_AOD_DISABLED, true);
-        mSendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, true);
+        mSendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, false);
 
         // Get default value from Settings.Secure
         final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index e637df4..0ba5a56 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1297,7 +1297,7 @@
         // going to the bottom. Allowing closing {@link AppWindowToken} to participate can lead to
         // an Activity in another task being started in the wrong orientation during the transition.
         if (!(sendingToBottom || mService.mClosingApps.contains(this))
-                && (isVisible() || mService.mOpeningApps.contains(this) || isOnTop())) {
+                && (isVisible() || mService.mOpeningApps.contains(this))) {
             return mOrientation;
         }
 
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index b8431b1..65c8e96 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -22,7 +22,9 @@
 import static com.android.server.wm.AnimationSpecProto.ALPHA;
 
 import android.graphics.Rect;
+import android.util.Log;
 import android.util.proto.ProtoOutputStream;
+import android.view.Surface;
 import android.view.SurfaceControl;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -171,14 +173,18 @@
      */
     private DimState getDimState(WindowContainer container) {
         if (mDimState == null) {
-            final SurfaceControl ctl = makeDimLayer();
-            mDimState = new DimState(ctl);
-            /**
-             * See documentation on {@link #dimAbove} to understand lifecycle management of Dim's
-             * via state resetting for Dim's with containers.
-             */
-            if (container == null) {
-                mDimState.mDontReset = true;
+            try {
+                final SurfaceControl ctl = makeDimLayer();
+                mDimState = new DimState(ctl);
+                /**
+                 * See documentation on {@link #dimAbove} to understand lifecycle management of
+                 * Dim's via state resetting for Dim's with containers.
+                 */
+                if (container == null) {
+                    mDimState.mDontReset = true;
+                }
+            } catch (Surface.OutOfResourcesException e) {
+                Log.w(TAG, "OutOfResourcesException creating dim surface");
             }
         }
 
@@ -189,6 +195,11 @@
     private void dim(SurfaceControl.Transaction t, WindowContainer container, int relativeLayer,
             float alpha) {
         final DimState d = getDimState(container);
+
+        if (d == null) {
+            return;
+        }
+
         if (container != null) {
             // The dim method is called from WindowState.prepareSurfaces(), which is always called
             // in the correct Z from lowest Z to highest. This ensures that the dim layer is always
@@ -208,10 +219,11 @@
      * @param t A Transaction in which to finish the dim.
      */
     void stopDim(SurfaceControl.Transaction t) {
-        DimState d = getDimState(null);
-        t.hide(d.mDimLayer);
-        d.isVisible = false;
-        d.mDontReset = false;
+        if (mDimState != null) {
+            t.hide(mDimState.mDimLayer);
+            mDimState.isVisible = false;
+            mDimState.mDontReset = false;
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f3423c6..b59e728 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -944,33 +944,50 @@
     /**
      * Update rotation of the display.
      *
-     * Returns true if the rotation has been changed.  In this case YOU MUST CALL
-     * {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
+     * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
+     *         {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
      */
     boolean updateRotationUnchecked() {
-        if (mService.mDeferredRotationPauseCount > 0) {
-            // Rotation updates have been paused temporarily.  Defer the update until
-            // updates have been resumed.
-            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
-            return false;
-        }
+        return updateRotationUnchecked(false /* forceUpdate */);
+    }
 
-        ScreenRotationAnimation screenRotationAnimation =
-                mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
-        if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
-            // Rotation updates cannot be performed while the previous rotation change
-            // animation is still in progress.  Skip this update.  We will try updating
-            // again after the animation is finished and the display is unfrozen.
-            if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
-            return false;
-        }
-        if (mService.mDisplayFrozen) {
-            // Even if the screen rotation animation has finished (e.g. isAnimating
-            // returns false), there is still some time where we haven't yet unfrozen
-            // the display. We also need to abort rotation here.
-            if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
-                    "Deferring rotation, still finishing previous rotation");
-            return false;
+    /**
+     * Update rotation of the display with an option to force the update.
+     * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating
+     *                    orientation because we're waiting for some rotation to finish or display
+     *                    to unfreeze, which results in configuration of the previously visible
+     *                    activity being applied to a newly visible one. Forcing the rotation
+     *                    update allows to workaround this issue.
+     * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
+     *         {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
+     */
+    boolean updateRotationUnchecked(boolean forceUpdate) {
+        ScreenRotationAnimation screenRotationAnimation;
+        if (!forceUpdate) {
+            if (mService.mDeferredRotationPauseCount > 0) {
+                // Rotation updates have been paused temporarily.  Defer the update until
+                // updates have been resumed.
+                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, rotation is paused.");
+                return false;
+            }
+
+            screenRotationAnimation =
+                    mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
+            if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
+                // Rotation updates cannot be performed while the previous rotation change
+                // animation is still in progress.  Skip this update.  We will try updating
+                // again after the animation is finished and the display is unfrozen.
+                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
+                return false;
+            }
+            if (mService.mDisplayFrozen) {
+                // Even if the screen rotation animation has finished (e.g. isAnimating
+                // returns false), there is still some time where we haven't yet unfrozen
+                // the display. We also need to abort rotation here.
+                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
+                        "Deferring rotation, still finishing previous rotation");
+                return false;
+            }
         }
 
         if (!mService.mDisplayEnabled) {
@@ -992,7 +1009,7 @@
 
         if (mayRotateSeamlessly) {
             final WindowState seamlessRotated = getWindow((w) -> w.mSeamlesslyRotated);
-            if (seamlessRotated != null) {
+            if (seamlessRotated != null && !forceUpdate) {
                 // We can't rotate (seamlessly or not) while waiting for the last seamless rotation
                 // to complete (that is, waiting for windows to redraw). It's tempting to check
                 // w.mSeamlessRotationCount but that could be incorrect in the case of
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 7211533..2bfff26 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -206,6 +206,9 @@
                 }
             }
         });
+        a.mAnim = anim;
+        mRunningAnimations.put(a.mLeash, a);
+
         anim.start();
         if (a.mAnimSpec.canSkipFirstFrame()) {
             // If we can skip the first frame, we start one frame later.
@@ -215,8 +218,6 @@
         // Immediately start the animation by manually applying an animation frame. Otherwise, the
         // start time would only be set in the next frame, leading to a delay.
         anim.doAnimationFrame(mChoreographer.getFrameTime());
-        a.mAnim = anim;
-        mRunningAnimations.put(a.mLeash, a);
     }
 
     private void applyTransformation(RunningAnimation a, Transaction t, long currentPlayTime) {
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index f73c2db..35e4092 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -29,6 +29,7 @@
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
 
 import android.annotation.IntDef;
+import android.app.IActivityManager;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Looper;
@@ -93,6 +94,7 @@
     static final float MIN_ASPECT = 1.2f;
 
     private final WindowManagerService mService;
+    private final IActivityManager mActivityManager;
     private WindowPositionerEventReceiver mInputEventReceiver;
     private Display mDisplay;
     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@@ -165,7 +167,7 @@
                             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                                     "wm.TaskPositioner.resizeTask");
                             try {
-                                mService.mActivityManager.resizeTask(
+                                mActivityManager.resizeTask(
                                         mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
                             } catch (RemoteException e) {
                             }
@@ -198,7 +200,7 @@
                         if (wasResizing && !mTmpRect.equals(mWindowDragBounds)) {
                             // We were using fullscreen surface during resizing. Request
                             // resizeTask() one last time to restore surface to window size.
-                            mService.mActivityManager.resizeTask(
+                            mActivityManager.resizeTask(
                                     mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER_FORCED);
                         }
                     } catch(RemoteException e) {}
@@ -216,9 +218,15 @@
         }
     }
 
+    @VisibleForTesting
+    TaskPositioner(WindowManagerService service, IActivityManager activityManager) {
+        mService = service;
+        mActivityManager = activityManager;
+    }
+
     /** Use {@link #create(WindowManagerService)} instead **/
     TaskPositioner(WindowManagerService service) {
-        mService = service;
+        this(service, service.mActivityManager);
     }
 
     @VisibleForTesting
@@ -349,8 +357,7 @@
         startDrag(resize, preserveOrientation, startX, startY, mTmpRect);
     }
 
-    @VisibleForTesting
-    void startDrag(boolean resize, boolean preserveOrientation,
+    private void startDrag(boolean resize, boolean preserveOrientation,
                    float startX, float startY, Rect startBounds) {
         mCtrlType = CTRL_NONE;
         mStartDragX = startX;
@@ -394,7 +401,7 @@
             // guaranteed to happen before subsequent drag resizes.
             mService.mH.post(() -> {
                 try {
-                    mService.mActivityManager.resizeTask(
+                    mActivityManager.resizeTask(
                             mTask.mTaskId, startBounds, RESIZE_MODE_USER_FORCED);
                 } catch (RemoteException e) {
                 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index c366e4d..7b775f5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -54,7 +54,7 @@
     static final boolean DEBUG_STARTING_WINDOW_VERBOSE = false;
     static final boolean DEBUG_STARTING_WINDOW = DEBUG_STARTING_WINDOW_VERBOSE || false;
     static final boolean DEBUG_WALLPAPER = false;
-    static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
+    static final boolean DEBUG_WALLPAPER_LIGHT = true || DEBUG_WALLPAPER;
     static final boolean DEBUG_DRAG = false;
     static final boolean DEBUG_SCREEN_ON = false;
     static final boolean DEBUG_SCREENSHOT = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ab19b82..a2ffcae 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2371,6 +2371,12 @@
     @Override
     public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
             IBinder freezeThisOneIfNeeded, int displayId) {
+        return updateOrientationFromAppTokens(currentConfig, freezeThisOneIfNeeded, displayId,
+                false /* forceUpdate */);
+    }
+
+    public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
+            IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
@@ -2380,7 +2386,7 @@
         try {
             synchronized(mWindowMap) {
                 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
-                        displayId);
+                        displayId, forceUpdate);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -2390,13 +2396,13 @@
     }
 
     private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
-            IBinder freezeThisOneIfNeeded, int displayId) {
+            IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) {
         if (!mDisplayReady) {
             return null;
         }
         Configuration config = null;
 
-        if (updateOrientationFromAppTokensLocked(displayId)) {
+        if (updateOrientationFromAppTokensLocked(displayId, forceUpdate)) {
             // If we changed the orientation but mOrientationChangeComplete is already true,
             // we used seamless rotation, and we don't need to freeze the screen.
             if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
@@ -2444,11 +2450,15 @@
      * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
      */
     boolean updateOrientationFromAppTokensLocked(int displayId) {
+        return updateOrientationFromAppTokensLocked(displayId, false /* forceUpdate */);
+    }
+
+    boolean updateOrientationFromAppTokensLocked(int displayId, boolean forceUpdate) {
         long ident = Binder.clearCallingIdentity();
         try {
             final DisplayContent dc = mRoot.getDisplayContent(displayId);
             final int req = dc.getOrientation();
-            if (req != dc.getLastOrientation()) {
+            if (req != dc.getLastOrientation() || forceUpdate) {
                 dc.setLastOrientation(req);
                 //send a message to Policy indicating orientation change to take
                 //action like disabling/enabling sensors etc.,
@@ -2456,12 +2466,8 @@
                 if (dc.isDefaultDisplay) {
                     mPolicy.setCurrentOrientationLw(req);
                 }
-                if (dc.updateRotationUnchecked()) {
-                    // changed
-                    return true;
-                }
+                return dc.updateRotationUnchecked(forceUpdate);
             }
-
             return false;
         } finally {
             Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 0c9ed21..a18d34b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -87,6 +87,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
@@ -1763,7 +1764,7 @@
     @Override
     void onResize() {
         final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
-        if (mHasSurface && !resizingWindows.contains(this)) {
+        if (mHasSurface && !isGoneForLayoutLw() && !resizingWindows.contains(this)) {
             if (DEBUG_RESIZE) Slog.d(TAG, "onResize: Resizing " + this);
             resizingWindows.add(this);
         }
@@ -4210,10 +4211,15 @@
         }
         if (!mWinAnimator.mLastHidden || wasDeferred) {
             mWinAnimator.hide(reason);
+            getDisplayContent().mWallpaperController.mDeferredHideWallpaper = null;
             dispatchWallpaperVisibility(false);
             final DisplayContent displayContent = getDisplayContent();
             if (displayContent != null) {
                 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+                if (DEBUG_LAYOUT_REPEATS) {
+                    mService.mWindowPlacerLocked.debugLayoutRepeats("hideWallpaperWindow " + this,
+                            displayContent.pendingLayoutChanges);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3eef125..561c9de 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1115,7 +1115,7 @@
 
         setSurfaceBoundariesLocked(recoveringMemory);
 
-        if (mIsWallpaper && !mWin.mWallpaperVisible) {
+        if (mIsWallpaper && !w.mWallpaperVisible) {
             // Wallpaper is no longer visible and there is no wp target => hide it.
             hide("prepareSurfaceLocked");
         } else if (w.isParentWindowHidden() || !w.isOnScreen()) {
@@ -1179,6 +1179,11 @@
                         // LogicalDisplay.
                         mAnimator.setPendingLayoutChanges(w.getDisplayId(),
                                 FINISH_LAYOUT_REDO_ANIM);
+                        if (DEBUG_LAYOUT_REPEATS) {
+                            mService.mWindowPlacerLocked.debugLayoutRepeats(
+                                    "showSurfaceRobustlyLocked " + w,
+                                    mAnimator.getPendingLayoutChanges(w.getDisplayId()));
+                        }
                     } else {
                         w.setOrientationChanging(false);
                     }
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index 8399aaf..d16bc26 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -22,9 +22,7 @@
 import static com.android.server.backup.testing.TransportData.localTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpCurrentTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpTransports;
-
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -43,9 +41,10 @@
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.os.HandlerThread;
+import android.os.PowerManager;
+import android.os.PowerSaveState;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-
 import com.android.server.backup.internal.BackupRequest;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
@@ -54,8 +53,11 @@
 import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowAppBackupUtils;
 import com.android.server.testing.shadows.ShadowBackupPolicyEnforcer;
+import com.android.server.testing.shadows.ShadowBinder;
+import com.android.server.testing.shadows.ShadowKeyValueBackupJob;
 import com.android.server.testing.shadows.ShadowPerformBackupTask;
-
+import java.io.File;
+import java.util.List;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -64,6 +66,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implements;
 import org.robolectric.shadows.ShadowContextWrapper;
 import org.robolectric.shadows.ShadowLog;
 import org.robolectric.shadows.ShadowLooper;
@@ -71,9 +74,6 @@
 import org.robolectric.shadows.ShadowSettings;
 import org.robolectric.shadows.ShadowSystemClock;
 
-import java.io.File;
-import java.util.List;
-
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
         manifest = Config.NONE,
@@ -796,6 +796,34 @@
         tearDownForRequestBackup();
     }
 
+    @Test
+    @Config(shadows = {ShadowBinder.class, ShadowKeyValueBackupJob.class})
+    public void testBackupNow_clearsCallingIdentityForJobScheduler() {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        BackupManagerService backupManagerService = createInitializedBackupManagerService();
+        setUpPowerManager(backupManagerService);
+        ShadowBinder.setCallingUid(1);
+
+        backupManagerService.backupNow();
+
+        assertThat(ShadowKeyValueBackupJob.getCallingUid()).isEqualTo(ShadowBinder.LOCAL_UID);
+        assertThat(ShadowBinder.getCallingUid()).isEqualTo(1);
+    }
+
+    @Test
+    @Config(shadows = {ShadowBinder.class, ShadowKeyValueBackupJobException.class})
+    public void testBackupNow_whenExceptionThrown_restoresCallingIdentity() {
+        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
+        BackupManagerService backupManagerService = createInitializedBackupManagerService();
+        setUpPowerManager(backupManagerService);
+        ShadowBinder.setCallingUid(1);
+
+        expectThrows(IllegalArgumentException.class, backupManagerService::backupNow);
+        assertThat(ShadowKeyValueBackupJobException.getCallingUid())
+                .isEqualTo(ShadowBinder.LOCAL_UID);
+        assertThat(ShadowBinder.getCallingUid()).isEqualTo(1);
+    }
+
     private BackupManagerService createBackupManagerServiceForRequestBackup() {
         BackupManagerService backupManagerService = createInitializedBackupManagerService();
         backupManagerService.setEnabled(true);
@@ -853,4 +881,23 @@
         ShadowSystemClock.setCurrentTimeMillis(mShadowBackupLooper.getScheduler().getCurrentTime());
         return backupManagerService;
     }
+
+    private void setUpPowerManager(BackupManagerService backupManagerService) {
+        PowerManager powerManagerMock = mock(PowerManager.class);
+        when(powerManagerMock.getPowerSaveState(anyInt()))
+                .thenReturn(new PowerSaveState.Builder().setBatterySaverEnabled(true).build());
+        backupManagerService.setPowerManager(powerManagerMock);
+    }
+
+    /**
+     * We can't mock the void method {@link #schedule(Context, long, BackupManagerConstants)} so we
+     * extend {@link ShadowKeyValueBackupJob} and throw an exception at the end of the method.
+     */
+    @Implements(KeyValueBackupJob.class)
+    public static class ShadowKeyValueBackupJobException extends ShadowKeyValueBackupJob {
+        public static void schedule(Context ctx, long delay, BackupManagerConstants constants) {
+            ShadowKeyValueBackupJob.schedule(ctx, delay, constants);
+            throw new IllegalArgumentException();
+        }
+    }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
new file mode 100644
index 0000000..043d44b
--- /dev/null
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
@@ -0,0 +1,44 @@
+/*
+ * 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.testing.shadows;
+
+import android.os.Binder;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+/**
+ * Extends {@link org.robolectric.shadows.ShadowBinder} with {@link Binder#clearCallingIdentity()}
+ * and {@link Binder#restoreCallingIdentity(long)}. Uses a hardcoded default {@link #LOCAL_UID} to
+ * mimic the local process uid.
+ */
+@Implements(Binder.class)
+public class ShadowBinder extends org.robolectric.shadows.ShadowBinder {
+    public static final Integer LOCAL_UID = 1000;
+    private static Integer originalCallingUid;
+
+    @Implementation
+    public static long clearCallingIdentity() {
+        originalCallingUid = getCallingUid();
+        setCallingUid(LOCAL_UID);
+        return 1L;
+    }
+
+    @Implementation
+    public static void restoreCallingIdentity(long token) {
+        setCallingUid(originalCallingUid);
+    }
+}
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
new file mode 100644
index 0000000..3941f17
--- /dev/null
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
@@ -0,0 +1,38 @@
+/*
+ * 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.testing.shadows;
+
+import android.content.Context;
+import android.os.Binder;
+import com.android.server.backup.BackupManagerConstants;
+import com.android.server.backup.KeyValueBackupJob;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(KeyValueBackupJob.class)
+public class ShadowKeyValueBackupJob {
+    private static int callingUid;
+
+    public static int getCallingUid() {
+        return callingUid;
+    }
+
+    @Implementation
+    public static void schedule(Context ctx, long delay, BackupManagerConstants constants) {
+        callingUid = Binder.getCallingUid();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
index 5daacd7..933b3d6 100644
--- a/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
@@ -445,7 +445,7 @@
         areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
         areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
 
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_1}, new int[] {UID_2});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_1}, new int[] {}, new int[] {UID_2});
 
         areRestricted(instance, UID_1, PACKAGE_1, NONE);
         areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
@@ -482,6 +482,15 @@
     }
 
     @Test
+    public void testPowerSaveUserWhitelist() throws Exception {
+        final AppStateTrackerTestable instance = newInstance();
+        instance.setPowerSaveWhitelistAppIds(new int[] {}, new int[] {UID_1, UID_2}, new int[] {});
+        assertTrue(instance.isUidPowerSaveUserWhitelisted(UID_1));
+        assertTrue(instance.isUidPowerSaveUserWhitelisted(UID_2));
+        assertFalse(instance.isUidPowerSaveUserWhitelisted(UID_3));
+    }
+
+    @Test
     public void testUidStateForeground() throws Exception {
         final AppStateTrackerTestable instance = newInstance();
         callStart(instance);
@@ -861,7 +870,7 @@
         // -------------------------------------------------------------------------
         // Tests with system/user/temp whitelist.
 
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {}, new int[] {});
 
         waitUntilMainHandlerDrain();
         verify(l, times(1)).updateAllJobs();
@@ -873,7 +882,7 @@
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {}, new int[] {});
 
         waitUntilMainHandlerDrain();
         verify(l, times(1)).updateAllJobs();
@@ -886,7 +895,8 @@
         reset(l);
 
         // Update temp whitelist.
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {UID_1, UID_3});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {},
+                new int[] {UID_1, UID_3});
 
         waitUntilMainHandlerDrain();
         verify(l, times(1)).updateAllJobs();
@@ -898,7 +908,7 @@
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {UID_3});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {}, new int[] {UID_3});
 
         waitUntilMainHandlerDrain();
         verify(l, times(1)).updateAllJobs();
@@ -924,7 +934,7 @@
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {}, new int[] {});
 
         waitUntilMainHandlerDrain();
         // Called once for updating all whitelist and once for updating temp whitelist
@@ -937,7 +947,7 @@
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {}, new int[] {});
 
         waitUntilMainHandlerDrain();
         verify(l, times(1)).updateAllJobs();
@@ -950,7 +960,8 @@
         reset(l);
 
         // Update temp whitelist.
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {UID_1, UID_3});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {},
+                new int[] {UID_1, UID_3});
 
         waitUntilMainHandlerDrain();
         verify(l, times(1)).updateAllJobs();
@@ -962,7 +973,7 @@
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
-        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {UID_3});
+        instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {}, new int[] {UID_3});
 
         waitUntilMainHandlerDrain();
         verify(l, times(1)).updateAllJobs();
diff --git a/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java b/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
index ea0fe45..7f397d6 100644
--- a/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appops/AppOpsActiveWatcherTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
@@ -36,6 +38,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.List;
+
 /**
  * Tests app ops version upgrades
  */
@@ -107,6 +111,46 @@
         verifyNoMoreInteractions(listener);
     }
 
+    @Test
+    public void testIsRunning() throws Exception {
+        final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+        // Start the op
+        appOpsManager.startOp(AppOpsManager.OP_CAMERA);
+
+        assertTrue("Camera should be running", isCameraOn(appOpsManager));
+
+        // Finish the op
+        appOpsManager.finishOp(AppOpsManager.OP_CAMERA);
+
+        assertFalse("Camera should not be running", isCameraOn(appOpsManager));
+    }
+
+    private boolean isCameraOn(AppOpsManager appOpsManager) {
+        List<AppOpsManager.PackageOps> packages
+                = appOpsManager.getPackagesForOps(new int[] {AppOpsManager.OP_CAMERA});
+        // AppOpsManager can return null when there is no requested data.
+        if (packages != null) {
+            final int numPackages = packages.size();
+            for (int packageInd = 0; packageInd < numPackages; packageInd++) {
+                AppOpsManager.PackageOps packageOp = packages.get(packageInd);
+                List<AppOpsManager.OpEntry> opEntries = packageOp.getOps();
+                if (opEntries != null) {
+                    final int numOps = opEntries.size();
+                    for (int opInd = 0; opInd < numOps; opInd++) {
+                        AppOpsManager.OpEntry opEntry = opEntries.get(opInd);
+                        if (opEntry.getOp() == AppOpsManager.OP_CAMERA) {
+                            if (opEntry.isRunning()) {
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
     private static Context getContext() {
         return InstrumentationRegistry.getContext();
     }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
new file mode 100644
index 0000000..78cb56b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -0,0 +1,221 @@
+/*
+ * 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.hdmi;
+
+import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
+import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
+import static com.android.server.hdmi.Constants.ADDR_TV;
+import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
+import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID;
+import static com.android.server.hdmi.Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.hardware.hdmi.HdmiPortInfo;
+import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
+import android.os.MessageQueue;
+import com.android.server.hdmi.HdmiCecController.NativeWrapper;
+import junit.framework.Assert;
+import java.util.Arrays;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+/**
+ * Tests for {@link HdmiCecLocalDevice} class.
+ */
+public class HdmiCecLocalDeviceTest {
+
+    private static final class NativeWrapperImpl implements NativeWrapper {
+
+        @Override
+        public long nativeInit(HdmiCecController handler, MessageQueue messageQueue) {
+            return 1L;
+        }
+
+        @Override
+        public int nativeSendCecCommand(long controllerPtr, int srcAddress, int dstAddress,
+            byte[] body) {
+            return SendCecCommandFactory(srcAddress, dstAddress, body);
+        }
+
+        @Override
+        public int nativeAddLogicalAddress(long controllerPtr, int logicalAddress) {
+            return 0;
+        }
+
+        @Override
+        public void nativeClearLogicalAddress(long controllerPtr) {
+
+        }
+
+        @Override
+        public int nativeGetPhysicalAddress(long controllerPtr) {
+            return mPhysicalAddr;
+        }
+
+        @Override
+        public int nativeGetVersion(long controllerPtr) {
+            return 0;
+        }
+
+        @Override
+        public int nativeGetVendorId(long controllerPtr) {
+            return 0;
+        }
+
+        @Override
+        public HdmiPortInfo[] nativeGetPortInfos(long controllerPtr) {
+            return new HdmiPortInfo[0];
+        }
+
+        @Override
+        public void nativeSetOption(long controllerPtr, int flag, boolean enabled) {
+
+        }
+
+        @Override
+        public void nativeSetLanguage(long controllerPtr, String language) {
+
+        }
+
+        @Override
+        public void nativeEnableAudioReturnChannel(long controllerPtr, int port, boolean flag) {
+
+        }
+
+        @Override
+        public boolean nativeIsConnected(long controllerPtr, int port) {
+            return false;
+        }
+    }
+
+    private static int SendCecCommandFactory(int srcAddress, int dstAddress, byte[] body) {
+        switch(body[0] & 0xFF) {
+            /** {@link Constants#MESSAGE_GIVE_PHYSICAL_ADDRESS} */
+            case MESSAGE_REPORT_PHYSICAL_ADDRESS:
+            case MESSAGE_DEVICE_VENDOR_ID:
+                return srcAddress == mSrcAddr &&
+                    dstAddress == mDesAddr &&
+                    Arrays.equals(Arrays.copyOfRange(body, 1, body.length), param)? 0 : 1;
+            default:
+                return 1;
+        }
+    }
+
+    private class MyHdmiCecLocalDevice extends HdmiCecLocalDevice {
+
+
+        protected MyHdmiCecLocalDevice(HdmiControlService service, int deviceType) {
+            super(service, deviceType);
+        }
+
+        @Override
+        protected void onAddressAllocated(int logicalAddress, int reason) {
+
+        }
+
+        @Override
+        protected int getPreferredAddress() {
+            return 0;
+        }
+
+        @Override
+        protected void setPreferredAddress(int addr) {
+
+        }
+    }
+
+    private MyHdmiCecLocalDevice mHdmiLocalDevice;
+    private HdmiControlService mHdmiControlService;
+    private HdmiCecController mHdmiCecController;
+    private TestLooper mTestLooper = new TestLooper();
+    private static int mDesAddr = -1;
+    private static int mSrcAddr = -1;
+    private static int mPhysicalAddr = 2;
+    private int callbackResult;
+    private HdmiCecMessageValidator mMessageValidator;
+    private static byte[] param;
+
+    @Before
+    public void SetUp() {
+        mHdmiControlService = new HdmiControlService(null);
+        mHdmiControlService.setIoLooper(mTestLooper.getLooper());
+        mHdmiCecController = HdmiCecController.createWithNativeWrapper(
+            mHdmiControlService, new NativeWrapperImpl());
+        mHdmiControlService.setCecController(mHdmiCecController);
+        mHdmiLocalDevice = new MyHdmiCecLocalDevice(
+            mHdmiControlService, DEVICE_TV);
+        mMessageValidator = new HdmiCecMessageValidator(mHdmiControlService){
+            @Override
+            int isValid(HdmiCecMessage message) {
+                return HdmiCecMessageValidator.OK;
+            }
+        };
+        mHdmiControlService.setMessageValidator(mMessageValidator);
+    }
+
+    @Test
+    public void dispatchMessage_desNotValid() {
+        HdmiCecMessage msg = new HdmiCecMessage(
+            ADDR_TV, ADDR_TV, Constants.MESSAGE_CEC_VERSION, HdmiCecMessage.EMPTY_PARAM);
+        boolean handleResult = mHdmiLocalDevice.dispatchMessage(msg);
+        assertFalse(handleResult);
+    }
+
+    @Test
+    public void handleGivePhysicalAddress_success() {
+        mSrcAddr = ADDR_UNREGISTERED;
+        mDesAddr = ADDR_BROADCAST;
+        param = new byte[] {
+            (byte) ((mPhysicalAddr >> 8) & 0xFF),
+            (byte) (mPhysicalAddr & 0xFF),
+            (byte) (DEVICE_TV & 0xFF)
+        };
+        callbackResult = -1;
+        boolean handleResult = mHdmiLocalDevice.handleGivePhysicalAddress(
+            (int finalResult) -> callbackResult = finalResult);
+        mTestLooper.dispatchAll();
+        /**
+         * Test if CecMessage is sent successfully
+         * SendMessageResult#SUCCESS is defined in HAL as 0
+         */
+        assertEquals(0, callbackResult);
+        assertTrue(handleResult);
+    }
+
+    @Test
+    public void handleGiveDeviceVendorId_success() {
+        mSrcAddr = ADDR_UNREGISTERED;
+        mDesAddr = ADDR_BROADCAST;
+        /** nativeGetVendorId returns 0 */
+        param = new byte[] {
+            (byte) ((0 >> 8) & 0xFF),
+            (byte) (0 & 0xFF),
+            (byte) (0 & 0xFF)
+        };
+        callbackResult = -1;
+        mHdmiLocalDevice.handleGiveDeviceVendorId(
+            (int finalResult) -> callbackResult = finalResult);
+        mTestLooper.dispatchAll();
+        assertEquals(0, callbackResult);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index dee2556..8461166 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -218,6 +218,11 @@
                     + "stable_charging_threshold=" + STABLE_CHARGING_THRESHOLD;
         }
 
+        @Override
+        public boolean isDeviceIdleMode() {
+            return false;
+        }
+
         // Internal methods
 
         void setDisplayOn(boolean on) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 0c63cd2..f6599dc 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -202,11 +202,6 @@
         assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
         // Can specify orientation if the current orientation candidate is orientation behind.
         assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation(SCREEN_ORIENTATION_BEHIND));
-
-        mToken.sendingToBottom = false;
-        mToken.setIsOnTop(true);
-        // Allow for mToken to provide orientation hidden if on top and not being sent to bottom.
-        assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation());
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
index 7bf7dd7..4447b26 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import android.app.IActivityManager;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -27,7 +28,10 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Display;
+import org.mockito.Mockito;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
 import static com.android.server.wm.WindowManagerService.dipToPixel;
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
@@ -54,6 +58,8 @@
     private int mMinVisibleWidth;
     private int mMinVisibleHeight;
     private TaskPositioner mPositioner;
+    private WindowState mWindow;
+    private Rect mDimBounds = new Rect();
 
     @Before
     public void setUp() throws Exception {
@@ -69,8 +75,20 @@
         mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
         mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
 
-        mPositioner = TaskPositioner.create(sWm);
+        mPositioner = new TaskPositioner(sWm, Mockito.mock(IActivityManager.class));
         mPositioner.register(mDisplayContent);
+
+        mWindow = Mockito.spy(createWindow(null, TYPE_BASE_APPLICATION, "window"));
+        final Task task = Mockito.spy(mWindow.getTask());
+        Mockito.when(mWindow.getTask()).thenReturn(task);
+
+        Mockito.doAnswer(invocation -> {
+            final Rect rect = (Rect) invocation.getArguments()[0];
+            rect.set(mDimBounds);
+            return (Void) null;
+        }).when(task).getDimBounds(Mockito.any(Rect.class));
+
+        mWindow.getStack().setWindowingMode(WINDOWING_MODE_FREEFORM);
     }
 
     @Test
@@ -94,14 +112,14 @@
      * as does some basic tests (e.g. dragging in Y only will keep X stable).
      */
     @Test
-    @Ignore
     public void testBasicFreeWindowResizing() throws Exception {
         final Rect r = new Rect(100, 220, 700, 520);
         final int midY = (r.top + r.bottom) / 2;
+        mDimBounds.set(r);
 
         // Start a drag resize starting upper left.
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
         assertBoundsEquals(r, mPositioner.getWindowDragBounds());
 
         // Drag to a good landscape size.
@@ -127,8 +145,8 @@
                 mPositioner.getWindowDragBounds());
 
         // Start a drag resize left and see that only the left coord changes..
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY);
 
         // Drag to the left.
         mPositioner.resizeDrag(0.0f, midY);
@@ -155,15 +173,15 @@
      * This tests that by dragging any edge, the fixed / opposite edge(s) remains anchored.
      */
     @Test
-    @Ignore
     public void testFreeWindowResizingTestAllEdges() throws Exception {
         final Rect r = new Rect(100, 220, 700, 520);
         final int midX = (r.left + r.right) / 2;
         final int midY = (r.top + r.bottom) / 2;
+        mDimBounds.set(r);
 
         // Drag upper left.
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
         mPositioner.resizeDrag(0.0f, 0.0f);
         assertTrue(r.left != mPositioner.getWindowDragBounds().left);
         assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -171,8 +189,8 @@
         assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
 
         // Drag upper.
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y);
         mPositioner.resizeDrag(0.0f, 0.0f);
         assertEquals(r.left, mPositioner.getWindowDragBounds().left);
         assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -180,8 +198,8 @@
         assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
 
         // Drag upper right.
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
         mPositioner.resizeDrag(r.right + 100, 0.0f);
         assertEquals(r.left, mPositioner.getWindowDragBounds().left);
         assertTrue(r.right != mPositioner.getWindowDragBounds().right);
@@ -189,8 +207,8 @@
         assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
 
         // Drag right.
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, midY, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, r.right + MOUSE_DELTA_X, midY);
         mPositioner.resizeDrag(r.right + 100, 0.0f);
         assertEquals(r.left, mPositioner.getWindowDragBounds().left);
         assertTrue(r.right != mPositioner.getWindowDragBounds().right);
@@ -198,9 +216,9 @@
         assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
 
         // Drag bottom right.
-        mPositioner.startDrag(true /*resizing*/,
+        mPositioner.startDrag(mWindow, true /*resizing*/,
                 false /*preserveOrientation*/,
-                r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
+                r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
         mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
         assertEquals(r.left, mPositioner.getWindowDragBounds().left);
         assertTrue(r.right != mPositioner.getWindowDragBounds().right);
@@ -208,8 +226,8 @@
         assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
 
         // Drag bottom.
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, midX, r.bottom + MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, midX, r.bottom + MOUSE_DELTA_Y);
         mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
         assertEquals(r.left, mPositioner.getWindowDragBounds().left);
         assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -217,8 +235,8 @@
         assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
 
         // Drag bottom left.
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
         mPositioner.resizeDrag(0.0f, r.bottom + 100);
         assertTrue(r.left != mPositioner.getWindowDragBounds().left);
         assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -226,8 +244,8 @@
         assertTrue(r.bottom != mPositioner.getWindowDragBounds().bottom);
 
         // Drag left.
-        mPositioner.startDrag(true /*resizing*/,
-                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midX, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                false /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midX);
         mPositioner.resizeDrag(0.0f, r.bottom + 100);
         assertTrue(r.left != mPositioner.getWindowDragBounds().left);
         assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -240,12 +258,12 @@
      * right things upon resizing when dragged from the top left corner.
      */
     @Test
-    @Ignore
     public void testLandscapePreservedWindowResizingDragTopLeft() throws Exception {
         final Rect r = new Rect(100, 220, 700, 520);
+        mDimBounds.set(r);
 
-        mPositioner.startDrag(true /*resizing*/,
-                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
         assertBoundsEquals(r, mPositioner.getWindowDragBounds());
 
         // Drag to a good landscape size.
@@ -278,13 +296,13 @@
      * right things upon resizing when dragged from the left corner.
      */
     @Test
-    @Ignore
     public void testLandscapePreservedWindowResizingDragLeft() throws Exception {
         final Rect r = new Rect(100, 220, 700, 520);
         final int midY = (r.top + r.bottom) / 2;
+        mDimBounds.set(r);
 
-        mPositioner.startDrag(true /*resizing*/,
-                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY);
 
         // Drag to the left.
         mPositioner.resizeDrag(0.0f, midY);
@@ -319,13 +337,13 @@
      * right things upon resizing when dragged from the top corner.
      */
     @Test
-    @Ignore
     public void testLandscapePreservedWindowResizingDragTop() throws Exception {
         final Rect r = new Rect(100, 220, 700, 520);
         final int midX = (r.left + r.right) / 2;
+        mDimBounds.set(r);
 
-        mPositioner.startDrag(true /*resizing*/,
-                true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y);
 
         // Drag to the left (no change).
         mPositioner.resizeDrag(0.0f, r.top);
@@ -356,12 +374,12 @@
      * right things upon resizing when dragged from the top left corner.
      */
     @Test
-    @Ignore
     public void testPortraitPreservedWindowResizingDragTopLeft() throws Exception {
         final Rect r = new Rect(330, 100, 630, 600);
+        mDimBounds.set(r);
 
-        mPositioner.startDrag(true /*resizing*/,
-                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
         assertBoundsEquals(r, mPositioner.getWindowDragBounds());
 
         // Drag to a good landscape size.
@@ -371,8 +389,8 @@
                 mPositioner.getWindowDragBounds());
 
         // Drag to a good portrait size.
-        mPositioner.resizeDrag(500.0f, 0.0f);
-        assertBoundsEquals(new Rect(500 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
+        mPositioner.resizeDrag(400.0f, 0.0f);
+        assertBoundsEquals(new Rect(400 + MOUSE_DELTA_X, MOUSE_DELTA_Y, r.right, r.bottom),
                 mPositioner.getWindowDragBounds());
 
         // Drag to a too small size for the height and the the width shrinking.
@@ -389,13 +407,13 @@
      * right things upon resizing when dragged from the left corner.
      */
     @Test
-    @Ignore
     public void testPortraitPreservedWindowResizingDragLeft() throws Exception {
         final Rect r = new Rect(330, 100, 630, 600);
         final int midY = (r.top + r.bottom) / 2;
+        mDimBounds.set(r);
 
-        mPositioner.startDrag(true /*resizing*/,
-                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, midY);
 
         // Drag to the left.
         mPositioner.resizeDrag(0.0f, midY);
@@ -432,13 +450,13 @@
      * right things upon resizing when dragged from the top corner.
      */
     @Test
-    @Ignore
     public void testPortraitPreservedWindowResizingDragTop() throws Exception {
         final Rect r = new Rect(330, 100, 630, 600);
         final int midX = (r.left + r.right) / 2;
+        mDimBounds.set(r);
 
-        mPositioner.startDrag(true /*resizing*/,
-                true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y, r);
+        mPositioner.startDrag(mWindow, true /*resizing*/,
+                true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y);
 
         // Drag to the left (no change).
         mPositioner.resizeDrag(0.0f, r.top);
@@ -472,9 +490,9 @@
                         + ") " + Log.getStackTraceString(new Throwable()));
             }
         }
-        assertEquals(expected.left, actual.left);
-        assertEquals(expected.right, actual.right);
-        assertEquals(expected.top, actual.top);
-        assertEquals(expected.bottom, actual.bottom);
+        assertEquals("left", expected.left, actual.left);
+        assertEquals("right", expected.right, actual.right);
+        assertEquals("top", expected.top, actual.top);
+        assertEquals("bottom", expected.bottom, actual.bottom);
     }
 }
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 3378897..9c62700 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -24,6 +24,8 @@
 import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
 import static android.app.usage.UsageStatsManager.REASON_SUB_PREDICTED_RESTORED;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_ACTIVE_TIMEOUT;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_START;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
@@ -194,8 +196,9 @@
     static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
     /** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
     static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
-    static final int MSG_REPORT_EXEMPTED_SYNC_START = 12;
-    static final int MSG_UPDATE_STABLE_CHARGING= 13;
+    static final int MSG_REPORT_EXEMPTED_SYNC_SCHEDULED = 12;
+    static final int MSG_REPORT_EXEMPTED_SYNC_START = 13;
+    static final int MSG_UPDATE_STABLE_CHARGING= 14;
 
     long mCheckIdleIntervalMillis;
     long mAppIdleParoleIntervalMillis;
@@ -213,8 +216,20 @@
     long mPredictionTimeoutMillis;
     /** Maximum time a sync adapter associated with a CP should keep the buckets elevated. */
     long mSyncAdapterTimeoutMillis;
-    /** Maximum time an exempted sync should keep the buckets elevated. */
-    long mExemptedSyncAdapterTimeoutMillis;
+    /**
+     * Maximum time an exempted sync should keep the buckets elevated, when sync is scheduled in
+     * non-doze
+     */
+    long mExemptedSyncScheduledNonDozeTimeoutMillis;
+    /**
+     * Maximum time an exempted sync should keep the buckets elevated, when sync is scheduled in
+     * doze
+     */
+    long mExemptedSyncScheduledDozeTimeoutMillis;
+    /**
+     * Maximum time an exempted sync should keep the buckets elevated, when sync is started.
+     */
+    long mExemptedSyncStartTimeoutMillis;
     /** Maximum time a system interaction should keep the buckets elevated. */
     long mSystemInteractionTimeoutMillis;
     /** The length of time phone must be charging before considered stable enough to run jobs  */
@@ -393,6 +408,37 @@
         }
     }
 
+    void reportExemptedSyncScheduled(String packageName, int userId) {
+        if (!mAppIdleEnabled) return;
+
+        final int bucketToPromote;
+        final int usageReason;
+        final long durationMillis;
+
+        if (!mInjector.isDeviceIdleMode()) {
+            // Not dozing.
+            bucketToPromote = STANDBY_BUCKET_ACTIVE;
+            usageReason = REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
+            durationMillis = mExemptedSyncScheduledNonDozeTimeoutMillis;
+        } else {
+            // Dozing.
+            bucketToPromote = STANDBY_BUCKET_WORKING_SET;
+            usageReason = REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
+            durationMillis = mExemptedSyncScheduledDozeTimeoutMillis;
+        }
+
+        final long elapsedRealtime = mInjector.elapsedRealtime();
+
+        synchronized (mAppIdleLock) {
+            AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
+                    bucketToPromote, usageReason,
+                    0,
+                    elapsedRealtime + durationMillis);
+            maybeInformListeners(packageName, userId, elapsedRealtime,
+                    appUsage.currentBucket, appUsage.bucketingReason, false);
+        }
+    }
+
     void reportExemptedSyncStart(String packageName, int userId) {
         if (!mAppIdleEnabled) return;
 
@@ -402,7 +448,7 @@
             AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
                     STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_EXEMPTED_SYNC_START,
                     0,
-                    elapsedRealtime + mExemptedSyncAdapterTimeoutMillis);
+                    elapsedRealtime + mExemptedSyncStartTimeoutMillis);
             maybeInformListeners(packageName, userId, elapsedRealtime,
                     appUsage.currentBucket, appUsage.bucketingReason, false);
         }
@@ -1365,6 +1411,11 @@
                 .sendToTarget();
     }
 
+    void postReportExemptedSyncScheduled(String packageName, int userId) {
+        mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_SCHEDULED, userId, 0, packageName)
+                .sendToTarget();
+    }
+
     void postReportExemptedSyncStart(String packageName, int userId) {
         mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_START, userId, 0, packageName)
                 .sendToTarget();
@@ -1401,6 +1452,16 @@
         TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
         pw.println();
 
+        pw.print("  mExemptedSyncScheduledNonDozeTimeoutMillis=");
+        TimeUtils.formatDuration(mExemptedSyncScheduledNonDozeTimeoutMillis, pw);
+        pw.println();
+        pw.print("  mExemptedSyncScheduledDozeTimeoutMillis=");
+        TimeUtils.formatDuration(mExemptedSyncScheduledDozeTimeoutMillis, pw);
+        pw.println();
+        pw.print("  mExemptedSyncStartTimeoutMillis=");
+        TimeUtils.formatDuration(mExemptedSyncStartTimeoutMillis, pw);
+        pw.println();
+
         pw.println();
         pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
         pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
@@ -1429,6 +1490,7 @@
         private IBatteryStats mBatteryStats;
         private PackageManagerInternal mPackageManagerInternal;
         private DisplayManager mDisplayManager;
+        private PowerManager mPowerManager;
         int mBootPhase;
 
         Injector(Context context, Looper looper) {
@@ -1453,6 +1515,7 @@
                 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
                 mDisplayManager = (DisplayManager) mContext.getSystemService(
                         Context.DISPLAY_SERVICE);
+                mPowerManager = mContext.getSystemService(PowerManager.class);
             }
             mBootPhase = phase;
         }
@@ -1532,6 +1595,11 @@
             return Global.getString(mContext.getContentResolver(),
                     Global.APP_IDLE_CONSTANTS);
         }
+
+        /** Whether the device is in doze or not. */
+        public boolean isDeviceIdleMode() {
+            return mPowerManager.isDeviceIdleMode();
+        }
     }
 
     class AppStandbyHandler extends Handler {
@@ -1595,6 +1663,10 @@
                             mInjector.elapsedRealtime());
                     break;
 
+                case MSG_REPORT_EXEMPTED_SYNC_SCHEDULED:
+                    reportExemptedSyncScheduled((String) msg.obj, msg.arg1);
+                    break;
+
                 case MSG_REPORT_EXEMPTED_SYNC_START:
                     reportExemptedSyncStart((String) msg.obj, msg.arg1);
                     break;
@@ -1684,7 +1756,12 @@
                 "system_update_usage_duration";
         private static final String KEY_PREDICTION_TIMEOUT = "prediction_timeout";
         private static final String KEY_SYNC_ADAPTER_HOLD_DURATION = "sync_adapter_duration";
-        private static final String KEY_EXEMPTED_SYNC_HOLD_DURATION = "exempted_sync_duration";
+        private static final String KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION
+                = "exempted_sync_scheduled_nd_duration";
+        private static final String KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION
+                = "exempted_sync_scheduled_d_duration";
+        private static final String KEY_EXEMPTED_SYNC_START_HOLD_DURATION
+                = "exempted_sync_start_duration";
         private static final String KEY_SYSTEM_INTERACTION_HOLD_DURATION =
                 "system_interaction_duration";
         private static final String KEY_STABLE_CHARGING_THRESHOLD = "stable_charging_threshold";
@@ -1693,7 +1770,9 @@
         public static final long DEFAULT_SYSTEM_UPDATE_TIMEOUT = 2 * ONE_HOUR;
         public static final long DEFAULT_SYSTEM_INTERACTION_TIMEOUT = 10 * ONE_MINUTE;
         public static final long DEFAULT_SYNC_ADAPTER_TIMEOUT = 10 * ONE_MINUTE;
-        public static final long DEFAULT_EXEMPTED_SYNC_TIMEOUT = 10 * ONE_MINUTE;
+        public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT = 10 * ONE_MINUTE;
+        public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT = 4 * ONE_HOUR;
+        public static final long DEFAULT_EXEMPTED_SYNC_START_TIMEOUT = 10 * ONE_MINUTE;
         public static final long DEFAULT_STABLE_CHARGING_THRESHOLD = 10 * ONE_MINUTE;
 
         private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -1778,9 +1857,22 @@
                 mSyncAdapterTimeoutMillis = mParser.getDurationMillis
                         (KEY_SYNC_ADAPTER_HOLD_DURATION,
                                 COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYNC_ADAPTER_TIMEOUT);
-                mExemptedSyncAdapterTimeoutMillis = mParser.getDurationMillis
-                        (KEY_EXEMPTED_SYNC_HOLD_DURATION,
-                                COMPRESS_TIME ? ONE_MINUTE : DEFAULT_EXEMPTED_SYNC_TIMEOUT);
+
+                mExemptedSyncScheduledNonDozeTimeoutMillis = mParser.getDurationMillis
+                        (KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION,
+                                COMPRESS_TIME ? (ONE_MINUTE / 2)
+                                        : DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT);
+
+                mExemptedSyncScheduledDozeTimeoutMillis = mParser.getDurationMillis
+                        (KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION,
+                                COMPRESS_TIME ? ONE_MINUTE
+                                        : DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT);
+
+                mExemptedSyncStartTimeoutMillis = mParser.getDurationMillis
+                        (KEY_EXEMPTED_SYNC_START_HOLD_DURATION,
+                                COMPRESS_TIME ? ONE_MINUTE
+                                        : DEFAULT_EXEMPTED_SYNC_START_TIMEOUT);
+
                 mSystemInteractionTimeoutMillis = mParser.getDurationMillis
                         (KEY_SYSTEM_INTERACTION_HOLD_DURATION,
                                 COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYSTEM_INTERACTION_TIMEOUT);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 7d42eb3..16f8fba 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1305,6 +1305,11 @@
         }
 
         @Override
+        public void reportExemptedSyncScheduled(String packageName, int userId) {
+            mAppStandby.postReportExemptedSyncScheduled(packageName, userId);
+        }
+
+        @Override
         public void reportExemptedSyncStart(String packageName, int userId) {
             mAppStandby.postReportExemptedSyncStart(packageName, userId);
         }
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 4334d3a..3138180 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -213,6 +213,17 @@
 
     /**
      * Notify the framework that the device is disconnected from the IMS network.
+     * <p>
+     * Note: Prior to calling {@link #onDeregistered(ImsReasonInfo)}, you should ensure that any
+     * changes to {@link android.telephony.ims.feature.ImsFeature} capability availability is sent
+     * to the framework.  For example,
+     * {@link android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}
+     * and
+     * {@link android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}
+     * may be set to unavailable to ensure the framework knows these services are no longer
+     * available due to de-registration.  If you do not report capability changes impacted by
+     * de-registration, the framework will not know which features are no longer available as a
+     * result.
      *
      * @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
      */
diff --git a/tests/ActivityTests/Android.mk b/tests/ActivityTests/Android.mk
index 61dbcc3..4c68c8b 100644
--- a/tests/ActivityTests/Android.mk
+++ b/tests/ActivityTests/Android.mk
@@ -9,9 +9,10 @@
 LOCAL_MODULE_TAGS := tests
 LOCAL_CERTIFICATE := platform
 
-# Disable AAPT2 to fix:
+LOCAL_USE_AAPT2 := true
+# Disable AAPT2 manifest checks to fix:
 # frameworks/base/tests/ActivityTests/AndroidManifest.xml:42: error: unexpected element <preferred> found in <manifest><application><activity>.
-# TODO(b/79755007): Re-enable AAPT2 when it supports the missing features.
-LOCAL_USE_AAPT2 := false
+# TODO(b/79755007): Remove when AAPT2 recognizes the manifest elements.
+LOCAL_AAPT_FLAGS += --warn-manifest-validation
 
 include $(BUILD_PACKAGE)
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 6ce66f0..4a6fe49 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -184,7 +184,8 @@
         if (null != launchDirectory && !launchDirectory.isEmpty()) {
             launchRootDir = new File(launchDirectory);
             if (!launchRootDir.exists() && !launchRootDir.mkdirs()) {
-                throw new IOException("Unable to create the destination directory");
+                throw new IOException("Unable to create the destination directory "
+                    + launchRootDir + ". Try disabling selinux.");
             }
         }
 
@@ -192,7 +193,8 @@
             File launchSubDir = new File(launchRootDir, LAUNCH_SUB_DIRECTORY);
 
             if (!launchSubDir.exists() && !launchSubDir.mkdirs()) {
-                throw new IOException("Unable to create the lauch file sub directory");
+                throw new IOException("Unable to create the lauch file sub directory "
+                    + launchSubDir + ". Try disabling selinux.");
             }
             File file = new File(launchSubDir, LAUNCH_FILE);
             FileOutputStream outputStream = new FileOutputStream(file);
@@ -769,6 +771,8 @@
                              BufferedWriter writer =
                                 new BufferedWriter(new OutputStreamWriter(stream))) {
                             String cmd = String.format(SIMPLEPERF_APP_CMD, packageName, launchCmd);
+                            // In the file, we need to escape any "$".
+                            cmd = cmd.replace("$", "\\$");
                             writer.write(cmd);
                         }
                         launchCmd = launchFile.getAbsolutePath();
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index ed9cbab..0248e97 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -77,7 +77,7 @@
 @SmallTest
 public class ApfTest {
     private static final int TIMEOUT_MS = 500;
-    private final static int MIN_APF_VERSION = 2;
+    private static final int MIN_APF_VERSION = 2;
 
     @Mock IpConnectivityLog mLog;
     @Mock Context mContext;
@@ -90,20 +90,30 @@
     }
 
     // Expected return codes from APF interpreter.
-    private final static int PASS = 1;
-    private final static int DROP = 0;
+    private static final int PASS = 1;
+    private static final int DROP = 0;
     // Interpreter will just accept packets without link layer headers, so pad fake packet to at
     // least the minimum packet size.
-    private final static int MIN_PKT_SIZE = 15;
+    private static final int MIN_PKT_SIZE = 15;
 
     private static final ApfCapabilities MOCK_APF_CAPABILITIES =
       new ApfCapabilities(2, 1700, ARPHRD_ETHER);
 
-    private final static boolean DROP_MULTICAST = true;
-    private final static boolean ALLOW_MULTICAST = false;
+    private static final boolean DROP_MULTICAST = true;
+    private static final boolean ALLOW_MULTICAST = false;
 
-    private final static boolean DROP_802_3_FRAMES = true;
-    private final static boolean ALLOW_802_3_FRAMES = false;
+    private static final boolean DROP_802_3_FRAMES = true;
+    private static final boolean ALLOW_802_3_FRAMES = false;
+
+    // Constants for opcode encoding
+    private static final byte LI_OP   = (byte)(13 << 3);
+    private static final byte LDDW_OP = (byte)(22 << 3);
+    private static final byte STDW_OP = (byte)(23 << 3);
+    private static final byte SIZE0   = (byte)(0 << 1);
+    private static final byte SIZE8   = (byte)(1 << 1);
+    private static final byte SIZE16  = (byte)(2 << 1);
+    private static final byte SIZE32  = (byte)(3 << 1);
+    private static final byte R1 = 1;
 
     private static ApfConfiguration getDefaultConfig() {
         ApfFilter.ApfConfiguration config = new ApfConfiguration();
@@ -636,29 +646,28 @@
      */
     @Test
     public void testImmediateEncoding() throws IllegalInstructionException {
-        final int LI_OPCODE = 13 << 3;
         ApfGenerator gen;
 
         // 0-byte immediate: li R0, 0
-        gen = new ApfGenerator(3);
+        gen = new ApfGenerator(4);
         gen.addLoadImmediate(Register.R0, 0);
-        assertProgramEquals(new byte[]{LI_OPCODE | (0 << 1)}, gen.generate());
+        assertProgramEquals(new byte[]{LI_OP | SIZE0}, gen.generate());
 
         // 1-byte immediate: li R0, 42
-        gen = new ApfGenerator(3);
+        gen = new ApfGenerator(4);
         gen.addLoadImmediate(Register.R0, 42);
-        assertProgramEquals(new byte[]{LI_OPCODE | (1 << 1), 42}, gen.generate());
+        assertProgramEquals(new byte[]{LI_OP | SIZE8, 42}, gen.generate());
 
         // 2-byte immediate: li R1, 0x1234
-        gen = new ApfGenerator(3);
+        gen = new ApfGenerator(4);
         gen.addLoadImmediate(Register.R1, 0x1234);
-        assertProgramEquals(new byte[]{LI_OPCODE | (2 << 1) | 1 , 0x12, 0x34}, gen.generate());
+        assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, 0x12, 0x34}, gen.generate());
 
         // 4-byte immediate: li R0, 0x12345678
         gen = new ApfGenerator(3);
         gen.addLoadImmediate(Register.R0, 0x12345678);
         assertProgramEquals(
-                new byte[]{LI_OPCODE | (3 << 1), 0x12, 0x34, 0x56, 0x78},
+                new byte[]{LI_OP | SIZE32, 0x12, 0x34, 0x56, 0x78},
                 gen.generate());
     }
 
@@ -667,28 +676,61 @@
      */
     @Test
     public void testNegativeImmediateEncoding() throws IllegalInstructionException {
-        final int LI_OPCODE = 13 << 3;
         ApfGenerator gen;
 
         // 1-byte negative immediate: li R0, -42
         gen = new ApfGenerator(3);
         gen.addLoadImmediate(Register.R0, -42);
-        assertProgramEquals(new byte[]{LI_OPCODE | (1 << 1), -42}, gen.generate());
+        assertProgramEquals(new byte[]{LI_OP | SIZE8, -42}, gen.generate());
 
-        // 2-byte negative immediate: li R1, -0x1234
+        // 2-byte negative immediate: li R1, -0x1122
         gen = new ApfGenerator(3);
         gen.addLoadImmediate(Register.R1, -0x1122);
-        assertProgramEquals(new byte[]{LI_OPCODE | (2 << 1) | 1, (byte)0xEE, (byte)0xDE},
+        assertProgramEquals(new byte[]{LI_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
                 gen.generate());
 
         // 4-byte negative immediate: li R0, -0x11223344
         gen = new ApfGenerator(3);
         gen.addLoadImmediate(Register.R0, -0x11223344);
         assertProgramEquals(
-                new byte[]{LI_OPCODE | (3 << 1), (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC},
+                new byte[]{LI_OP | SIZE32, (byte)0xEE, (byte)0xDD, (byte)0xCC, (byte)0xBC},
                 gen.generate());
     }
 
+    /**
+     * Test that the generator correctly emits positive and negative immediates for LDDW/STDW.
+     */
+    @Test
+    public void testLoadStoreDataEncoding() throws IllegalInstructionException {
+        ApfGenerator gen;
+
+        // Load data with no offset: lddw R0, [0 + r1]
+        gen = new ApfGenerator(3);
+        gen.addLoadData(Register.R0, 0);
+        assertProgramEquals(new byte[]{LDDW_OP | SIZE0}, gen.generate());
+
+        // Store data with 8bit negative offset: lddw r0, [-42 + r1]
+        gen = new ApfGenerator(3);
+        gen.addStoreData(Register.R0, -42);
+        assertProgramEquals(new byte[]{STDW_OP | SIZE8, -42}, gen.generate());
+
+        // Store data to R1 with 16bit negative offset: stdw r1, [-0x1122 + r0]
+        gen = new ApfGenerator(3);
+        gen.addStoreData(Register.R1, -0x1122);
+        assertProgramEquals(new byte[]{STDW_OP | SIZE16 | R1, (byte)0xEE, (byte)0xDE},
+                gen.generate());
+
+        // Load data to R1 with 32bit negative offset: lddw r1, [0xDEADBEEF + r0]
+        gen = new ApfGenerator(3);
+        gen.addLoadData(Register.R1, 0xDEADBEEF);
+        assertProgramEquals(
+                new byte[]{LDDW_OP | SIZE32 | R1, (byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF},
+                gen.generate());
+    }
+
+    /**
+     * Test that the interpreter correctly executes STDW with a negative 8bit offset
+     */
     @Test
     public void testApfDataWrite() throws IllegalInstructionException, Exception {
         byte[] packet = new byte[MIN_PKT_SIZE];
@@ -712,12 +754,15 @@
         assertDataMemoryContents(PASS, gen.generate(), packet, data, expected_data);
     }
 
+    /**
+     * Test that the interpreter correctly executes LDDW with a negative 16bit offset
+     */
     @Test
     public void testApfDataRead() throws IllegalInstructionException, Exception {
         // Program that DROPs if address 10 (-6) contains 0x87654321.
         ApfGenerator gen = new ApfGenerator(3);
-        gen.addLoadImmediate(Register.R1, 10);
-        gen.addLoadData(Register.R0, -16);  // 10 + -16 = -6 (offset +10 with data_len=16)
+        gen.addLoadImmediate(Register.R1, 1000);
+        gen.addLoadData(Register.R0, -1006);  // 1000 + -1006 = -6 (offset +10 with data_len=16)
         gen.addJumpIfR0Equals(0x87654321, gen.DROP_LABEL);
         byte[] program = gen.generate();
         byte[] packet = new byte[MIN_PKT_SIZE];
@@ -737,6 +782,11 @@
         assertDataMemoryContents(DROP, program, packet, data, expected_data);
     }
 
+    /**
+     * Test that the interpreter correctly executes LDDW followed by a STDW.
+     * To cover a few more edge cases, LDDW has a 0bit offset, while STDW has a positive 8bit
+     * offset.
+     */
     @Test
     public void testApfDataReadModifyWrite() throws IllegalInstructionException, Exception {
         ApfGenerator gen = new ApfGenerator(3);
@@ -844,7 +894,7 @@
     }
 
     private static class TestApfFilter extends ApfFilter {
-        public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
+        public static final byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
 
         private FileDescriptor mWriteSocket;
         private final long mFixedTimeMs = SystemClock.elapsedRealtime();
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 280e4c2..f89f303 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -227,9 +227,6 @@
 
     @After
     public void tearDown() throws Exception {
-        // Registered by NetworkStatsService's constructor.
-        LocalServices.removeServiceForTest(NetworkStatsManagerInternal.class);
-
         IoUtils.deleteContents(mStatsDir);
 
         mServiceContext = null;
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 74edf6e..c3fb728 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -2135,6 +2135,12 @@
           .OptionalFlag("--version-name",
                         "Version name to inject into the AndroidManifest.xml if none is present.",
                         &options.manifest_fixer_options.version_name_default)
+          .OptionalSwitch("--replace-version",
+                         "If --version-code and/or --version-name are specified, these\n"
+                         "values will replace any value already in the manifest. By\n"
+                         "default, nothing is changed if the manifest already defines\n"
+                         "these attributes.",
+                         &options.manifest_fixer_options.replace_version)
           .OptionalFlag("--compile-sdk-version-code",
                         "Version code (integer) to inject into the AndroidManifest.xml if none is\n"
                         "present.",
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index bfff148..ee4e702 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -261,6 +261,9 @@
   manifest_action.Action(FixCoreAppAttribute);
   manifest_action.Action([&](xml::Element* el) -> bool {
     if (options_.version_name_default) {
+      if (options_.replace_version) {
+        el->RemoveAttribute(xml::kSchemaAndroid, "versionName");
+      }
       if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
         el->attributes.push_back(
             xml::Attribute{xml::kSchemaAndroid, "versionName",
@@ -269,6 +272,9 @@
     }
 
     if (options_.version_code_default) {
+      if (options_.replace_version) {
+        el->RemoveAttribute(xml::kSchemaAndroid, "versionCode");
+      }
       if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
         el->attributes.push_back(
             xml::Attribute{xml::kSchemaAndroid, "versionCode",
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 7d6fad2..98d06fd 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -44,10 +44,12 @@
   // <instrumentation>.
   Maybe<std::string> rename_instrumentation_target_package;
 
-  // The version name to set if 'android:versionName' is not defined in <manifest>.
+  // The version name to set if 'android:versionName' is not defined in <manifest> or if
+  // replace_version is set.
   Maybe<std::string> version_name_default;
 
-  // The version code to set if 'android:versionCode' is not defined in <manifest>.
+  // The version code to set if 'android:versionCode' is not defined in <manifest> or if
+  // replace_version is set.
   Maybe<std::string> version_code_default;
 
   // The version of the framework being compiled against to set for 'android:compileSdkVersion' in
@@ -65,6 +67,9 @@
 
   // Whether to inject the android:debuggable="true" flag into the manifest
   bool debug_mode = false;
+
+  // Whether to replace the manifest version with the the command line version
+  bool replace_version = false;
 };
 
 // Verifies that the manifest is correctly formed and inserts defaults where specified with
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 5f406e8..5bc004d 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -349,6 +349,136 @@
   EXPECT_THAT(attr->value, StrEq("0x10000000"));
 }
 
+TEST_F(ManifestFixerTest, DontUseDefaultVersionNameAndCode) {
+ManifestFixerOptions options;
+options.version_name_default = std::string("Beta");
+options.version_code_default = std::string("0x10000000");
+
+std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                package="android"
+                android:versionCode="0x20000000"
+                android:versionName="Alpha" />)EOF",
+                                                          options);
+ASSERT_THAT(doc, NotNull());
+
+xml::Element* manifest_el = doc->root.get();
+ASSERT_THAT(manifest_el, NotNull());
+
+xml::Attribute* attr =
+    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Alpha"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x20000000"));
+}
+
+TEST_F(ManifestFixerTest, ReplaceVersionNameAndCode) {
+ManifestFixerOptions options;
+options.replace_version = true;
+options.version_name_default = std::string("Beta");
+options.version_code_default = std::string("0x10000000");
+
+std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+              package="android"
+              android:versionCode="0x20000000"
+              android:versionName="Alpha" />)EOF",
+                                                          options);
+ASSERT_THAT(doc, NotNull());
+
+xml::Element* manifest_el = doc->root.get();
+ASSERT_THAT(manifest_el, NotNull());
+
+xml::Attribute* attr =
+    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Beta"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x10000000"));
+}
+
+TEST_F(ManifestFixerTest, ReplaceVersionName) {
+ManifestFixerOptions options;
+options.replace_version = true;
+options.version_name_default = std::string("Beta");
+
+std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+            package="android"
+            android:versionCode="0x20000000"
+            android:versionName="Alpha" />)EOF",
+                                                          options);
+ASSERT_THAT(doc, NotNull());
+
+xml::Element* manifest_el = doc->root.get();
+ASSERT_THAT(manifest_el, NotNull());
+
+xml::Attribute* attr =
+    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Beta"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x20000000"));
+}
+
+TEST_F(ManifestFixerTest, ReplaceVersionCode) {
+ManifestFixerOptions options;
+options.replace_version = true;
+options.version_code_default = std::string("0x10000000");
+
+std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+            package="android"
+            android:versionCode="0x20000000"
+            android:versionName="Alpha" />)EOF",
+                                                          options);
+ASSERT_THAT(doc, NotNull());
+
+xml::Element* manifest_el = doc->root.get();
+ASSERT_THAT(manifest_el, NotNull());
+
+xml::Attribute* attr =
+    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Alpha"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x10000000"));
+}
+
+TEST_F(ManifestFixerTest, DontReplaceVersionNameOrCode) {
+ManifestFixerOptions options;
+options.replace_version = true;
+
+std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android"
+          android:versionCode="0x20000000"
+          android:versionName="Alpha" />)EOF",
+                                                          options);
+ASSERT_THAT(doc, NotNull());
+
+xml::Element* manifest_el = doc->root.get();
+ASSERT_THAT(manifest_el, NotNull());
+
+xml::Attribute* attr =
+    manifest_el->FindAttribute(xml::kSchemaAndroid, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Alpha"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x20000000"));
+}
+
 TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
   EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
   EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index b6cd086..acd07c2 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -423,6 +423,15 @@
   return nullptr;
 }
 
+void Element::RemoveAttribute(const StringPiece& ns, const StringPiece& name) {
+  auto new_attr_end = std::remove_if(attributes.begin(), attributes.end(),
+    [&](const Attribute& attr) -> bool {
+      return ns == attr.namespace_uri && name == attr.name;
+    });
+
+  attributes.erase(new_attr_end, attributes.end());
+}
+
 Attribute* Element::FindOrCreateAttribute(const StringPiece& ns, const StringPiece& name) {
   Attribute* attr = FindAttribute(ns, name);
   if (attr == nullptr) {
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index 8f382961..a5b2d10 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -102,6 +102,8 @@
                                  const android::StringPiece& name) const;
   Attribute* FindOrCreateAttribute(const android::StringPiece& ns,
                                    const android::StringPiece& name);
+  void RemoveAttribute(const android::StringPiece& ns,
+                       const android::StringPiece& name);
 
   Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
   const Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name) const;