Merge "Tie FAS service-start to the same idleness state as O+ bg restrictions" into pi-dev
diff --git a/api/test-current.txt b/api/test-current.txt
index f7bfeae..5cffd0e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -917,6 +917,7 @@
 
   public class TelephonyManager {
     method public int getCarrierIdListVersion();
+    method public void refreshUiccProfile();
     method public void setCarrierTestOverride(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     field public static final int UNKNOWN_CARRIER_ID_LIST_VERSION = -1; // 0xffffffff
   }
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 19ce180..6228473 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -229,6 +229,7 @@
 Landroid/app/AppOpsManager;->OP_WRITE_CONTACTS:I
 Landroid/app/AppOpsManager;->OP_WRITE_SMS:I
 Landroid/app/AppOpsManager;->permissionToOpCode(Ljava/lang/String;)I
+Landroid/app/AppOpsManager;->setRestriction(III[Ljava/lang/String;)V
 Landroid/app/AppOpsManager;->sOpPerms:[Ljava/lang/String;
 Landroid/app/AppOpsManager;->strOpToOp(Ljava/lang/String;)I
 Landroid/app/backup/BackupDataInput$EntityHeader;->dataSize:I
@@ -420,6 +421,7 @@
 Landroid/app/PendingIntent;->getActivityAsUser(Landroid/content/Context;ILandroid/content/Intent;ILandroid/os/Bundle;Landroid/os/UserHandle;)Landroid/app/PendingIntent;
 Landroid/app/PendingIntent;->getIntent()Landroid/content/Intent;
 Landroid/app/PendingIntent;->isActivity()Z
+Landroid/app/PictureInPictureParams;->getAspectRatio()F
 Landroid/app/Presentation;->createPresentationContext(Landroid/content/Context;Landroid/view/Display;I)Landroid/content/Context;
 Landroid/app/ProgressDialog;->mProgressNumber:Landroid/widget/TextView;
 Landroid/app/QueuedWork;->addFinisher(Ljava/lang/Runnable;)V
@@ -488,6 +490,7 @@
 Landroid/bluetooth/BluetoothA2dp;->ACTION_CODEC_CONFIG_CHANGED:Ljava/lang/String;
 Landroid/bluetooth/BluetoothA2dp;->connect(Landroid/bluetooth/BluetoothDevice;)Z
 Landroid/bluetooth/BluetoothA2dp;->disableOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)V
+Landroid/bluetooth/BluetoothA2dp;->disconnect(Landroid/bluetooth/BluetoothDevice;)Z
 Landroid/bluetooth/BluetoothA2dp;->enableOptionalCodecs(Landroid/bluetooth/BluetoothDevice;)V
 Landroid/bluetooth/BluetoothA2dp;->getActiveDevice()Landroid/bluetooth/BluetoothDevice;
 Landroid/bluetooth/BluetoothA2dp;->getCodecStatus(Landroid/bluetooth/BluetoothDevice;)Landroid/bluetooth/BluetoothCodecStatus;
@@ -695,6 +698,7 @@
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
 Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
+Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
 Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDeleteObserver2;->onPackageDeleted(Ljava/lang/String;ILjava/lang/String;)V
@@ -738,6 +742,7 @@
 Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageStatsObserver$Stub;-><init>()V
+Landroid/content/pm/IPackageStatsObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageStatsObserver;
 Landroid/content/pm/IShortcutService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IShortcutService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IShortcutService;
 Landroid/content/pm/LauncherActivityInfo;->mActivityInfo:Landroid/content/pm/ActivityInfo;
@@ -796,6 +801,7 @@
 Landroid/content/pm/PackageParser$Package;->configPreferences:Ljava/util/ArrayList;
 Landroid/content/pm/PackageParser$Package;->instrumentation:Ljava/util/ArrayList;
 Landroid/content/pm/PackageParser$Package;->mAppMetaData:Landroid/os/Bundle;
+Landroid/content/pm/PackageParser$Package;->mKeySetMapping:Landroid/util/ArrayMap;
 Landroid/content/pm/PackageParser$Package;->mPreferredOrder:I
 Landroid/content/pm/PackageParser$Package;->mSharedUserId:Ljava/lang/String;
 Landroid/content/pm/PackageParser$Package;->mSharedUserLabel:I
@@ -891,6 +897,7 @@
 Landroid/content/res/Resources;->setCompatibilityInfo(Landroid/content/res/CompatibilityInfo;)V
 Landroid/content/res/Resources;->updateSystemConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
 Landroid/content/res/ResourcesImpl;->getAssets()Landroid/content/res/AssetManager;
+Landroid/content/res/ResourcesImpl;->getValue(ILandroid/util/TypedValue;Z)V
 Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object;
 Landroid/content/res/ResourcesImpl;->mAnimatorCache:Landroid/content/res/ConfigurationBoundResourceCache;
 Landroid/content/res/ResourcesImpl;->mAssets:Landroid/content/res/AssetManager;
@@ -1081,7 +1088,9 @@
 Landroid/graphics/GraphicBuffer;->mNativeObject:J
 Landroid/graphics/ImageDecoder;->postProcessAndRelease(Landroid/graphics/Canvas;)I
 Landroid/graphics/Insets;->left:I
+Landroid/graphics/Insets;->top:I
 Landroid/graphics/Insets;->right:I
+Landroid/graphics/Insets;->bottom:I
 Landroid/graphics/LinearGradient;->mColors:[I
 Landroid/graphics/Matrix;->native_instance:J
 Landroid/graphics/Movie;-><init>(J)V
@@ -1264,6 +1273,7 @@
 Landroid/icu/text/SpoofChecker$ScriptSet;->setAll()V
 Landroid/icu/text/TimeZoneNames$DefaultTimeZoneNames$FactoryImpl;-><init>()V
 Landroid/icu/text/Transliterator;->createFromRules(Ljava/lang/String;Ljava/lang/String;I)Landroid/icu/text/Transliterator;
+Landroid/icu/text/Transliterator;->getInstance(Ljava/lang/String;)Landroid/icu/text/Transliterator;
 Landroid/icu/text/Transliterator;->transliterate(Ljava/lang/String;)Ljava/lang/String;
 Landroid/icu/text/UFormat;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
 Landroid/icu/util/Calendar;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
@@ -2096,6 +2106,7 @@
 Landroid/R$styleable;->CheckedTextView_checkMark:I
 Landroid/R$styleable;->CompoundButton:[I
 Landroid/R$styleable;->CompoundButton_button:I
+Landroid/R$styleable;->DrawableStates:[I
 Landroid/R$styleable;->ImageView:[I
 Landroid/R$styleable;->ImageView_adjustViewBounds:I
 Landroid/R$styleable;->ImageView_baselineAlignBottom:I
@@ -2358,6 +2369,7 @@
 Landroid/telephony/CellSignalStrengthLte;->mRsrq:I
 Landroid/telephony/CellSignalStrengthLte;->mRssnr:I
 Landroid/telephony/CellSignalStrengthLte;->mSignalStrength:I
+Landroid/telephony/CellSignalStrengthLte;->mTimingAdvance:I
 Landroid/telephony/CellSignalStrengthWcdma;->mBitErrorRate:I
 Landroid/telephony/CellSignalStrengthWcdma;->mSignalStrength:I
 Landroid/telephony/PhoneNumberUtils;->isLocalEmergencyNumber(Landroid/content/Context;ILjava/lang/String;)Z
@@ -2367,6 +2379,7 @@
 Landroid/telephony/SignalStrength;->getAsuLevel()I
 Landroid/telephony/SignalStrength;->getCdmaLevel()I
 Landroid/telephony/SignalStrength;->getDbm()I
+Landroid/telephony/SignalStrength;->getGsmDbm()I
 Landroid/telephony/SignalStrength;->getLteDbm()I
 Landroid/telephony/SignalStrength;->getLteRsrp()I
 Landroid/telephony/SignalStrength;->getLteRsrq()I
@@ -2431,6 +2444,7 @@
 Landroid/telephony/TelephonyManager;->hasIccCard(I)Z
 Landroid/telephony/TelephonyManager;->isMultiSimEnabled()Z
 Landroid/telephony/TelephonyManager;->isNetworkRoaming(I)Z
+Landroid/telephony/TelephonyManager;->isVideoTelephonyAvailable()Z
 Landroid/telephony/TelephonyManager;->isVolteAvailable()Z
 Landroid/telephony/TelephonyManager;->isWifiCallingAvailable()Z
 Landroid/telephony/TelephonyManager;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
@@ -2609,6 +2623,7 @@
 Landroid/view/inputmethod/InputMethodManager;->finishInputLocked()V
 Landroid/view/inputmethod/InputMethodManager;->focusIn(Landroid/view/View;)V
 Landroid/view/inputmethod/InputMethodManager;->focusOut(Landroid/view/View;)V
+Landroid/view/inputmethod/InputMethodManager;->getClient()Lcom/android/internal/view/IInputMethodClient;
 Landroid/view/inputmethod/InputMethodManager;->getInputMethodWindowVisibleHeight()I
 Landroid/view/inputmethod/InputMethodManager;->getInstance()Landroid/view/inputmethod/InputMethodManager;
 Landroid/view/inputmethod/InputMethodManager;->mCurId:Ljava/lang/String;
@@ -2785,6 +2800,7 @@
 Landroid/view/View;->includeForAccessibility()Z
 Landroid/view/View;->initializeScrollbars(Landroid/content/res/TypedArray;)V
 Landroid/view/View;->internalSetPadding(IIII)V
+Landroid/view/View;->invalidateParentIfNeeded()V
 Landroid/view/View;->isPaddingResolved()Z
 Landroid/view/View;->isRootNamespace()Z
 Landroid/view/View;->isVisibleToUser()Z
@@ -3069,6 +3085,7 @@
 Landroid/widget/ImageView;->mDrawMatrix:Landroid/graphics/Matrix;
 Landroid/widget/ImageView;->mMaxHeight:I
 Landroid/widget/ImageView;->mMaxWidth:I
+Landroid/widget/ImageView;->mRecycleableBitmapDrawable:Landroid/graphics/drawable/BitmapDrawable;
 Landroid/widget/ImageView;->mResource:I
 Landroid/widget/ImageView;->mUri:Landroid/net/Uri;
 Landroid/widget/ImageView;->updateDrawable(Landroid/graphics/drawable/Drawable;)V
@@ -3573,11 +3590,13 @@
 Lcom/android/internal/telephony/ITelephony;->disableDataConnectivity()Z
 Lcom/android/internal/telephony/ITelephony;->enableDataConnectivity()Z
 Lcom/android/internal/telephony/ITelephony;->endCall()Z
+Lcom/android/internal/telephony/ITelephony;->endCallForSubscriber(I)Z
 Lcom/android/internal/telephony/ITelephony;->getCallState()I
 Lcom/android/internal/telephony/ITelephony;->getDataState()I
 Lcom/android/internal/telephony/ITelephony;->isIdle(Ljava/lang/String;)Z
 Lcom/android/internal/telephony/ITelephony;->setRadio(Z)Z
 Lcom/android/internal/telephony/ITelephony;->silenceRinger()V
+Lcom/android/internal/telephony/ITelephonyRegistry$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ITelephonyRegistry$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephonyRegistry;
 Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallState(ILjava/lang/String;)V
 Lcom/android/internal/telephony/SmsHeader$ConcatRef;->msgCount:I
@@ -3714,6 +3733,7 @@
 Ldalvik/system/VMDebug;->isDebuggerConnected()Z
 Ldalvik/system/VMRuntime;->addressOf(Ljava/lang/Object;)J
 Ldalvik/system/VMRuntime;->clearGrowthLimit()V
+Ldalvik/system/VMRuntime;->gcSoftReferences()V
 Ldalvik/system/VMRuntime;->getCurrentInstructionSet()Ljava/lang/String;
 Ldalvik/system/VMRuntime;->getExternalBytesAllocated()J
 Ldalvik/system/VMRuntime;->getInstructionSet(Ljava/lang/String;)Ljava/lang/String;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index ab0001c..dcf4eec 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -109,6 +109,48 @@
      */
     public static final int MODE_DEFAULT = 3;
 
+    /**
+     * Metrics about an op when its uid is persistent.
+     * @hide
+     */
+    public static final int UID_STATE_PERSISTENT = 0;
+
+    /**
+     * Metrics about an op when its uid is at the top.
+     * @hide
+     */
+    public static final int UID_STATE_TOP = 1;
+
+    /**
+     * Metrics about an op when its uid is running a foreground service.
+     * @hide
+     */
+    public static final int UID_STATE_FOREGROUND_SERVICE = 2;
+
+    /**
+     * Metrics about an op when its uid is in the foreground for any other reasons.
+     * @hide
+     */
+    public static final int UID_STATE_FOREGROUND = 3;
+
+    /**
+     * Metrics about an op when its uid is in the background for any reason.
+     * @hide
+     */
+    public static final int UID_STATE_BACKGROUND = 4;
+
+    /**
+     * Metrics about an op when its uid is cached.
+     * @hide
+     */
+    public static final int UID_STATE_CACHED = 5;
+
+    /**
+     * Number of uid states we track.
+     * @hide
+     */
+    public static final int _NUM_UID_STATE = 6;
+
     // when adding one of these:
     //  - increment _NUM_OP
     //  - define an OPSTR_* constant (marked as @SystemApi)
@@ -1471,8 +1513,8 @@
     public static class OpEntry implements Parcelable {
         private final int mOp;
         private final int mMode;
-        private final long mTime;
-        private final long mRejectTime;
+        private final long[] mTimes;
+        private final long[] mRejectTimes;
         private final int mDuration;
         private final int mProxyUid;
         private final String mProxyPackageName;
@@ -1481,8 +1523,23 @@
                 int proxyUid, String proxyPackage) {
             mOp = op;
             mMode = mode;
-            mTime = time;
-            mRejectTime = rejectTime;
+            mTimes = new long[_NUM_UID_STATE];
+            mRejectTimes = new long[_NUM_UID_STATE];
+            mTimes[0] = time;
+            mRejectTimes[0] = rejectTime;
+            mDuration = duration;
+            mProxyUid = proxyUid;
+            mProxyPackageName = proxyPackage;
+        }
+
+        public OpEntry(int op, int mode, long[] times, long[] rejectTimes, int duration,
+                int proxyUid, String proxyPackage) {
+            mOp = op;
+            mMode = mode;
+            mTimes = new long[_NUM_UID_STATE];
+            mRejectTimes = new long[_NUM_UID_STATE];
+            System.arraycopy(times, 0, mTimes, 0, _NUM_UID_STATE);
+            System.arraycopy(rejectTimes, 0, mRejectTimes, 0, _NUM_UID_STATE);
             mDuration = duration;
             mProxyUid = proxyUid;
             mProxyPackageName = proxyPackage;
@@ -1497,11 +1554,31 @@
         }
 
         public long getTime() {
-            return mTime;
+            long time = 0;
+            for (int i = 0; i < _NUM_UID_STATE; i++) {
+                if (mTimes[i] > time) {
+                    time = mTimes[i];
+                }
+            }
+            return time;
+        }
+
+        public long getTimeFor(int uidState) {
+            return mTimes[uidState];
         }
 
         public long getRejectTime() {
-            return mRejectTime;
+            long time = 0;
+            for (int i = 0; i < _NUM_UID_STATE; i++) {
+                if (mRejectTimes[i] > time) {
+                    time = mRejectTimes[i];
+                }
+            }
+            return time;
+        }
+
+        public long getRejectTimeFor(int uidState) {
+            return mRejectTimes[uidState];
         }
 
         public boolean isRunning() {
@@ -1509,7 +1586,7 @@
         }
 
         public int getDuration() {
-            return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
+            return mDuration;
         }
 
         public int getProxyUid() {
@@ -1529,8 +1606,8 @@
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(mOp);
             dest.writeInt(mMode);
-            dest.writeLong(mTime);
-            dest.writeLong(mRejectTime);
+            dest.writeLongArray(mTimes);
+            dest.writeLongArray(mRejectTimes);
             dest.writeInt(mDuration);
             dest.writeInt(mProxyUid);
             dest.writeString(mProxyPackageName);
@@ -1539,8 +1616,8 @@
         OpEntry(Parcel source) {
             mOp = source.readInt();
             mMode = source.readInt();
-            mTime = source.readLong();
-            mRejectTime = source.readLong();
+            mTimes = source.createLongArray();
+            mRejectTimes = source.createLongArray();
             mDuration = source.readInt();
             mProxyUid = source.readInt();
             mProxyPackageName = source.readString();
diff --git a/core/java/android/app/usage/EventList.java b/core/java/android/app/usage/EventList.java
new file mode 100644
index 0000000..aaae57e5
--- /dev/null
+++ b/core/java/android/app/usage/EventList.java
@@ -0,0 +1,106 @@
+/*
+ * 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.app.usage;
+
+import java.util.ArrayList;
+
+/**
+ * A container to keep {@link UsageEvents.Event usage events} in non-descending order of their
+ * {@link UsageEvents.Event#mTimeStamp timestamps}.
+ *
+ * @hide
+ */
+public class EventList {
+
+    private final ArrayList<UsageEvents.Event> mEvents;
+
+    /**
+     * Create a new event list with default capacity
+     */
+    public EventList() {
+        mEvents = new ArrayList<>();
+    }
+
+    /**
+     * Returns the size of the list
+     * @return the number of events in the list
+     */
+    public int size() {
+        return mEvents.size();
+    }
+
+    /**
+     * Removes all events from the list
+     */
+    public void clear() {
+        mEvents.clear();
+    }
+
+    /**
+     * Returns the {@link UsageEvents.Event event} at the specified position in this list.
+     * @param index the index of the event to return, such that {@code 0 <= index < size()}
+     * @return The {@link UsageEvents.Event event} at position {@code index}
+     */
+    public UsageEvents.Event get(int index) {
+        return mEvents.get(index);
+    }
+
+    /**
+     * Inserts the given {@link UsageEvents.Event event} into the list while keeping the list sorted
+     * based on the event {@link UsageEvents.Event#mTimeStamp timestamps}.
+     *
+     * @param event The event to insert
+     */
+    public void insert(UsageEvents.Event event) {
+        final int size = mEvents.size();
+        // fast case: just append if this is the latest event
+        if (size == 0 || event.mTimeStamp >= mEvents.get(size - 1).mTimeStamp) {
+            mEvents.add(event);
+            return;
+        }
+        // To minimize number of elements being shifted, insert at the first occurrence of the next
+        // greatest timestamp in the list.
+        final int insertIndex = firstIndexOnOrAfter(event.mTimeStamp + 1);
+        mEvents.add(insertIndex, event);
+    }
+
+    /**
+     * Finds the index of the first event whose timestamp is greater than or equal to the given
+     * timestamp.
+     *
+     * @param timeStamp The timestamp for which to search the list.
+     * @return The smallest {@code index} for which {@code (get(index).mTimeStamp >= timeStamp)} is
+     * {@code true}, or {@link #size() size} if no such {@code index} exists.
+     */
+    public int firstIndexOnOrAfter(long timeStamp) {
+        final int size = mEvents.size();
+        int result = size;
+        int lo = 0;
+        int hi = size - 1;
+        while (lo <= hi) {
+            final int mid = (lo + hi) >>> 1;
+            final long midTimeStamp = mEvents.get(mid).mTimeStamp;
+            if (midTimeStamp >= timeStamp) {
+                hi = mid - 1;
+                result = mid;
+            } else {
+                lo = mid + 1;
+            }
+        }
+        return result;
+    }
+}
diff --git a/core/java/android/app/usage/TimeSparseArray.java b/core/java/android/app/usage/TimeSparseArray.java
index 4ec0e9e..2bd6b24 100644
--- a/core/java/android/app/usage/TimeSparseArray.java
+++ b/core/java/android/app/usage/TimeSparseArray.java
@@ -27,14 +27,12 @@
 public class TimeSparseArray<E> extends LongSparseArray<E> {
     private static final String TAG = TimeSparseArray.class.getSimpleName();
 
+    private boolean mWtfReported;
+
     public TimeSparseArray() {
         super();
     }
 
-    public TimeSparseArray(int initialCapacity) {
-        super(initialCapacity);
-    }
-
     /**
      * Finds the index of the first element whose timestamp is greater or equal to
      * the given time.
@@ -75,22 +73,16 @@
     /**
      * {@inheritDoc}
      *
-     * Overridden to ensure no collisions. The key (time in milliseconds) is incremented till an
-     * empty place is found.
+     * <p> As this container is being used only to keep {@link android.util.AtomicFile files},
+     * there should not be any collisions. Reporting a {@link Slog#wtf(String, String)} in case that
+     * happens, as that will lead to one whole file being dropped.
      */
     @Override
     public void put(long key, E value) {
-        final long origKey = key;
-        int keyIndex = indexOfKey(key);
-        if (keyIndex >= 0) {
-            final long sz = size();
-            while (keyIndex < sz && keyAt(keyIndex) == key) {
-                key++;
-                keyIndex++;
-            }
-            if (key >= origKey + 100) {
-                Slog.w(TAG, "Value " + value + " supposed to be inserted at " + origKey
-                        + " displaced to " + key);
+        if (indexOfKey(key) >= 0) {
+            if (!mWtfReported) {
+                Slog.wtf(TAG, "Overwriting value " + get(key) + " by " + value);
+                mWtfReported = true;
             }
         }
         super.put(key, value);
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index e9b4853..4d238c0 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -349,6 +349,26 @@
             return new OneShot(mDuration, newAmplitude);
         }
 
+        /**
+         * Resolve default values into integer amplitude numbers.
+         *
+         * @param defaultAmplitude the default amplitude to apply, must be between 0 and
+         *         MAX_AMPLITUDE
+         * @return A {@link OneShot} effect with same physical meaning but explicitly set amplitude
+         *
+         * @hide
+         */
+        public OneShot resolve(int defaultAmplitude) {
+            if (defaultAmplitude > MAX_AMPLITUDE || defaultAmplitude < 0) {
+                throw new IllegalArgumentException(
+                        "Amplitude is negative or greater than MAX_AMPLITUDE");
+            }
+            if (mAmplitude == DEFAULT_AMPLITUDE) {
+                return new OneShot(mDuration, defaultAmplitude);
+            }
+            return this;
+        }
+
         @Override
         public void validate() {
             if (mAmplitude < -1 || mAmplitude == 0 || mAmplitude > 255) {
@@ -470,6 +490,30 @@
             return new Waveform(mTimings, scaledAmplitudes, mRepeat);
         }
 
+        /**
+         * Resolve default values into integer amplitude numbers.
+         *
+         * @param defaultAmplitude the default amplitude to apply, must be between 0 and
+         *         MAX_AMPLITUDE
+         * @return A {@link Waveform} effect with same physical meaning but explicitly set
+         *         amplitude
+         *
+         * @hide
+         */
+        public Waveform resolve(int defaultAmplitude) {
+            if (defaultAmplitude > MAX_AMPLITUDE || defaultAmplitude < 0) {
+                throw new IllegalArgumentException(
+                        "Amplitude is negative or greater than MAX_AMPLITUDE");
+            }
+            int[] resolvedAmplitudes = Arrays.copyOf(mAmplitudes, mAmplitudes.length);
+            for (int i = 0; i < resolvedAmplitudes.length; i++) {
+                if (resolvedAmplitudes[i] == DEFAULT_AMPLITUDE) {
+                    resolvedAmplitudes[i] = defaultAmplitude;
+                }
+            }
+            return new Waveform(mTimings, resolvedAmplitudes, mRepeat);
+        }
+
         @Override
         public void validate() {
             if (mTimings.length != mAmplitudes.length) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6b6e14f..318265b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10796,15 +10796,28 @@
         public static final String SYNC_MANAGER_CONSTANTS = "sync_manager_constants";
 
         /**
-         * Whether or not App Standby feature is enabled. This controls throttling of apps
-         * based on usage patterns and predictions.
+         * Whether or not App Standby feature is enabled by system. This controls throttling of apps
+         * based on usage patterns and predictions. Platform will turn on this feature if both this
+         * flag and {@link #ADAPTIVE_BATTERY_MANAGEMENT_ENABLED} is on.
          * Type: int (0 for false, 1 for true)
          * Default: 1
          * @hide
+         * @see #ADAPTIVE_BATTERY_MANAGEMENT_ENABLED
          */
         public static final String APP_STANDBY_ENABLED = "app_standby_enabled";
 
         /**
+         * Whether or not adaptive battery feature is enabled by user. Platform will turn on this
+         * feature if both this flag and {@link #APP_STANDBY_ENABLED} is on.
+         * Type: int (0 for false, 1 for true)
+         * Default: 1
+         * @hide
+         * @see #APP_STANDBY_ENABLED
+         */
+        public static final String ADAPTIVE_BATTERY_MANAGEMENT_ENABLED =
+                "adaptive_battery_management_enabled";
+
+        /**
          * Whether or not app auto restriction is enabled. When it is enabled, settings app will
          * auto restrict the app if it has bad behavior(e.g. hold wakelock for long time).
          *
diff --git a/core/java/android/service/autofill/BatchUpdates.java b/core/java/android/service/autofill/BatchUpdates.java
index 90acc88..2ba0376 100644
--- a/core/java/android/service/autofill/BatchUpdates.java
+++ b/core/java/android/service/autofill/BatchUpdates.java
@@ -82,6 +82,9 @@
          * {@link #transformChild(int, Transformation) transformations} are applied to the children
          * views.
          *
+         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+         * or background color: Autofill on different platforms may have different themes.
+         *
          * @param updates a {@link RemoteViews} with the updated actions to be applied in the
          * underlying presentation template.
          *
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index ccec483..5211767 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -336,6 +336,9 @@
          * higher, datasets that require authentication can be also be filtered by passing a
          * {@link AutofillValue#forText(CharSequence) text value} as the  {@code value} parameter.
          *
+         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+         * or background color: Autofill on different platforms may have different themes.
+         *
          * @param id id returned by {@link
          *         android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
          * @param value the value to be autofilled. Pass {@code null} if you do not have the value
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 2bc4b8f..7bf1f83 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -241,6 +241,9 @@
          * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
          * platform needs to fill in the authentication arguments.
          *
+         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+         * or background color: Autofill on different platforms may have different themes.
+         *
          * @param authentication Intent to an activity with your authentication flow.
          * @param presentation The presentation to visualize the response.
          * @param ids id of Views that when focused will display the authentication UI.
@@ -449,6 +452,9 @@
          * authentication (as the header could have been set directly in the main presentation in
          * these cases).
          *
+         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+         * or background color: Autofill on different platforms may have different themes.
+         *
          * @param header a presentation to represent the header. This presentation is not clickable
          * &mdash;calling
          * {@link RemoteViews#setOnClickPendingIntent(int, android.app.PendingIntent)} on it would
@@ -477,6 +483,9 @@
          * authentication (as the footer could have been set directly in the main presentation in
          * these cases).
          *
+         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
+         * or background color: Autofill on different platforms may have different themes.
+         *
          * @param footer a presentation to represent the footer. This presentation is not clickable
          * &mdash;calling
          * {@link RemoteViews#setOnClickPendingIntent(int, android.app.PendingIntent)} on it would
diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java
index a6495d1..8266207 100644
--- a/core/java/android/view/autofill/AutofillPopupWindow.java
+++ b/core/java/android/view/autofill/AutofillPopupWindow.java
@@ -19,6 +19,7 @@
 import static android.view.autofill.Helper.sVerbose;
 
 import android.annotation.NonNull;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.IBinder;
@@ -79,11 +80,6 @@
     public AutofillPopupWindow(@NonNull IAutofillWindowPresenter presenter) {
         mWindowPresenter = new WindowPresenter(presenter);
 
-        // We want to show the window as system controlled one so it covers app windows, but it has
-        // to be an application type (so it's contained inside the application area).
-        // Hence, we set it to the application type with the highest z-order, which currently
-        // is TYPE_APPLICATION_ABOVE_SUB_PANEL.
-        setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
         setTouchModal(false);
         setOutsideTouchable(true);
         setInputMethodMode(INPUT_METHOD_NOT_NEEDED);
@@ -110,7 +106,16 @@
      */
     public void update(View anchor, int offsetX, int offsetY, int width, int height,
             Rect virtualBounds) {
-        mFullScreen = width == LayoutParams.MATCH_PARENT && height == LayoutParams.MATCH_PARENT;
+        mFullScreen = width == LayoutParams.MATCH_PARENT;
+        // For no fullscreen autofill window, we want to show the window as system controlled one
+        // so it covers app windows, but it has to be an application type (so it's contained inside
+        // the application area). Hence, we set it to the application type with the highest z-order,
+        // which currently is TYPE_APPLICATION_ABOVE_SUB_PANEL.
+        // For fullscreen mode, autofill window is at the bottom of screen, it should not be
+        // clipped by app activity window. Fullscreen autofill window does not need to follow app
+        // anchor view position.
+        setWindowLayoutType(mFullScreen ? WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
+                : WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
         // If we are showing the popup for a virtual view we use a fake view which
         // delegates to the anchor but present itself with the same bounds as the
         // virtual view. This ensures that the location logic in popup works
@@ -119,6 +124,15 @@
         if (mFullScreen) {
             offsetX = 0;
             offsetY = 0;
+            // If it is not fullscreen height, put window at bottom. Computes absolute position.
+            // Note that we cannot easily change default gravity from Gravity.TOP to
+            // Gravity.BOTTOM because PopupWindow base class does not expose computeGravity().
+            final Point outPoint = new Point();
+            anchor.getContext().getDisplay().getSize(outPoint);
+            width = outPoint.x;
+            if (height != LayoutParams.MATCH_PARENT) {
+                offsetY = outPoint.y - height;
+            }
             actualAnchor = anchor;
         } else if (virtualBounds != null) {
             final int[] mLocationOnScreen = new int[] {virtualBounds.left, virtualBounds.top};
@@ -202,6 +216,16 @@
             actualAnchor = anchor;
         }
 
+        if (!mFullScreen) {
+            // No fullscreen window animation is controlled by PopupWindow.
+            setAnimationStyle(-1);
+        } else if (height == LayoutParams.MATCH_PARENT) {
+            // Complete fullscreen autofill window has no animation.
+            setAnimationStyle(0);
+        } else {
+            // Slide half screen height autofill window from bottom.
+            setAnimationStyle(com.android.internal.R.style.AutofillHalfScreenAnimation);
+        }
         if (!isShowing()) {
             setWidth(width);
             setHeight(height);
@@ -223,7 +247,12 @@
     protected boolean findDropDownPosition(View anchor, LayoutParams outParams,
             int xOffset, int yOffset, int width, int height, int gravity, boolean allowScroll) {
         if (mFullScreen) {
-            // Do not patch LayoutParams if force full screen
+            // In fullscreen mode, don't need consider the anchor view.
+            outParams.x = xOffset;
+            outParams.y = yOffset;
+            outParams.width = width;
+            outParams.height = height;
+            outParams.gravity = gravity;
             return false;
         }
         return super.findDropDownPosition(anchor, outParams, xOffset, yOffset,
@@ -316,11 +345,6 @@
     }
 
     @Override
-    public void setAnimationStyle(int animationStyle) {
-        throw new IllegalStateException("You can't call this!");
-    }
-
-    @Override
     public void setBackgroundDrawable(Drawable background) {
         throw new IllegalStateException("You can't call this!");
     }
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index cb362e6..f1a1457 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -170,7 +170,7 @@
             if (mWindow == null) {
                 synchronized (mLock) {
                     mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
-                            getValidViewSurface(),
+                            getValidParentSurfaceForMagnifier(),
                             mWindowWidth, mWindowHeight, mWindowElevation, mWindowCornerRadius,
                             Handler.getMain() /* draw the magnifier on the UI thread */, mLock,
                             mCallback);
@@ -245,18 +245,20 @@
     }
 
     @Nullable
-    private Surface getValidViewSurface() {
-        // TODO: deduplicate this against the first part of #performPixelCopy
-        final Surface surface;
-        if (mView instanceof SurfaceView) {
-            surface = ((SurfaceView) mView).getHolder().getSurface();
-        } else if (mView.getViewRootImpl() != null) {
-            surface = mView.getViewRootImpl().mSurface;
-        } else {
-            surface = null;
+    private Surface getValidParentSurfaceForMagnifier() {
+        if (mView.getViewRootImpl() != null) {
+            final Surface mainWindowSurface = mView.getViewRootImpl().mSurface;
+            if (mainWindowSurface != null && mainWindowSurface.isValid()) {
+                return mainWindowSurface;
+            }
         }
-
-        return (surface != null && surface.isValid()) ? surface : null;
+        if (mView instanceof SurfaceView) {
+            final Surface surfaceViewSurface = ((SurfaceView) mView).getHolder().getSurface();
+            if (surfaceViewSurface != null && surfaceViewSurface.isValid()) {
+                return surfaceViewSurface;
+            }
+        }
+        return null;
     }
 
     private void configureCoordinates(final float xPosInView, final float yPosInView) {
@@ -264,12 +266,12 @@
         // magnifier. These are relative to the surface the content is copied from.
         final float posX;
         final float posY;
+        mView.getLocationInSurface(mViewCoordinatesInSurface);
         if (mView instanceof SurfaceView) {
             // No offset required if the backing Surface matches the size of the SurfaceView.
             posX = xPosInView;
             posY = yPosInView;
         } else {
-            mView.getLocationInSurface(mViewCoordinatesInSurface);
             posX = xPosInView + mViewCoordinatesInSurface[0];
             posY = yPosInView + mViewCoordinatesInSurface[1];
         }
@@ -282,6 +284,14 @@
                 R.dimen.magnifier_offset);
         mWindowCoords.x = mCenterZoomCoords.x - mWindowWidth / 2;
         mWindowCoords.y = mCenterZoomCoords.y - mWindowHeight / 2 - verticalOffset;
+        if (mView instanceof SurfaceView && mView.getViewRootImpl() != null) {
+            // TODO: deduplicate against the first part of #getValidParentSurfaceForMagnifier()
+            final Surface mainWindowSurface = mView.getViewRootImpl().mSurface;
+            if (mainWindowSurface != null && mainWindowSurface.isValid()) {
+                mWindowCoords.x += mViewCoordinatesInSurface[0];
+                mWindowCoords.y += mViewCoordinatesInSurface[1];
+            }
+        }
     }
 
     private void performPixelCopy(final int startXInSurface, final int startYInSurface,
@@ -361,6 +371,9 @@
         // The alpha set on the magnifier's content, which defines how
         // prominent the white background is.
         private static final int CONTENT_BITMAP_ALPHA = 242;
+        // The z of the magnifier surface, defining its z order in the list of
+        // siblings having the same parent surface (usually the main app surface).
+        private static final int SURFACE_Z = 5;
 
         // Display associated to the view the magnifier is attached to.
         private final Display mDisplay;
@@ -602,6 +615,7 @@
                                     mSurfaceControl.setPosition(pendingX, pendingY);
                                 }
                                 if (firstDraw) {
+                                    mSurfaceControl.setLayer(SURFACE_Z);
                                     mSurfaceControl.show();
                                 }
                                 SurfaceControl.closeTransaction();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5ecbf90a..4865dab 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -21,6 +21,7 @@
 import android.annotation.ColorInt;
 import android.annotation.DimenRes;
 import android.annotation.NonNull;
+import android.annotation.StyleRes;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.Application;
@@ -56,6 +57,7 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.LayoutInflater.Filter;
 import android.view.RemotableViewMethod;
@@ -182,6 +184,12 @@
     private boolean mIsRoot = true;
 
     /**
+     * Optional theme resource id applied in inflateView(). When 0, Theme.DeviceDefault will be
+     * used.
+     */
+    private int mApplyThemeResId;
+
+    /**
      * Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify
      * the layout in a way that isn't recoverable, since views are being removed.
      */
@@ -3267,6 +3275,14 @@
     }
 
     /**
+     * Set the theme used in apply() and applyASync().
+     * @hide
+     */
+    public void setApplyTheme(@StyleRes int themeResId) {
+        mApplyThemeResId = themeResId;
+    }
+
+    /**
      * Inflates the view hierarchy represented by this object and applies
      * all of the actions.
      *
@@ -3301,6 +3317,10 @@
         final Context contextForResources = getContextForResources(context);
         Context inflationContext = new RemoteViewsContextWrapper(context, contextForResources);
 
+        // If mApplyThemeResId is not given, Theme.DeviceDefault will be used.
+        if (mApplyThemeResId != 0) {
+            inflationContext = new ContextThemeWrapper(inflationContext, mApplyThemeResId);
+        }
         LayoutInflater inflater = (LayoutInflater)
                 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index da494d4..8235507 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1424,6 +1424,13 @@
     <permission android:name="android.permission.NETWORK_SETTINGS"
         android:protectionLevel="signature" />
 
+    <!-- Allows SetupWizard to call methods in Networking services
+         <p>Not for use by any other third-party or privileged applications.
+         @hide This should only be used by SetupWizard.
+    -->
+    <permission android:name="android.permission.NETWORK_SETUP_WIZARD"
+        android:protectionLevel="signature|setup" />
+
     <!-- #SystemApi @hide Allows applications to access information about LoWPAN interfaces.
          <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.ACCESS_LOWPAN_STATE"
diff --git a/core/res/res/layout-television/autofill_save.xml b/core/res/res/layout-television/autofill_save.xml
new file mode 100644
index 0000000..ebd2dec
--- /dev/null
+++ b/core/res/res/layout-television/autofill_save.xml
@@ -0,0 +1,100 @@
+<?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.
+-->
+
+<!-- NOTE: outer layout is required to provide proper shadow. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:id="@+id/autofill_save"
+        android:background="?android:attr/colorBackground"
+        android:layout_marginTop="32dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="40dp"
+        android:paddingEnd="40dp"
+        android:paddingTop="40dp"
+        android:paddingBottom="40dp">
+
+        <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_marginEnd="32dp">
+
+            <LinearLayout
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="6dp">
+
+                <ImageView
+                    android:id="@+id/autofill_save_icon"
+                    android:scaleType="fitStart"
+                    android:layout_marginEnd="10dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_width="48dp"
+                    android:layout_height="48dp"/>
+                <TextView
+                    android:id="@+id/autofill_save_title"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/autofill_save_title"
+                    android:layout_gravity="center_vertical"
+                    android:textSize="24sp" />
+            </LinearLayout>
+
+            <com.android.server.autofill.ui.CustomScrollView
+                android:id="@+id/autofill_save_custom_subtitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="4dp"
+                android:visibility="gone"/>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="304dp"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <Button
+                android:id="@+id/autofill_save_no"
+                style="?attr/borderlessButtonStyle"
+                android:textAlignment="viewStart"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/autofill_save_no">
+            </Button>
+
+            <Button
+                android:id="@+id/autofill_save_yes"
+                style="?attr/borderlessButtonStyle"
+                android:textAlignment="viewStart"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/autofill_save_yes">
+            </Button>
+        </LinearLayout>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index ef19f87..a88836e 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -14,8 +14,7 @@
      limitations under the License.
 -->
 
-<view  xmlns:android="http://schemas.android.com/apk/res/android"
-    class="com.android.server.autofill.ui.FillUi$AutofillFrameLayout"
+<FrameLayout  xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/autofill_dataset_picker"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
@@ -31,4 +30,4 @@
         android:visibility="gone">
     </ListView>
 
-</view>
+</FrameLayout>
diff --git a/core/res/res/layout/autofill_dataset_picker_fullscreen.xml b/core/res/res/layout/autofill_dataset_picker_fullscreen.xml
index 07298c1..1d2b5e5 100644
--- a/core/res/res/layout/autofill_dataset_picker_fullscreen.xml
+++ b/core/res/res/layout/autofill_dataset_picker_fullscreen.xml
@@ -14,35 +14,73 @@
      limitations under the License.
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/autofill_dataset_picker"
-    style="@style/AutofillDatasetPicker"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent">
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:background="?android:attr/windowBackground"
+    android:paddingStart="40dp"
+    android:paddingEnd="40dp"
+    android:paddingTop="40dp"
+    android:paddingBottom="40dp">
 
-    <TextView
-        android:layout_width="wrap_content"
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:text="@string/autofill_window_title"
-        android:layout_above="@+id/autofill_dataset_container"
-        android:layout_alignStart="@+id/autofill_dataset_container"
-        android:textSize="16sp"/>
+        android:layout_weight="1"
+        android:layout_marginEnd="32dp">
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="6dp"
+            >
+            <ImageView
+                android:id="@+id/autofill_dataset_icon"
+                android:scaleType="fitStart"
+                android:layout_marginEnd="10dp"
+                android:layout_gravity="center_vertical"
+                android:layout_width="48dp"
+                android:layout_height="48dp"/>
+            <TextView
+                android:id="@+id/autofill_dataset_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:textSize="24sp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/autofill_dataset_header"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"/>
+
+    </LinearLayout>
 
     <!-- autofill_container is the common parent for inserting authentication item or
-         autofill_dataset_list-->
-    <FrameLayout
-        android:id="@+id/autofill_dataset_container"
-        android:layout_width="wrap_content"
+         autofill_dataset_list, autofill_dataset_foolter-->
+    <LinearLayout
+        android:layout_width="304dp"
         android:layout_height="wrap_content"
-        android:layout_centerInParent="true">
+        android:id="@+id/autofill_dataset_picker"
+        android:orientation="vertical">
         <ListView
             android:id="@+id/autofill_dataset_list"
-            android:layout_width="wrap_content"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:clickable="true"
             android:divider="@null"
             android:drawSelectorOnTop="true"
             android:visibility="gone"/>
-    </FrameLayout>
+        <LinearLayout
+            android:id="@+id/autofill_dataset_footer"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"/>
+    </LinearLayout>
 
-</RelativeLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/autofill_dataset_picker_header_footer.xml b/core/res/res/layout/autofill_dataset_picker_header_footer.xml
index 048494a..093f035 100644
--- a/core/res/res/layout/autofill_dataset_picker_header_footer.xml
+++ b/core/res/res/layout/autofill_dataset_picker_header_footer.xml
@@ -14,8 +14,7 @@
      limitations under the License.
 -->
 
-<view  xmlns:android="http://schemas.android.com/apk/res/android"
-    class="com.android.server.autofill.ui.FillUi$AutofillFrameLayout"
+<FrameLayout  xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/autofill_dataset_picker"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
@@ -54,4 +53,4 @@
 
     </LinearLayout>
 
-</view>
+</FrameLayout>
diff --git a/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml b/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml
deleted file mode 100644
index 24b14a0..0000000
--- a/core/res/res/layout/autofill_dataset_picker_header_footer_fullscreen.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/autofill_dataset_picker"
-    style="@style/AutofillDatasetPicker"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent">
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/autofill_window_title"
-        android:layout_above="@+id/autofill_dataset_container"
-        android:layout_alignStart="@+id/autofill_dataset_container"
-        android:textSize="16sp"/>
-
-    <!-- autofill_container is the common parent for inserting authentication item or
-         autofill_dataset_list-->
-    <FrameLayout
-        android:id="@+id/autofill_dataset_container"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerInParent="true">
-
-        <LinearLayout
-            xmlns:android="http://schemas.android.com/apk/res/android"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-
-            <LinearLayout
-                android:id="@+id/autofill_dataset_header"
-                android:visibility="gone"
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"/>
-
-            <ListView
-                android:id="@+id/autofill_dataset_list"
-                android:layout_weight="1"
-                android:layout_width="fill_parent"
-                android:layout_height="0dp"
-                android:clickable="true"
-                android:divider="@null"
-                android:drawSelectorOnTop="true"
-                android:visibility="gone"/>
-
-            <LinearLayout
-                android:id="@+id/autofill_dataset_footer"
-                android:visibility="gone"
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"/>
-
-        </LinearLayout>
-
-    </FrameLayout>
-
-</RelativeLayout>
diff --git a/core/res/res/values-television/dimens.xml b/core/res/res/values-television/dimens.xml
index aa56251..4c25225 100644
--- a/core/res/res/values-television/dimens.xml
+++ b/core/res/res/values-television/dimens.xml
@@ -20,8 +20,4 @@
      <item type="dimen" format="float" name="ambient_shadow_alpha">0.15</item>
      <item type="dimen" format="float" name="spot_shadow_alpha">0.3</item>
 
-     <!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
-     <dimen name="autofill_dataset_picker_max_width">60%</dimen>
-     <dimen name="autofill_dataset_picker_max_height">70%</dimen>
-
 </resources>
diff --git a/core/res/res/values-television/themes_device_defaults.xml b/core/res/res/values-television/themes_device_defaults.xml
index e01caa3..e380a7b 100644
--- a/core/res/res/values-television/themes_device_defaults.xml
+++ b/core/res/res/values-television/themes_device_defaults.xml
@@ -16,4 +16,6 @@
 <resources>
     <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material.Autofill" />
+    <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.Material.Autofill.Save" />
 </resources>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 3609fb8..2966aff 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -145,4 +145,8 @@
     <color name="datepicker_default_view_animator_color_material_light">#fff2f2f2</color>
     <color name="datepicker_default_view_animator_color_material_dark">#ff303030</color>
 
+    <!-- Autofill colors -->
+    <color name="autofill_background_material_dark">@color/material_blue_grey_900</color>
+    <color name="autofill_background_material_light">@color/material_grey_50</color>
+
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 860dd87..45814ea 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -629,7 +629,7 @@
     <!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.-->
     <dimen name="notification_media_image_max_width_low_ram">100dp</dimen>
     <!-- The size of the right icon image when on low ram -->
-    <dimen name="notification_right_icon_size_low_ram">@dimen/notification_right_icon_size_low_ram</dimen>
+    <dimen name="notification_right_icon_size_low_ram">38dp</dimen>
 
     <dimen name="messaging_avatar_size">@dimen/notification_right_icon_size</dimen>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e5bb587..b92052b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2196,8 +2196,8 @@
     <!-- Text to show in the auto complete drop down list on a text view when the WebView can auto fill the entire form but the user has not configured an AutoFill profile [CHAR-LIMIT=19] -->
     <string name="setup_autofill">Set up Autofill</string>
 
-    <!-- Title of fullscreen autofill window [CHAR-LIMIT=80] -->
-    <string name="autofill_window_title">Autofill</string>
+    <!-- Title of fullscreen autofill window, including the name of which autofill service it is using [CHAR-LIMIT=NONE] -->
+    <string name="autofill_window_title">Autofill with <xliff:g id="serviceName" example="MyPass">%1$s</xliff:g></string>
 
     <!-- String used to separate FirstName and LastName when writing out a local name
          e.g. John<separator>Smith [CHAR-LIMIT=NONE]-->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 984461b..50a6ff3 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1487,13 +1487,19 @@
         <item name="successColor">@color/lock_pattern_view_success_color</item>
     </style>
 
-    <!-- @hide -->
+    <!-- @hide Autofill background for popup window (not for fullscreen) -->
     <style name="AutofillDatasetPicker">
         <item name="elevation">4dp</item>
         <item name="background">@drawable/autofill_dataset_picker_background</item>
     </style>
 
     <!-- @hide -->
+    <style name="AutofillHalfScreenAnimation">
+        <item name="android:windowEnterAnimation">@anim/slide_in_up</item>
+        <item name="android:windowExitAnimation">@anim/slide_out_down</item>
+    </style>
+
+    <!-- @hide -->
     <style name="AutofillSaveAnimation">
         <item name="android:windowEnterAnimation">@anim/slide_in_up</item>
         <item name="android:windowExitAnimation">@anim/slide_out_down</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0800f51..b7f5b62 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -663,6 +663,7 @@
   <java-symbol type="string" name="autofill_state_re" />
   <java-symbol type="string" name="autofill_this_form" />
   <java-symbol type="string" name="autofill_username_re" />
+  <java-symbol type="string" name="autofill_window_title" />
   <java-symbol type="string" name="autofill_zip_4_re" />
   <java-symbol type="string" name="autofill_zip_code" />
   <java-symbol type="string" name="autofill_zip_code_re" />
@@ -3053,13 +3054,13 @@
   <java-symbol type="layout" name="autofill_dataset_picker"/>
   <java-symbol type="layout" name="autofill_dataset_picker_fullscreen"/>
   <java-symbol type="layout" name="autofill_dataset_picker_header_footer"/>
-  <java-symbol type="layout" name="autofill_dataset_picker_header_footer_fullscreen"/>
   <java-symbol type="id" name="autofill" />
-  <java-symbol type="id" name="autofill_dataset_container"/>
   <java-symbol type="id" name="autofill_dataset_footer"/>
   <java-symbol type="id" name="autofill_dataset_header"/>
+  <java-symbol type="id" name="autofill_dataset_icon" />
   <java-symbol type="id" name="autofill_dataset_list"/>
   <java-symbol type="id" name="autofill_dataset_picker"/>
+  <java-symbol type="id" name="autofill_dataset_title" />
   <java-symbol type="id" name="autofill_save_custom_subtitle" />
   <java-symbol type="id" name="autofill_save_icon" />
   <java-symbol type="id" name="autofill_save_no" />
@@ -3084,6 +3085,7 @@
   <java-symbol type="string" name="autofill_save_type_email_address" />
   <java-symbol type="drawable" name="autofill_dataset_picker_background" />
   <java-symbol type="style" name="AutofillDatasetPicker" />
+  <java-symbol type="style" name="AutofillHalfScreenAnimation" />
   <java-symbol type="style" name="AutofillSaveAnimation" />
   <java-symbol type="dimen" name="autofill_dataset_picker_max_width"/>
   <java-symbol type="dimen" name="autofill_dataset_picker_max_height"/>
@@ -3091,6 +3093,9 @@
   <java-symbol type="dimen" name="autofill_save_icon_max_size"/>
   <java-symbol type="integer" name="autofill_max_visible_datasets" />
 
+  <java-symbol type="style" name="Theme.DeviceDefault.Autofill" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Autofill.Save" />
+
   <java-symbol type="dimen" name="notification_big_picture_max_height"/>
   <java-symbol type="dimen" name="notification_big_picture_max_width"/>
   <java-symbol type="dimen" name="notification_media_image_max_width"/>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 92b2f33..14e5082 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1673,6 +1673,15 @@
         <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
     </style>
 
+
+    <!-- @hide DeviceDefault theme for the autofill FillUi -->
+    <style name="Theme.DeviceDefault.Autofill" parent="Theme.Material.Autofill.Light">
+    </style>
+
+    <!-- @hide DeviceDefault theme for the autofill SaveUi -->
+    <style name="Theme.DeviceDefault.Autofill.Save" parent="Theme.Material.Autofill.Save.Light">
+    </style>
+
     <!-- DeviceDefault theme for the default system theme.  -->
     <style name="Theme.DeviceDefault.System" parent="Theme.DeviceDefault.Light.DarkActionBar" />
 
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 9b633fc..b3e33d5 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1417,4 +1417,25 @@
         <item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
         <item name="colorSecondary">@color/secondary_material_settings</item>
     </style>
+
+    <!-- @hide -->
+    <style name="Theme.Material.Autofill" parent="Theme.Material">
+        <item name="colorBackground">@color/autofill_background_material_dark</item>
+    </style>
+
+    <!-- @hide -->
+    <style name="Theme.Material.Autofill.Light" parent="Theme.Material.Light">
+        <item name="colorBackground">@color/autofill_background_material_light</item>
+    </style>
+
+    <!-- @hide -->
+    <style name="Theme.Material.Autofill.Save" parent="Theme.Material.Panel">
+        <item name="colorBackground">@color/autofill_background_material_dark</item>
+    </style>
+
+    <!-- @hide -->
+    <style name="Theme.Material.Autofill.Save.Light" parent="Theme.Material.Light.Panel">
+        <item name="colorBackground">@color/autofill_background_material_light</item>
+    </style>
+
 </resources>
diff --git a/core/tests/coretests/src/android/app/usage/EventListTest.java b/core/tests/coretests/src/android/app/usage/EventListTest.java
new file mode 100644
index 0000000..9dc0d43
--- /dev/null
+++ b/core/tests/coretests/src/android/app/usage/EventListTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.app.usage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class EventListTest {
+    private static final String TAG = EventListTest.class.getSimpleName();
+
+    private UsageEvents.Event getUsageEvent(long timeStamp) {
+        final UsageEvents.Event event = new UsageEvents.Event();
+        event.mTimeStamp = timeStamp;
+        return event;
+    }
+
+    private static String getListTimeStamps(EventList list) {
+        final StringBuilder builder = new StringBuilder("[");
+        for (int i = 0; i < list.size() - 1; i++) {
+            builder.append(list.get(i).mTimeStamp);
+            builder.append(", ");
+        }
+        builder.append(list.get(list.size() - 1).mTimeStamp);
+        builder.append("]");
+        return builder.toString();
+    }
+
+    private static void assertSorted(EventList eventList) {
+        for (int i = 1; i < eventList.size(); i++) {
+            final long lastTimeStamp = eventList.get(i - 1).mTimeStamp;
+            if (eventList.get(i).mTimeStamp < lastTimeStamp) {
+                Log.e(TAG, "Unsorted timestamps in list: " + getListTimeStamps(eventList));
+                fail("Timestamp " + eventList.get(i).mTimeStamp + " at " + i
+                        + " follows larger timestamp " + lastTimeStamp);
+            }
+        }
+    }
+
+    @Test
+    public void testInsertsSortedRandom() {
+        final Random random = new Random(128);
+        final EventList listUnderTest = new EventList();
+        for (int i = 0; i < 100; i++) {
+            listUnderTest.insert(getUsageEvent(random.nextLong()));
+        }
+        assertSorted(listUnderTest);
+    }
+
+    @Test
+    public void testInsertsSortedWithDuplicates() {
+        final Random random = new Random(256);
+        final EventList listUnderTest = new EventList();
+        for (int i = 0; i < 10; i++) {
+            final long randomTimeStamp = random.nextLong();
+            for (int j = 0; j < 10; j++) {
+                listUnderTest.insert(getUsageEvent(randomTimeStamp));
+            }
+        }
+        assertSorted(listUnderTest);
+    }
+
+    @Test
+    public void testFirstIndexOnOrAfter() {
+        final EventList listUnderTest = new EventList();
+        listUnderTest.insert(getUsageEvent(2));
+        listUnderTest.insert(getUsageEvent(5));
+        listUnderTest.insert(getUsageEvent(5));
+        listUnderTest.insert(getUsageEvent(5));
+        listUnderTest.insert(getUsageEvent(8));
+        assertTrue(listUnderTest.firstIndexOnOrAfter(1) == 0);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(2) == 0);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(3) == 1);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(4) == 1);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(5) == 1);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(6) == 4);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(7) == 4);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(8) == 4);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(9) == listUnderTest.size());
+        assertTrue(listUnderTest.firstIndexOnOrAfter(100) == listUnderTest.size());
+
+        listUnderTest.clear();
+        assertTrue(listUnderTest.firstIndexOnOrAfter(5) == 0);
+        assertTrue(listUnderTest.firstIndexOnOrAfter(100) == 0);
+    }
+
+    @Test
+    public void testClear() {
+        final EventList listUnderTest = new EventList();
+        for (int i = 1; i <= 100; i++) {
+            listUnderTest.insert(getUsageEvent(i));
+        }
+        listUnderTest.clear();
+        assertEquals(0, listUnderTest.size());
+    }
+
+    @Test
+    public void testSize() {
+        final EventList listUnderTest = new EventList();
+        for (int i = 1; i <= 100; i++) {
+            listUnderTest.insert(getUsageEvent(i));
+        }
+        assertEquals(100, listUnderTest.size());
+    }
+}
diff --git a/core/tests/coretests/src/android/app/usage/TimeSparseArrayTest.java b/core/tests/coretests/src/android/app/usage/TimeSparseArrayTest.java
deleted file mode 100644
index db46740..0000000
--- a/core/tests/coretests/src/android/app/usage/TimeSparseArrayTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.app.usage;
-
-import static org.junit.Assert.assertTrue;
-
-import android.os.SystemClock;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class TimeSparseArrayTest {
-    @Test
-    public void testDuplicateKeysNotDropped() {
-        final TimeSparseArray<Integer> testTimeSparseArray = new TimeSparseArray<>();
-        final long key = SystemClock.elapsedRealtime();
-        for (int i = 0; i < 5; i++) {
-            testTimeSparseArray.put(key, i);
-        }
-        for (int i = 0; i < 5; i++) {
-            final int valueIndex = testTimeSparseArray.indexOfValue(i);
-            assertTrue("Value " + i + " not found; intended key: " + key , valueIndex >= 0);
-            final long keyForValue = testTimeSparseArray.keyAt(valueIndex);
-            assertTrue("Value " + i + " stored too far (at " + keyForValue + ") from intended key "
-                    + key, Math.abs(keyForValue - key) < 100);
-        }
-    }
-}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 43e980e..dafd475 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -98,6 +98,7 @@
     private static final Set<String> BACKUP_BLACKLISTED_GLOBAL_SETTINGS =
             newHashSet(
                     Settings.Global.ACTIVITY_MANAGER_CONSTANTS,
+                    Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED,
                     Settings.Global.ADB_ENABLED,
                     Settings.Global.ADD_USERS_WHEN_LOCKED,
                     Settings.Global.AIRPLANE_MODE_ON,
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 7d4e6f8..b3a3f45 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3504,13 +3504,14 @@
 {
     PackageGroup(
             ResTable* _owner, const String16& _name, uint32_t _id,
-            bool appAsLib, bool _isSystemAsset)
+            bool appAsLib, bool _isSystemAsset, bool _isDynamic)
         : owner(_owner)
         , name(_name)
         , id(_id)
         , largestTypeId(0)
         , dynamicRefTable(static_cast<uint8_t>(_id), appAsLib)
         , isSystemAsset(_isSystemAsset)
+        , isDynamic(_isDynamic)
     { }
 
     ~PackageGroup() {
@@ -3614,6 +3615,7 @@
     // If the package group comes from a system asset. Used in
     // determining non-system locales.
     const bool                      isSystemAsset;
+    const bool isDynamic;
 };
 
 ResTable::Theme::Theme(const ResTable& table)
@@ -3982,6 +3984,11 @@
     return ((ssize_t)mPackageMap[Res_GETPACKAGE(resID)+1])-1;
 }
 
+inline ssize_t ResTable::getResourcePackageIndexFromPackage(uint8_t packageID) const
+{
+    return ((ssize_t)mPackageMap[packageID])-1;
+}
+
 status_t ResTable::add(const void* data, size_t size, const int32_t cookie, bool copyData) {
     return addInternal(data, size, NULL, 0, false, cookie, copyData);
 }
@@ -4037,7 +4044,7 @@
     for (size_t i=0; i < src->mPackageGroups.size(); i++) {
         PackageGroup* srcPg = src->mPackageGroups[i];
         PackageGroup* pg = new PackageGroup(this, srcPg->name, srcPg->id,
-                false /* appAsLib */, isSystemAsset || srcPg->isSystemAsset);
+                false /* appAsLib */, isSystemAsset || srcPg->isSystemAsset, srcPg->isDynamic);
         for (size_t j=0; j<srcPg->packages.size(); j++) {
             pg->packages.add(srcPg->packages[j]);
         }
@@ -6277,6 +6284,68 @@
     return true;
 }
 
+bool ResTable::isPackageDynamic(uint8_t packageID) const {
+  if (mError != NO_ERROR) {
+      return false;
+  }
+  if (packageID == 0) {
+      ALOGW("Invalid package number 0x%08x", packageID);
+      return false;
+  }
+
+  const ssize_t p = getResourcePackageIndexFromPackage(packageID);
+
+  if (p < 0) {
+      ALOGW("Unknown package number 0x%08x", packageID);
+      return false;
+  }
+
+  const PackageGroup* const grp = mPackageGroups[p];
+  if (grp == NULL) {
+      ALOGW("Bad identifier for package number 0x%08x", packageID);
+      return false;
+  }
+
+  return grp->isDynamic;
+}
+
+bool ResTable::isResourceDynamic(uint32_t resID) const {
+    if (mError != NO_ERROR) {
+        return false;
+    }
+
+    const ssize_t p = getResourcePackageIndex(resID);
+    const int t = Res_GETTYPE(resID);
+    const int e = Res_GETENTRY(resID);
+
+    if (p < 0) {
+        if (Res_GETPACKAGE(resID)+1 == 0) {
+            ALOGW("No package identifier for resource number 0x%08x", resID);
+        } else {
+            ALOGW("No known package for resource number 0x%08x", resID);
+        }
+        return false;
+    }
+    if (t < 0) {
+        ALOGW("No type identifier for resource number 0x%08x", resID);
+        return false;
+    }
+
+    const PackageGroup* const grp = mPackageGroups[p];
+    if (grp == NULL) {
+        ALOGW("Bad identifier for resource number 0x%08x", resID);
+        return false;
+    }
+
+    Entry entry;
+    status_t err = getEntry(grp, t, e, NULL, &entry);
+    if (err != NO_ERROR) {
+        return false;
+    }
+
+    return grp->isDynamic;
+}
+
 static bool keyCompare(const ResTable_sparseTypeEntry& entry , uint16_t entryIdx) {
   return dtohs(entry.idx) < entryIdx;
 }
@@ -6520,12 +6589,14 @@
         id = targetPackageId;
     }
 
+    bool isDynamic = false;
     if (id >= 256) {
         LOG_ALWAYS_FATAL("Package id out of range");
         return NO_ERROR;
     } else if (id == 0 || (id == 0x7f && appAsLib) || isSystemAsset) {
         // This is a library or a system asset, so assign an ID
         id = mNextPackageId++;
+        isDynamic = true;
     }
 
     PackageGroup* group = NULL;
@@ -6553,10 +6624,9 @@
     size_t idx = mPackageMap[id];
     if (idx == 0) {
         idx = mPackageGroups.size() + 1;
-
         char16_t tmpName[sizeof(pkg->name)/sizeof(pkg->name[0])];
         strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(pkg->name[0]));
-        group = new PackageGroup(this, String16(tmpName), id, appAsLib, isSystemAsset);
+        group = new PackageGroup(this, String16(tmpName), id, appAsLib, isSystemAsset, isDynamic);
         if (group == NULL) {
             delete package;
             return (mError=NO_MEMORY);
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index bc0a07a..63b9e3a 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1716,6 +1716,18 @@
     bool getResourceFlags(uint32_t resID, uint32_t* outFlags) const;
 
     /**
+     * Returns whether or not the package for the given resource has been dynamically assigned.
+     * If the resource can't be found, returns 'false'.
+     */
+    bool isResourceDynamic(uint32_t resID) const;
+
+    /**
+     * Returns whether or not the given package has been dynamically assigned.
+     * If the package can't be found, returns 'false'.
+     */
+    bool isPackageDynamic(uint8_t packageID) const;
+
+    /**
      * Retrieve the value of a resource.  If the resource is found, returns a
      * value >= 0 indicating the table it is in (for use with
      * getTableStringBlock() and getTableCookie()) and fills in 'outValue'.  If
@@ -2024,6 +2036,7 @@
             bool appAsLib, const int32_t cookie, bool copyData, bool isSystemAsset=false);
 
     ssize_t getResourcePackageIndex(uint32_t resID) const;
+    ssize_t getResourcePackageIndexFromPackage(uint8_t packageID) const;
 
     status_t getEntry(
         const PackageGroup* packageGroup, int typeIndex, int entryIndex,
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 0e2a0e0..91c04fa 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -321,6 +321,7 @@
         // TODO: reuse NetworkMonitor facilities for consistent captive portal detection.
         new Thread(new Runnable() {
             public void run() {
+                final Network network = ResolvUtil.makeNetworkWithPrivateDnsBypass(mNetwork);
                 // Give time for captive portal to open.
                 try {
                     Thread.sleep(1000);
@@ -329,7 +330,7 @@
                 HttpURLConnection urlConnection = null;
                 int httpResponseCode = 500;
                 try {
-                    urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl);
+                    urlConnection = (HttpURLConnection) network.openConnection(mUrl);
                     urlConnection.setInstanceFollowRedirects(false);
                     urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
                     urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index aeb4a85..8bab3ca 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -46,6 +46,7 @@
 import com.android.internal.widget.LockPatternUtils;
 
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Utility class to host methods usable in adding a restricted padlock icon and showing admin
@@ -90,29 +91,29 @@
             // Restriction is not enforced.
             return null;
         } else if (enforcingUsers.size() > 1) {
-            return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+            return EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction);
         }
 
         final int restrictionSource = enforcingUsers.get(0).getUserRestrictionSource();
         final int adminUserId = enforcingUsers.get(0).getUserHandle().getIdentifier();
-
         if (restrictionSource == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) {
             // Check if it is a profile owner of the user under consideration.
             if (adminUserId == userId) {
-                return getProfileOwner(context, adminUserId);
+                return getProfileOwner(context, userRestriction, adminUserId);
             } else {
                 // Check if it is a profile owner of a managed profile of the current user.
                 // Otherwise it is in a separate user and we return a default EnforcedAdmin.
                 final UserInfo parentUser = um.getProfileParent(adminUserId);
                 return (parentUser != null && parentUser.id == userId)
-                        ? getProfileOwner(context, adminUserId)
-                        : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+                        ? getProfileOwner(context, userRestriction, adminUserId)
+                        : EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction);
             }
         } else if (restrictionSource == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) {
             // When the restriction is enforced by device owner, return the device owner admin only
             // if the admin is for the {@param userId} otherwise return a default EnforcedAdmin.
             return adminUserId == userId
-                    ? getDeviceOwner(context) : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
+                    ? getDeviceOwner(context, userRestriction)
+                    : EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction);
         }
 
         // If the restriction is enforced by system then return null.
@@ -406,7 +407,6 @@
      * or {@code null} if no quality requirements are set. If the requirements are set by
      * multiple device admins, then the admin component will be set to {@code null} and userId to
      * {@link UserHandle#USER_NULL}.
-     *
      */
     public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) {
         final LockSettingCheck check =
@@ -518,6 +518,11 @@
     }
 
     public static EnforcedAdmin getProfileOrDeviceOwner(Context context, int userId) {
+        return getProfileOrDeviceOwner(context, null, userId);
+    }
+
+    public static EnforcedAdmin getProfileOrDeviceOwner(
+            Context context, String enforcedRestriction, int userId) {
         if (userId == UserHandle.USER_NULL) {
             return null;
         }
@@ -528,18 +533,22 @@
         }
         ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
         if (adminComponent != null) {
-            return new EnforcedAdmin(adminComponent, userId);
+            return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
         }
         if (dpm.getDeviceOwnerUserId() == userId) {
             adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
             if (adminComponent != null) {
-                return new EnforcedAdmin(adminComponent, userId);
+                return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
             }
         }
         return null;
     }
 
     public static EnforcedAdmin getDeviceOwner(Context context) {
+        return getDeviceOwner(context, null);
+    }
+
+    private static EnforcedAdmin getDeviceOwner(Context context, String enforcedRestriction) {
         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (dpm == null) {
@@ -547,12 +556,18 @@
         }
         ComponentName adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
         if (adminComponent != null) {
-            return new EnforcedAdmin(adminComponent, dpm.getDeviceOwnerUserId());
+            return new EnforcedAdmin(
+                    adminComponent, enforcedRestriction, dpm.getDeviceOwnerUserId());
         }
         return null;
     }
 
     private static EnforcedAdmin getProfileOwner(Context context, int userId) {
+        return getProfileOwner(context, null, userId);
+    }
+
+    private static EnforcedAdmin getProfileOwner(
+            Context context, String enforcedRestriction, int userId) {
         if (userId == UserHandle.USER_NULL) {
             return null;
         }
@@ -563,7 +578,7 @@
         }
         ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
         if (adminComponent != null) {
-            return new EnforcedAdmin(adminComponent, userId);
+            return new EnforcedAdmin(adminComponent, enforcedRestriction, userId);
         }
         return null;
     }
@@ -626,6 +641,7 @@
                 && isCurrentUserOrProfile(context, admin.userId)) {
             targetUserId = admin.userId;
         }
+        intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, admin.enforcedRestriction);
         context.startActivityAsUser(intent, new UserHandle(targetUserId));
     }
 
@@ -700,53 +716,71 @@
     }
 
     public static class EnforcedAdmin {
+        @Nullable
         public ComponentName component = null;
+        /**
+         * The restriction enforced by admin. It could be any user restriction or policy like
+         * {@link DevicePolicyManager#POLICY_DISABLE_CAMERA}.
+         */
+        @Nullable
+        public String enforcedRestriction = null;
         public int userId = UserHandle.USER_NULL;
 
         // We use this to represent the case where a policy is enforced by multiple admins.
         public final static EnforcedAdmin MULTIPLE_ENFORCED_ADMIN = new EnforcedAdmin();
 
+        public static EnforcedAdmin createDefaultEnforcedAdminWithRestriction(
+                String enforcedRestriction) {
+            EnforcedAdmin enforcedAdmin = new EnforcedAdmin();
+            enforcedAdmin.enforcedRestriction = enforcedRestriction;
+            return enforcedAdmin;
+        }
+
         public EnforcedAdmin(ComponentName component, int userId) {
             this.component = component;
             this.userId = userId;
         }
 
+        public EnforcedAdmin(ComponentName component, String enforcedRestriction, int userId) {
+            this.component = component;
+            this.enforcedRestriction = enforcedRestriction;
+            this.userId = userId;
+        }
+
         public EnforcedAdmin(EnforcedAdmin other) {
             if (other == null) {
                 throw new IllegalArgumentException();
             }
             this.component = other.component;
+            this.enforcedRestriction = other.enforcedRestriction;
             this.userId = other.userId;
         }
 
-        public EnforcedAdmin() {}
+        public EnforcedAdmin() {
+        }
 
         @Override
-        public boolean equals(Object object) {
-            if (object == this) return true;
-            if (!(object instanceof EnforcedAdmin)) return false;
-            EnforcedAdmin other = (EnforcedAdmin) object;
-            if (userId != other.userId) {
-                return false;
-            }
-            if ((component == null && other.component == null) ||
-                    (component != null && component.equals(other.component))) {
-                return true;
-            }
-            return false;
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            EnforcedAdmin that = (EnforcedAdmin) o;
+            return userId == that.userId &&
+                    Objects.equals(component, that.component) &&
+                    Objects.equals(enforcedRestriction, that.enforcedRestriction);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(component, enforcedRestriction, userId);
         }
 
         @Override
         public String toString() {
-            return "EnforcedAdmin{component=" + component + ",userId=" + userId + "}";
-        }
-
-        public void copyTo(EnforcedAdmin other) {
-            if (other == null) {
-                throw new IllegalArgumentException();
-            }
-            other.component = component;
-            other.userId = userId;
+            return "EnforcedAdmin{" +
+                    "component=" + component +
+                    ", enforcedRestriction='" + enforcedRestriction +
+                    ", userId=" + userId +
+                    '}';
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
index 113256f..e2faf6a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
@@ -354,20 +354,15 @@
             return;
         }
 
-        if (userInfo.isGuest()) {
-            switchToGuest(userInfo.name);
-            return;
-        }
-
         switchToUserId(userInfo.id);
     }
 
     /**
-     * Creates a guest session and switches into the guest session.
+     * Creates a new guest session and switches into the guest session.
      *
      * @param guestName Username for the guest user.
      */
-    public void switchToGuest(String guestName) {
+    public void startNewGuestSession(String guestName) {
         UserInfo guest = mUserManager.createGuest(mContext, guestName);
         if (guest == null) {
             // Couldn't create user, most likely because there are too many, but we haven't
@@ -375,6 +370,7 @@
             Log.w(TAG, "can't create user.");
             return;
         }
+        assignDefaultIcon(guest);
         switchToUserId(guest.id);
     }
 
@@ -417,6 +413,27 @@
         mUserManager.setUserName(user.id, name);
     }
 
+    /**
+     * Gets a bitmap representing the user's default avatar.
+     *
+     * @param userInfo User whose avatar should be returned.
+     * @return Default user icon
+     */
+    public Bitmap getUserDefaultIcon(UserInfo userInfo) {
+        return UserIcons.convertToBitmap(
+                UserIcons.getDefaultUserIcon(mContext.getResources(), userInfo.id, false));
+    }
+
+    /**
+     * Gets a bitmap representing the default icon for a Guest user.
+     *
+     * @return Degault guest icon
+     */
+    public Bitmap getGuestDefaultIcon() {
+        return UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
+                mContext.getResources(), UserHandle.USER_NULL, false));
+    }
+
     private void registerReceiver() {
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_USER_REMOVED);
@@ -435,8 +452,7 @@
      * @return Bitmap that has been assigned to the user.
      */
     private Bitmap assignDefaultIcon(UserInfo userInfo) {
-        Bitmap bitmap = UserIcons.convertToBitmap(
-                UserIcons.getDefaultUserIcon(mContext.getResources(), userInfo.id, false));
+        Bitmap bitmap = userInfo.isGuest() ? getGuestDefaultIcon() : getUserDefaultIcon(userInfo);
         mUserManager.setUserIcon(userInfo.id, bitmap);
         return bitmap;
     }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
index 15f7770..54510b2 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
@@ -247,13 +247,13 @@
     }
 
     @Test
-    public void switchToGuest() {
-        mHelper.switchToGuest("Test Guest");
+    public void startNewGuestSession() {
+        mHelper.startNewGuestSession("Test Guest");
         verify(mUserManager).createGuest(mContext, "Test Guest");
 
         UserInfo guestInfo = new UserInfo(21, "Test Guest", UserInfo.FLAG_GUEST);
         when(mUserManager.createGuest(mContext, "Test Guest")).thenReturn(guestInfo);
-        mHelper.switchToGuest("Test Guest");
+        mHelper.startNewGuestSession("Test Guest");
         verify(mActivityManager).switchUser(21);
     }
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 5f60868..710dbc22 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -32,6 +32,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.os.UserHandle;
 import android.os.UserManager;
 
 import org.junit.Before;
@@ -42,6 +43,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.Arrays;
+import java.util.Collections;
 
 @RunWith(SettingsLibRobolectricTestRunner.class)
 public class RestrictedLockUtilsTest {
@@ -77,6 +79,42 @@
     }
 
     @Test
+    public void checkIfRestrictionEnforced_deviceOwner() {
+        UserManager.EnforcingUser enforcingUser = new UserManager.EnforcingUser(mUserId,
+                UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
+        final String userRestriction = UserManager.DISALLOW_UNINSTALL_APPS;
+        when(mUserManager.getUserRestrictionSources(userRestriction,
+                UserHandle.of(mUserId))).
+                thenReturn(Collections.singletonList(enforcingUser));
+        setUpDeviceOwner(mAdmin1);
+
+        EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
+                userRestriction, mUserId);
+
+        assertThat(enforcedAdmin).isNotNull();
+        assertThat(enforcedAdmin.enforcedRestriction).isEqualTo(userRestriction);
+        assertThat(enforcedAdmin.component).isEqualTo(mAdmin1);
+    }
+
+    @Test
+    public void checkIfRestrictionEnforced_profileOwner() {
+        UserManager.EnforcingUser enforcingUser = new UserManager.EnforcingUser(mUserId,
+                UserManager.RESTRICTION_SOURCE_PROFILE_OWNER);
+        final String userRestriction = UserManager.DISALLOW_UNINSTALL_APPS;
+        when(mUserManager.getUserRestrictionSources(userRestriction,
+                UserHandle.of(mUserId))).
+                thenReturn(Collections.singletonList(enforcingUser));
+        setUpProfileOwner(mAdmin1, mUserId);
+
+        EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
+                userRestriction, mUserId);
+
+        assertThat(enforcedAdmin).isNotNull();
+        assertThat(enforcedAdmin.enforcedRestriction).isEqualTo(userRestriction);
+        assertThat(enforcedAdmin.component).isEqualTo(mAdmin1);
+    }
+
+    @Test
     public void checkIfDevicePolicyServiceDisabled_noEnforceAdminForManagedProfile() {
         when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(null);
         final EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfAccountManagementDisabled(
@@ -263,4 +301,12 @@
         when(mDevicePolicyManager.getActiveAdminsAsUser(userId))
                 .thenReturn(Arrays.asList(activeAdmins));
     }
+
+    private void setUpDeviceOwner(ComponentName admin) {
+        when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(admin);
+    }
+
+    private void setUpProfileOwner(ComponentName admin, int userId) {
+        when(mDevicePolicyManager.getProfileOwnerAsUser(userId)).thenReturn(admin);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
index f2ea3a4..890abef 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
@@ -185,12 +185,7 @@
         mHelper.switchToUser(createUserInfoForId(20));
         assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isFalse();
 
-        // Switching to Guest calls createGuest.
-        UserInfo guestInfo = new UserInfo(21, "Test Guest", UserInfo.FLAG_GUEST);
-        mHelper.switchToUser(guestInfo);
-        verify(mUserManager).createGuest(mContext, "Test Guest");
-
-        // Switching to non-current, non-guest user, simply calls switchUser.
+        // Switching to non-foreground user, simply calls switchUser.
         UserInfo userToSwitchTo = new UserInfo(22, "Test User", 0);
         mHelper.switchToUser(userToSwitchTo);
         assertThat(ShadowActivityManager.getShadow().getSwitchUserCalled()).isTrue();
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index 5f73bef..4301fdb 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -18,13 +18,15 @@
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/quick_qs_status_icons"
     android:layout_width="match_parent"
-    android:layout_height="20dp"
+    android:layout_height="wrap_content"
     android:layout_marginTop="8dp"
     android:layout_marginBottom="14dp"
-    android:layout_marginStart="8dp"
-    android:layout_marginEnd="@dimen/notification_side_paddings"
+    android:layout_marginStart="@dimen/status_bar_padding_start"
+    android:layout_marginEnd="@dimen/status_bar_padding_end"
     android:layout_below="@id/quick_status_bar_system_icons"
-    android:paddingEnd="@dimen/status_bar_padding_end" >
+    android:clipChildren="false"
+    android:clipToPadding="false"
+    android:minHeight="20dp" >
 
     <com.android.systemui.statusbar.policy.DateView
         android:id="@+id/date"
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 54baa4a..0892f73 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -45,14 +45,16 @@
             android:layout_width="@dimen/qs_header_alarm_icon_size"
             android:layout_height="@dimen/qs_header_alarm_icon_size"
             android:src="@drawable/stat_sys_alarm"
-            android:tint="?android:attr/textColorPrimary" />
+            android:tint="?android:attr/textColorPrimary"
+            android:visibility="gone"/>
 
         <TextView
             android:id="@+id/next_alarm_text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
-            android:textAppearance="@style/TextAppearance.QS.TileLabel" />
+            android:textAppearance="@style/TextAppearance.QS.TileLabel"
+            android:visibility="gone"/>
 
         <View
             android:id="@+id/status_separator"
@@ -61,20 +63,23 @@
             android:layout_marginStart="10dp"
             android:layout_marginEnd="10dp"
             android:background="@android:color/white"
-            android:backgroundTint="?android:attr/textColorPrimary" />
+            android:backgroundTint="?android:attr/textColorPrimary"
+            android:visibility="gone"/>
 
         <ImageView
             android:id="@+id/ringer_mode_icon"
             android:layout_width="@dimen/qs_header_alarm_icon_size"
             android:layout_height="@dimen/qs_header_alarm_icon_size"
-            android:tint="?android:attr/textColorPrimary" />
+            android:tint="?android:attr/textColorPrimary"
+            android:visibility="gone"/>
 
         <TextView
             android:id="@+id/ringer_mode_text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
-            android:textAppearance="@style/TextAppearance.QS.TileLabel" />
+            android:textAppearance="@style/TextAppearance.QS.TileLabel"
+            android:visibility="gone"/>
 
     </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index a9fe862..d40534e 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -20,15 +20,12 @@
     android:id="@+id/quick_status_bar_system_icons"
     android:layout_width="match_parent"
     android:layout_height="@*android:dimen/quick_qs_offset_height"
-    android:layout_marginRight="@dimen/notification_side_paddings"
-    android:layout_marginLeft="@dimen/notification_side_paddings"
-    android:layout_alignParentEnd="true"
     android:clipChildren="false"
     android:clipToPadding="false"
     android:gravity="center"
+    android:orientation="horizontal"
     android:paddingStart="@dimen/status_bar_padding_start"
-    android:paddingEnd="@dimen/status_bar_padding_end"
-    android:orientation="horizontal">
+    android:paddingEnd="@dimen/status_bar_padding_end" >
 
     <com.android.systemui.statusbar.policy.Clock
         android:id="@+id/clock"
diff --git a/packages/SystemUI/res/layout/volume_dnd_icon.xml b/packages/SystemUI/res/layout/volume_dnd_icon.xml
index acf9aed..ac235b7 100644
--- a/packages/SystemUI/res/layout/volume_dnd_icon.xml
+++ b/packages/SystemUI/res/layout/volume_dnd_icon.xml
@@ -15,11 +15,11 @@
 -->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="@dimen/volume_dialog_panel_width"
+    android:id="@+id/dnd_icon"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
     <ImageView
-        android:id="@+id/dnd_icon"
         android:layout_width="14dp"
         android:layout_height="14dp"
         android:layout_marginTop="6dp"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 26c7858..ac9fb2b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -326,7 +326,7 @@
     <dimen name="pull_span_min">25dp</dimen>
 
     <dimen name="qs_tile_height">106dp</dimen>
-    <dimen name="qs_tile_layout_margin_side">9dp</dimen>
+    <dimen name="qs_tile_layout_margin_side">6dp</dimen>
     <dimen name="qs_tile_margin_horizontal">18dp</dimen>
     <dimen name="qs_tile_margin_vertical">24dp</dimen>
     <dimen name="qs_tile_margin_top_bottom">12dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index a44f9433..d8bf990 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -40,7 +40,7 @@
     private int mHeightOverride = -1;
     private QSPanel mQSPanel;
     private View mQSDetail;
-    private View mHeader;
+    private QuickStatusBarHeader mHeader;
     private float mQsExpansion;
     private QSCustomizer mQSCustomizer;
     private View mQSFooter;
@@ -178,7 +178,7 @@
         setMargins(mBackground);
         setMargins(mQSFooter);
         mQSPanel.setMargins(mSideMargins);
-        setMargins(mHeader);
+        mHeader.setMargins(mSideMargins);
     }
 
     private void setMargins(View view) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index f027c4b..ad2efbd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -41,6 +41,7 @@
 import android.view.View;
 import android.view.WindowInsets;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
@@ -591,4 +592,16 @@
     public static float getColorIntensity(@ColorInt int color) {
         return color == Color.WHITE ? 0 : 1;
     }
+
+    public void setMargins(int sideMargins) {
+        for (int i = 0; i < getChildCount(); i++) {
+            View v = getChildAt(i);
+            if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel) {
+                continue;
+            }
+            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
+            lp.leftMargin = sideMargins;
+            lp.rightMargin = sideMargins;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 1148fad..5768fa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -207,7 +207,7 @@
 
                 // If the user selects Guest, start the guest session.
                 if (userRecord.mIsStartGuestSession) {
-                    mUserManagerHelper.switchToGuest(mGuestName);
+                    mUserManagerHelper.startNewGuestSession(mGuestName);
                     return;
                 }
 
@@ -241,8 +241,7 @@
 
         private Bitmap getUserRecordIcon(UserRecord userRecord) {
             if (userRecord.mIsStartGuestSession) {
-                return UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon(
-                    mContext.getResources(), UserHandle.USER_NULL, false));
+                return mUserManagerHelper.getGuestDefaultIcon();
             }
 
             if (userRecord.mIsAddUser) {
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 66176b3..2ddae74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -281,6 +281,7 @@
 
         IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
         filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
         getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
         notifyNavigationBarScreenOn();
         mOverviewProxyService.addCallback(mOverviewProxyListener);
@@ -521,7 +522,7 @@
 
         // Clear any pending suggestion flag as it has either been nullified or is being shown
         mPendingRotationSuggestion = false;
-        getView().removeCallbacks(mCancelPendingRotationProposal);
+        if (getView() != null) getView().removeCallbacks(mCancelPendingRotationProposal);
 
         // Handle the visibility change and animation
         if (visible) { // Appear and change (cannot force)
@@ -1084,6 +1085,10 @@
                     || Intent.ACTION_SCREEN_ON.equals(action)) {
                 notifyNavigationBarScreenOn();
             }
+            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                // The accessibility settings may be different for the new user
+                updateAccessibilityServicesState(mAccessibilityManager);
+            };
         }
     };
 
@@ -1141,6 +1146,7 @@
         private final Runnable mRipple = new Runnable() {
             @Override
             public void run() { // Cause the ripple to fire via false presses
+                if (!mRoot.isAttachedToWindow()) return;
                 mRoot.setPressed(true);
                 mRoot.setPressed(false);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index b4e7575..24a5896 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -88,7 +88,7 @@
         List<Slot> allSlots = getSlots();
         for (int i = 0; i < allSlots.size(); i++) {
             Slot slot = allSlots.get(i);
-            List<StatusBarIconHolder> holders = slot.getHolderList();
+            List<StatusBarIconHolder> holders = slot.getHolderListInViewOrder();
             boolean blocked = mIconBlacklist.contains(slot.getName());
 
             for (StatusBarIconHolder holder : holders) {
@@ -121,7 +121,7 @@
         // Remove all the icons.
         for (int i = currentSlots.size() - 1; i >= 0; i--) {
             Slot s = currentSlots.get(i);
-            slotsToReAdd.put(s, s.getHolderList());
+            slotsToReAdd.put(s, s.getHolderListInViewOrder());
             removeAllIconsForSlot(s.getName());
         }
 
@@ -281,7 +281,7 @@
         mIconLogger.onIconHidden(slotName);
 
         int slotIndex = getSlotIndex(slotName);
-        List<StatusBarIconHolder> iconsToRemove = slot.getHolderList();
+        List<StatusBarIconHolder> iconsToRemove = slot.getHolderListInViewOrder();
         for (StatusBarIconHolder holder : iconsToRemove) {
             int viewIndex = getViewIndex(slotIndex, holder.getTag());
             slot.removeForTag(holder.getTag());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index c773170..b7e1cfb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -211,7 +211,7 @@
         }
 
         /**
-         * View index is backwards from regular index
+         * View index is inverted from regular index, because they are laid out back-to-front
          * @param tag the tag of the holder being viewed
          * @return (1 + mSubSlots.size() - indexOfTag)
          */
@@ -228,14 +228,22 @@
             return subSlots - getIndexForTag(tag) - 1;
         }
 
-        public List<StatusBarIconHolder> getHolderList() {
+        /**
+         * Build a list of the {@link StatusBarIconHolder}s in the same order they appear in their
+         * view group. This provides a safe list that can be iterated and inserted into its group.
+         *
+         * @return all holders contained here, in view order
+         */
+        public List<StatusBarIconHolder> getHolderListInViewOrder() {
             ArrayList<StatusBarIconHolder> holders = new ArrayList<>();
-            if (mHolder != null) {
-                holders.add(mHolder);
+            if (mSubSlots != null) {
+                for (int i = mSubSlots.size() - 1; i >= 0; i--) {
+                    holders.add(mSubSlots.get(i));
+                }
             }
 
-            if (mSubSlots != null) {
-                holders.addAll(mSubSlots);
+            if (mHolder != null) {
+                holders.add(mHolder);
             }
 
             return holders;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 5c7ce59..d7aedc4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -53,7 +53,6 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.os.VibrationEffect;
-import android.os.Vibrator;
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.text.InputFilter;
@@ -73,8 +72,8 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
 import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
 import android.widget.ImageButton;
-import android.widget.ImageView;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
@@ -122,7 +121,7 @@
     private ImageButton mRingerIcon;
     private View mSettingsView;
     private ImageButton mSettingsIcon;
-    private ImageView mZenIcon;
+    private FrameLayout mZenIcon;
     private final List<VolumeRow> mRows = new ArrayList<>();
     private ConfigurableTexts mConfigurableTexts;
     private final SparseBooleanArray mDynamic = new SparseBooleanArray();
@@ -132,7 +131,6 @@
     private final Accessibility mAccessibility = new Accessibility();
     private final ColorStateList mActiveTint;
     private final ColorStateList mInactiveTint;
-    private final Vibrator mVibrator;
 
     private boolean mShowing;
     private boolean mShowA11yStream;
@@ -153,7 +151,6 @@
         mActiveTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
         mInactiveTint = loadColorStateList(R.color.volume_slider_inactive);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
-        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
     }
 
     public void init(int windowType, Callback callback) {
@@ -673,7 +670,28 @@
      * @param enable whether to enable volume row views and hide dnd icon
      */
     private void enableVolumeRowViewsH(VolumeRow row, boolean enable) {
-        row.dndIcon.setVisibility(enable ? GONE : VISIBLE);
+        boolean showDndIcon = !enable;
+        row.dndIcon.setVisibility(showDndIcon ? VISIBLE : GONE);
+
+        if (showDndIcon && getNumVisibleRows() == 1) {
+            row.dndIcon.setLayoutParams(new FrameLayout.LayoutParams(
+                    mContext.getResources().getDimensionPixelSize(
+                            R.dimen.volume_dialog_panel_width),
+                    FrameLayout.LayoutParams.WRAP_CONTENT));
+        } else if (row.view.getVisibility() == VISIBLE) {
+            row.dndIcon.setLayoutParams(new FrameLayout.LayoutParams(
+                    FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT));
+        }
+    }
+
+    private int getNumVisibleRows() {
+        int count = 0;
+        for (int i = 0; i < mRows.size(); i++) {
+            if (mRows.get(i).view.getVisibility() == VISIBLE) {
+                count++;
+            }
+        }
+        return count;
     }
 
     /**
@@ -1241,6 +1259,6 @@
         private ObjectAnimator anim;  // slider progress animation for non-touch-related updates
         private int animTargetProgress;
         private int lastAudibleLevel = 1;
-        private ImageView dndIcon;
+        private FrameLayout dndIcon;
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconListTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconListTest.java
index 07ac11b..e529e4c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconListTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconListTest.java
@@ -132,7 +132,7 @@
      */
 
     @Test
-    public void testSlot_OrderIsPreserved() {
+    public void testSlot_ViewOrder() {
         Slot testSlot = new Slot("test_name", null);
 
         // no tag bc it defaults to 0
@@ -144,17 +144,18 @@
         int sb3Tag = 2;
         when(sbHolder3.getTag()).thenReturn(sb3Tag);
 
-        ArrayList<StatusBarIconHolder> expected = new ArrayList<>();
-        expected.add(sbHolder1);
-        expected.add(sbHolder2);
-        expected.add(sbHolder3);
-
-
         // Add 3 icons in the same slot, and verify that the list we get is equal to what we gave
-        for (StatusBarIconHolder holder : expected) {
-            testSlot.addHolder(holder);
-        }
-        assertTrue(listsEqual(expected, testSlot.getHolderList()));
+        testSlot.addHolder(sbHolder1);
+        testSlot.addHolder(sbHolder2);
+        testSlot.addHolder(sbHolder3);
+
+        // View order is reverse of the order added
+        ArrayList<StatusBarIconHolder> expected = new ArrayList<>();
+        expected.add(sbHolder3);
+        expected.add(sbHolder2);
+        expected.add(sbHolder1);
+
+        assertTrue(listsEqual(expected, testSlot.getHolderListInViewOrder()));
     }
 
     private boolean listsEqual(List<StatusBarIconHolder> list1, List<StatusBarIconHolder> list2) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index e6b2a35..c055060 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2079,7 +2079,8 @@
         }
 
         getUiForShowing().showFillUi(filledId, response, filterText,
-                mService.getServicePackageName(), mComponentName.getPackageName(), this);
+                mService.getServicePackageName(), mComponentName.getPackageName(),
+                mService.getServiceLabel(), mService.getServiceIcon(), this);
 
         synchronized (mLock) {
             if (mUiShownTime == 0) {
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 21a39e4..ee18dc2 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -163,11 +163,14 @@
      * @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 serviceLabel label of autofill service
+     * @param serviceIcon icon of autofill service
      * @param callback Identifier for the caller
      */
     public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response,
             @Nullable String filterText, @Nullable String servicePackageName,
-            @NonNull String packageName, @NonNull AutoFillUiCallback callback) {
+            @NonNull String packageName, @NonNull CharSequence serviceLabel,
+            @NonNull Drawable serviceIcon, @NonNull AutoFillUiCallback callback) {
         if (sDebug) {
             final int size = filterText == null ? 0 : filterText.length();
             Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars");
@@ -185,7 +188,7 @@
             }
             hideAllUiThread(callback);
             mFillUi = new FillUi(mContext, response, focusedId,
-                    filterText, mOverlayControl, new FillUi.Callback() {
+                    filterText, mOverlayControl, serviceLabel, serviceIcon, new FillUi.Callback() {
                 @Override
                 public void onResponsePicked(FillResponse response) {
                     log.setType(MetricsEvent.TYPE_DETAIL);
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d29ca05..1aeb3b9 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -26,6 +26,8 @@
 import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.ContextThemeWrapper;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.PackageManager;
@@ -53,9 +55,11 @@
 import android.widget.Filter;
 import android.widget.Filterable;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.RemoteViews;
+import android.widget.TextView;
 
 import com.android.internal.R;
 import com.android.server.UiThread;
@@ -72,30 +76,10 @@
 final class FillUi {
     private static final String TAG = "FillUi";
 
+    private static final int THEME_ID = com.android.internal.R.style.Theme_DeviceDefault_Autofill;
+
     private static final TypedValue sTempTypedValue = new TypedValue();
 
-    public static final class AutofillFrameLayout extends FrameLayout {
-
-        OnKeyListener mUnhandledListener;
-
-        public AutofillFrameLayout(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-
-        public AutofillFrameLayout(Context context, AttributeSet attrs, @AttrRes int defStyleAttr) {
-            super(context, attrs, defStyleAttr);
-        }
-
-        @Override
-        public boolean dispatchKeyEvent(KeyEvent event) {
-            boolean handled = super.dispatchKeyEvent(event);
-            if (!handled) {
-                handled = mUnhandledListener.onKey(this, event.getKeyCode(), event);
-            }
-            return handled;
-        }
-    }
-
     interface Callback {
         void onResponsePicked(@NonNull FillResponse response);
         void onDatasetPicked(@NonNull Dataset dataset);
@@ -146,51 +130,64 @@
 
     FillUi(@NonNull Context context, @NonNull FillResponse response,
            @NonNull AutofillId focusedViewId, @NonNull @Nullable String filterText,
-           @NonNull OverlayControl overlayControl, @NonNull Callback callback) {
-        mContext = context;
+           @NonNull OverlayControl overlayControl, @NonNull CharSequence serviceLabel,
+           @NonNull Drawable serviceIcon, @NonNull Callback callback) {
         mCallback = callback;
         mFullScreen = isFullScreen(context);
-
-        final LayoutInflater inflater = LayoutInflater.from(context);
+        mContext = new ContextThemeWrapper(context, THEME_ID);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
 
         final RemoteViews headerPresentation = response.getHeader();
         final RemoteViews footerPresentation = response.getFooter();
         final ViewGroup decor;
-        if (headerPresentation != null || footerPresentation != null) {
-            decor = (ViewGroup) inflater.inflate(
-                    mFullScreen ? R.layout.autofill_dataset_picker_header_footer_fullscreen
-                            : R.layout.autofill_dataset_picker_header_footer, null);
+        if (mFullScreen) {
+            decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_fullscreen, null);
+        } else if (headerPresentation != null || footerPresentation != null) {
+            decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker_header_footer,
+                    null);
         } else {
-            decor = (ViewGroup) inflater.inflate(
-                    mFullScreen ? R.layout.autofill_dataset_picker_fullscreen
-                            : R.layout.autofill_dataset_picker, null);
+            decor = (ViewGroup) inflater.inflate(R.layout.autofill_dataset_picker, null);
+        }
+        final TextView titleView = decor.findViewById(R.id.autofill_dataset_title);
+        if (titleView != null) {
+            titleView.setText(mContext.getString(R.string.autofill_window_title, serviceLabel));
+        }
+        final ImageView iconView = decor.findViewById(R.id.autofill_dataset_icon);
+        if (iconView != null) {
+            iconView.setImageDrawable(serviceIcon);
         }
 
-        // if autofill ui is not fullscreen, send unhandled keyevent to app window.
-        if (!mFullScreen) {
-            if (decor instanceof AutofillFrameLayout) {
-                ((AutofillFrameLayout) decor).mUnhandledListener =
-                        (View view, int keyCode, KeyEvent event) -> {
-                            switch (keyCode) {
-                                case KeyEvent.KEYCODE_BACK:
-                                case KeyEvent.KEYCODE_ESCAPE:
-                                case KeyEvent.KEYCODE_ENTER:
-                                case KeyEvent.KEYCODE_DPAD_CENTER:
-                                case KeyEvent.KEYCODE_DPAD_LEFT:
-                                case KeyEvent.KEYCODE_DPAD_UP:
-                                case KeyEvent.KEYCODE_DPAD_RIGHT:
-                                case KeyEvent.KEYCODE_DPAD_DOWN:
-                                    return false;
-                                default:
-                                    mCallback.dispatchUnhandledKey(event);
-                                    return true;
-                            }
-                        };
-            } else {
-                Slog.wtf(TAG, "Unable to send unhandled key");
+        // In full screen we only initialize size once assuming screen size never changes
+        if (mFullScreen) {
+            final Point outPoint = mTempPoint;
+            mContext.getDisplay().getSize(outPoint);
+            // full with of screen and half height of screen
+            mContentWidth = LayoutParams.MATCH_PARENT;
+            mContentHeight = outPoint.y / 2;
+            if (sVerbose) {
+                Slog.v(TAG, "initialized fillscreen LayoutParams "
+                        + mContentWidth + "," + mContentHeight);
             }
         }
 
+        // Send unhandled keyevent to app window.
+        decor.addOnUnhandledKeyEventListener((View view, KeyEvent event) -> {
+            switch (event.getKeyCode() ) {
+                case KeyEvent.KEYCODE_BACK:
+                case KeyEvent.KEYCODE_ESCAPE:
+                case KeyEvent.KEYCODE_ENTER:
+                case KeyEvent.KEYCODE_DPAD_CENTER:
+                case KeyEvent.KEYCODE_DPAD_LEFT:
+                case KeyEvent.KEYCODE_DPAD_UP:
+                case KeyEvent.KEYCODE_DPAD_RIGHT:
+                case KeyEvent.KEYCODE_DPAD_DOWN:
+                    return false;
+                default:
+                    mCallback.dispatchUnhandledKey(event);
+                    return true;
+            }
+        });
+
         if (sVisibleDatasetsMaxCount > 0) {
             mVisibleDatasetsMaxCount = sVisibleDatasetsMaxCount;
             if (sVerbose) {
@@ -218,14 +215,12 @@
             mFooter = null;
             mAdapter = null;
 
-            // insert authentication item under autofill_dataset_container or decor
-            ViewGroup container = decor.findViewById(R.id.autofill_dataset_container);
-            if (container == null) {
-                container = decor;
-            }
+            // insert authentication item under autofill_dataset_picker
+            ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
             final View content;
             try {
-                content = response.getPresentation().apply(context, decor, interceptionHandler);
+                response.getPresentation().setApplyTheme(THEME_ID);
+                content = response.getPresentation().apply(mContext, decor, interceptionHandler);
                 container.addView(content);
             } catch (RuntimeException e) {
                 callback.onCanceled();
@@ -236,20 +231,22 @@
             decor.setFocusable(true);
             decor.setOnClickListener(v -> mCallback.onResponsePicked(response));
 
-            final Point maxSize = mTempPoint;
-            resolveMaxWindowSize(context, maxSize);
-            // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
-            content.getLayoutParams().width = mFullScreen ? maxSize.x
-                    : ViewGroup.LayoutParams.WRAP_CONTENT;
-            content.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
-            final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.x,
-                    MeasureSpec.AT_MOST);
-            final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
-                    MeasureSpec.AT_MOST);
+            if (!mFullScreen) {
+                final Point maxSize = mTempPoint;
+                resolveMaxWindowSize(mContext, maxSize);
+                // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
+                content.getLayoutParams().width = mFullScreen ? maxSize.x
+                        : ViewGroup.LayoutParams.WRAP_CONTENT;
+                content.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
+                final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.x,
+                        MeasureSpec.AT_MOST);
+                final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
+                        MeasureSpec.AT_MOST);
 
-            decor.measure(widthMeasureSpec, heightMeasureSpec);
-            mContentWidth = content.getMeasuredWidth();
-            mContentHeight = content.getMeasuredHeight();
+                decor.measure(widthMeasureSpec, heightMeasureSpec);
+                mContentWidth = content.getMeasuredWidth();
+                mContentHeight = content.getMeasuredHeight();
+            }
 
             mWindow = new AnchoredWindow(decor, overlayControl);
             requestShowFillUi();
@@ -263,7 +260,8 @@
             RemoteViews.OnClickHandler clickBlocker = null;
             if (headerPresentation != null) {
                 clickBlocker = newClickBlocker();
-                mHeader = headerPresentation.apply(context, null, clickBlocker);
+                headerPresentation.setApplyTheme(THEME_ID);
+                mHeader = headerPresentation.apply(mContext, null, clickBlocker);
                 final LinearLayout headerContainer =
                         decor.findViewById(R.id.autofill_dataset_header);
                 if (sVerbose) Slog.v(TAG, "adding header");
@@ -274,15 +272,21 @@
             }
 
             if (footerPresentation != null) {
-                if (clickBlocker == null) { // already set for header
-                    clickBlocker = newClickBlocker();
-                }
-                mFooter = footerPresentation.apply(context, null, clickBlocker);
                 final LinearLayout footerContainer =
                         decor.findViewById(R.id.autofill_dataset_footer);
-                if (sVerbose) Slog.v(TAG, "adding footer");
-                footerContainer.addView(mFooter);
-                footerContainer.setVisibility(View.VISIBLE);
+                if (footerContainer != null) {
+                    if (clickBlocker == null) { // already set for header
+                        clickBlocker = newClickBlocker();
+                    }
+                    footerPresentation.setApplyTheme(THEME_ID);
+                    mFooter = footerPresentation.apply(mContext, null, clickBlocker);
+                    // Footer not supported on some platform e.g. TV
+                    if (sVerbose) Slog.v(TAG, "adding footer");
+                    footerContainer.addView(mFooter);
+                    footerContainer.setVisibility(View.VISIBLE);
+                } else {
+                    mFooter = null;
+                }
             } else {
                 mFooter = null;
             }
@@ -301,7 +305,8 @@
                     final View view;
                     try {
                         if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
-                        view = presentation.apply(context, null, interceptionHandler);
+                        presentation.setApplyTheme(THEME_ID);
+                        view = presentation.apply(mContext, null, interceptionHandler);
                     } catch (RuntimeException e) {
                         Slog.e(TAG, "Error inflating remote views", e);
                         continue;
@@ -352,12 +357,7 @@
     }
 
     void requestShowFillUi() {
-        if (mFullScreen) {
-            mCallback.requestShowFillUi(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
-                    mWindowPresenter);
-        } else {
-            mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
-        }
+        mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
     }
 
     /**
@@ -388,12 +388,6 @@
                 mCallback.requestHideFillUi();
             } else {
                 if (updateContentSize()) {
-                    if (mFullScreen) {
-                        LayoutParams lp = mListView.getLayoutParams();
-                        lp.width = mContentWidth;
-                        lp.height = mContentHeight;
-                        mListView.setLayoutParams(lp);
-                    }
                     requestShowFillUi();
                 }
                 if (mAdapter.getCount() > mVisibleDatasetsMaxCount) {
@@ -452,6 +446,10 @@
         if (mAdapter == null) {
             return false;
         }
+        if (mFullScreen) {
+            // always request show fill window with fixed size for fullscreen
+            return true;
+        }
         boolean changed = false;
         if (mAdapter.getCount() <= 0) {
             if (mContentWidth != 0) {
@@ -476,11 +474,6 @@
         final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxSize.y,
                 MeasureSpec.AT_MOST);
         final int itemCount = mAdapter.getCount();
-        if (mFullScreen) {
-            // fullScreen mode occupy the full width defined by autofill_dataset_picker_max_width
-            changed = true;
-            mContentWidth = maxSize.x;
-        }
 
         if (mHeader != null) {
             mHeader.measure(widthMeasureSpec, heightMeasureSpec);
@@ -491,20 +484,9 @@
         for (int i = 0; i < itemCount; i++) {
             final View view = mAdapter.getItem(i).view;
             view.measure(widthMeasureSpec, heightMeasureSpec);
-            if (mFullScreen) {
-                // for fullscreen, add up all children height until hit max height.
-                final int newContentHeight = mContentHeight + view.getMeasuredHeight();
-                final int clampedNewHeight = Math.min(newContentHeight, maxSize.y);
-                if (clampedNewHeight != mContentHeight) {
-                    mContentHeight = clampedNewHeight;
-                } else if (view.getMeasuredHeight() > 0) {
-                    break;
-                }
-            } else {
-                changed |= updateWidth(view, maxSize);
-                if (i < mVisibleDatasetsMaxCount) {
-                    changed |= updateHeight(view, maxSize);
-                }
+            changed |= updateWidth(view, maxSize);
+            if (i < mVisibleDatasetsMaxCount) {
+                changed |= updateHeight(view, maxSize);
             }
         }
 
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 f96fa7c2..80903c1 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -42,6 +42,7 @@
 import android.util.ArraySet;
 import android.util.Pair;
 import android.util.Slog;
+import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -70,6 +71,9 @@
 
     private static final String TAG = "AutofillSaveUi";
 
+    private static final int THEME_ID =
+            com.android.internal.R.style.Theme_DeviceDefault_Autofill_Save;
+
     public interface OnSaveListener {
         void onSave();
         void onCancel(IntentSender listener);
@@ -144,6 +148,7 @@
         mServicePackageName = servicePackageName;
         mPackageName = packageName;
 
+        context = new ContextThemeWrapper(context, THEME_ID);
         final LayoutInflater inflater = LayoutInflater.from(context);
         final View view = inflater.inflate(R.layout.autofill_save, null);
 
@@ -222,7 +227,7 @@
         final View yesButton = view.findViewById(R.id.autofill_save_yes);
         yesButton.setOnClickListener((v) -> mListener.onSave());
 
-        mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel);
+        mDialog = new Dialog(context, THEME_ID);
         mDialog.setContentView(view);
 
         // Dialog can be dismissed when touched outside, but the negative listener should not be
@@ -309,6 +314,7 @@
 
         try {
             // Create the remote view peer.
+            template.setApplyTheme(THEME_ID);
             final View customSubtitleView = template.apply(context, null, handler);
 
             // And apply batch updates (if any).
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index b860191..d818bd6 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -39,6 +39,7 @@
 import android.os.ServiceManager;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManagerInternal;
@@ -77,14 +78,24 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
+import static android.app.AppOpsManager.UID_STATE_CACHED;
+import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
+import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
+import static android.app.AppOpsManager._NUM_UID_STATE;
+import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
+import static android.app.AppOpsManager.UID_STATE_TOP;
+
 public class AppOpsService extends IAppOpsService.Stub {
     static final String TAG = "AppOps";
     static final boolean DEBUG = false;
@@ -100,6 +111,64 @@
     // Constant meaning that any UID should be matched when dispatching callbacks
     private static final int UID_ANY = -2;
 
+    // Map from process states to the uid states we track.
+    private static final int[] PROCESS_STATE_TO_UID_STATE = new int[] {
+        UID_STATE_PERSISTENT,           // ActivityManager.PROCESS_STATE_PERSISTENT
+        UID_STATE_PERSISTENT,           // ActivityManager.PROCESS_STATE_PERSISTENT_UI
+        UID_STATE_TOP,                  // ActivityManager.PROCESS_STATE_TOP
+        UID_STATE_FOREGROUND_SERVICE,   // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+        UID_STATE_FOREGROUND,           // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
+        UID_STATE_FOREGROUND,           // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+        UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+        UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
+        UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_BACKUP
+        UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_SERVICE
+        UID_STATE_BACKGROUND,           // ActivityManager.PROCESS_STATE_RECEIVER
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_TOP_SLEEPING
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_HOME
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_CACHED_RECENT
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+        UID_STATE_CACHED,               // ActivityManager.PROCESS_STATE_NONEXISTENT
+    };
+
+    static final String[] UID_STATE_NAMES = new String[] {
+            "pers ",    // UID_STATE_PERSISTENT
+            "top  ",    // UID_STATE_TOP
+            "fgsvc",    // UID_STATE_FOREGROUND_SERVICE
+            "fg   ",    // UID_STATE_FOREGROUND
+            "bg   ",    // UID_STATE_BACKGROUND
+            "cch  ",    // UID_STATE_CACHED
+    };
+
+    static final String[] UID_STATE_TIME_ATTRS = new String[] {
+            "tp",       // UID_STATE_PERSISTENT
+            "tt",       // UID_STATE_TOP
+            "tfs",      // UID_STATE_FOREGROUND_SERVICE
+            "tf",       // UID_STATE_FOREGROUND
+            "tb",       // UID_STATE_BACKGROUND
+            "tc",       // UID_STATE_CACHED
+    };
+
+    static final String[] UID_STATE_REJECT_ATTRS = new String[] {
+            "rp",       // UID_STATE_PERSISTENT
+            "rt",       // UID_STATE_TOP
+            "rfs",      // UID_STATE_FOREGROUND_SERVICE
+            "rf",       // UID_STATE_FOREGROUND
+            "rb",       // UID_STATE_BACKGROUND
+            "rc",       // UID_STATE_CACHED
+    };
+
+    static final String[] MODE_NAMES = new String[] {
+            "allow",        // MODE_ALLOWED
+            "ignore",       // MODE_IGNORED
+            "deny",         // MODE_ERRORED
+            "default",      // MODE_DEFAULT
+    };
+
     Context mContext;
     final AtomicFile mFile;
     final Handler mHandler;
@@ -133,6 +202,8 @@
     @VisibleForTesting
     static final class UidState {
         public final int uid;
+        public int state = UID_STATE_CACHED;
+        public int startNesting;
         public ArrayMap<String, Ops> pkgOps;
         public SparseIntArray opModes;
 
@@ -151,36 +222,51 @@
         }
     }
 
-    public final static class Ops extends SparseArray<Op> {
-        public final String packageName;
-        public final UidState uidState;
-        public final boolean isPrivileged;
+    final static class Ops extends SparseArray<Op> {
+        final String packageName;
+        final UidState uidState;
+        final boolean isPrivileged;
 
-        public Ops(String _packageName, UidState _uidState, boolean _isPrivileged) {
+        Ops(String _packageName, UidState _uidState, boolean _isPrivileged) {
             packageName = _packageName;
             uidState = _uidState;
             isPrivileged = _isPrivileged;
         }
     }
 
-    public final static class Op {
-        public final int uid;
-        public final String packageName;
-        public int proxyUid = -1;
-        public String proxyPackageName;
-        public final int op;
-        public int mode;
-        public int duration;
-        public long time;
-        public long rejectTime;
-        public int nesting;
+    final static class Op {
+        final UidState uidState;
+        final int uid;
+        final String packageName;
+        final int op;
+        int proxyUid = -1;
+        String proxyPackageName;
+        int mode;
+        int duration;
+        long time[] = new long[_NUM_UID_STATE];
+        long rejectTime[] = new long[_NUM_UID_STATE];
+        int startNesting;
+        long startRealtime;
 
-        public Op(int _uid, String _packageName, int _op) {
-            uid = _uid;
+        Op(UidState _uidState, String _packageName, int _op) {
+            uidState = _uidState;
+            uid = _uidState.uid;
             packageName = _packageName;
             op = _op;
             mode = AppOpsManager.opToDefaultMode(op);
         }
+
+        boolean hasAnyTime() {
+            for (int i = 0; i < AppOpsManager._NUM_UID_STATE; i++) {
+                if (time[i] != 0) {
+                    return true;
+                }
+                if (rejectTime[i] != 0) {
+                    return true;
+                }
+            }
+            return false;
+        }
     }
 
     final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>();
@@ -189,13 +275,13 @@
     final ArrayMap<IBinder, SparseArray<ActiveCallback>> mActiveWatchers = new ArrayMap<>();
     final SparseArray<SparseArray<Restriction>> mAudioRestrictions = new SparseArray<>();
 
-    public final class ModeCallback implements DeathRecipient {
+    final class ModeCallback implements DeathRecipient {
         final IAppOpsCallback mCallback;
         final int mWatchingUid;
         final int mCallingUid;
         final int mCallingPid;
 
-        public ModeCallback(IAppOpsCallback callback, int watchingUid, int callingUid,
+        ModeCallback(IAppOpsCallback callback, int watchingUid, int callingUid,
                 int callingPid) {
             mCallback = callback;
             mWatchingUid = watchingUid;
@@ -222,7 +308,7 @@
             return sb.toString();
         }
 
-        public void unlinkToDeath() {
+        void unlinkToDeath() {
             mCallback.asBinder().unlinkToDeath(this, 0);
         }
 
@@ -232,13 +318,13 @@
         }
     }
 
-    public final class ActiveCallback implements DeathRecipient {
+    final class ActiveCallback implements DeathRecipient {
         final IAppOpsActiveCallback mCallback;
         final int mWatchingUid;
         final int mCallingUid;
         final int mCallingPid;
 
-        public ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid,
+        ActiveCallback(IAppOpsActiveCallback callback, int watchingUid, int callingUid,
                 int callingPid) {
             mCallback = callback;
             mWatchingUid = watchingUid;
@@ -265,7 +351,7 @@
             return sb.toString();
         }
 
-        public void destroy() {
+        void destroy() {
             mCallback.asBinder().unlinkToDeath(this, 0);
         }
 
@@ -277,12 +363,12 @@
 
     final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<>();
 
-    public final class ClientState extends Binder implements DeathRecipient {
+    final class ClientState extends Binder implements DeathRecipient {
         final ArrayList<Op> mStartedOps = new ArrayList<>();
         final IBinder mAppToken;
         final int mPid;
 
-        public ClientState(IBinder appToken) {
+        ClientState(IBinder appToken) {
             mAppToken = appToken;
             mPid = Binder.getCallingPid();
             // Watch only for remote processes dying
@@ -453,7 +539,7 @@
                     if (uid == op.uid && packageName.equals(op.packageName)) {
                         finishOperationLocked(op, /*finishNested*/ true);
                         client.mStartedOps.remove(j);
-                        if (op.nesting <= 0) {
+                        if (op.startNesting <= 0) {
                             scheduleOpActiveChangedIfNeededLocked(op.op,
                                     uid, packageName, false);
                         }
@@ -485,6 +571,31 @@
         }
     }
 
+    public void updateUidProcState(int uid, int procState) {
+        synchronized (this) {
+            final UidState uidState = getUidStateLocked(uid, true);
+            final int newState = PROCESS_STATE_TO_UID_STATE[procState];
+            if (uidState != null && uidState.state != newState) {
+                if (uidState.startNesting != 0) {
+                    // There is some actively running operation...  need to find it
+                    // and appropriately update its state.
+                    final long now = System.currentTimeMillis();
+                    for (int i = uidState.pkgOps.size() - 1; i >= 0; i--) {
+                        final Ops ops = uidState.pkgOps.valueAt(i);
+                        for (int j = ops.size() - 1; j >= 0; j--) {
+                            final Op op = ops.valueAt(j);
+                            if (op.startNesting > 0) {
+                                op.time[uidState.state] = now;
+                                op.time[newState] = now;
+                            }
+                        }
+                    }
+                }
+                uidState.state = newState;
+            }
+        }
+    }
+
     public void shutdown() {
         Slog.w(TAG, "Writing app ops before shutdown...");
         boolean doWrite = false;
@@ -501,12 +612,16 @@
 
     private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
         ArrayList<AppOpsManager.OpEntry> resOps = null;
+        final long elapsedNow = SystemClock.elapsedRealtime();
         if (ops == null) {
-            resOps = new ArrayList<AppOpsManager.OpEntry>();
+            resOps = new ArrayList<>();
             for (int j=0; j<pkgOps.size(); j++) {
                 Op curOp = pkgOps.valueAt(j);
+                long duration = curOp.duration == -1
+                        ? (elapsedNow - curOp.startRealtime)
+                        : curOp.duration;
                 resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
-                        curOp.rejectTime, curOp.duration, curOp.proxyUid,
+                        curOp.rejectTime, (int) duration, curOp.proxyUid,
                         curOp.proxyPackageName));
             }
         } else {
@@ -514,10 +629,13 @@
                 Op curOp = pkgOps.get(ops[j]);
                 if (curOp != null) {
                     if (resOps == null) {
-                        resOps = new ArrayList<AppOpsManager.OpEntry>();
+                        resOps = new ArrayList<>();
                     }
+                    long duration = curOp.duration == -1
+                            ? (elapsedNow - curOp.startRealtime)
+                            : curOp.duration;
                     resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
-                            curOp.rejectTime, curOp.duration, curOp.proxyUid,
+                            curOp.rejectTime, (int) duration, curOp.proxyUid,
                             curOp.proxyPackageName));
                 }
             }
@@ -628,7 +746,7 @@
     }
 
     private void pruneOp(Op op, int uid, String packageName) {
-        if (op.time == 0 && op.rejectTime == 0) {
+        if (!op.hasAnyTime()) {
             Ops ops = getOpsRawLocked(uid, packageName, false /* edit */,
                     false /* uidMismatchExpected */);
             if (ops != null) {
@@ -946,7 +1064,7 @@
                                     mOpModeWatchers.get(curOp.op));
                             callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName,
                                     mPackageModeWatchers.get(packageName));
-                            if (curOp.time == 0 && curOp.rejectTime == 0) {
+                            if (!curOp.hasAnyTime()) {
                                 pkgOps.removeAt(j);
                             }
                         }
@@ -1212,24 +1330,25 @@
     private int noteOperationUnchecked(int code, int uid, String packageName,
             int proxyUid, String proxyPackageName) {
         synchronized (this) {
-            Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
+            final Ops ops = getOpsRawLocked(uid, packageName, true /* edit */,
                     false /* uidMismatchExpected */);
             if (ops == null) {
                 if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
                         + " package " + packageName);
                 return AppOpsManager.MODE_ERRORED;
             }
-            Op op = getOpLocked(ops, code, true);
+            final Op op = getOpLocked(ops, code, true);
             if (isOpRestrictedLocked(uid, code, packageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
+            final UidState uidState = ops.uidState;
             if (op.duration == -1) {
                 Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
-                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
+                        + " code " + code + " time=" + op.time[uidState.state]
+                        + " duration=" + op.duration);
             }
             op.duration = 0;
             final int switchCode = AppOpsManager.opToSwitch(code);
-            UidState uidState = ops.uidState;
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
             if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
@@ -1238,7 +1357,7 @@
                     if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + op.mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
-                    op.rejectTime = System.currentTimeMillis();
+                    op.rejectTime[uidState.state] = System.currentTimeMillis();
                     return uidMode;
                 }
             } else {
@@ -1247,14 +1366,14 @@
                     if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + op.mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + packageName);
-                    op.rejectTime = System.currentTimeMillis();
+                    op.rejectTime[uidState.state] = System.currentTimeMillis();
                     return switchOp.mode;
                 }
             }
             if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
                     + " package " + packageName);
-            op.time = System.currentTimeMillis();
-            op.rejectTime = 0;
+            op.time[uidState.state] = System.currentTimeMillis();
+            op.rejectTime[uidState.state] = 0;
             op.proxyUid = proxyUid;
             op.proxyPackageName = proxyPackageName;
             return AppOpsManager.MODE_ALLOWED;
@@ -1323,19 +1442,19 @@
         }
         ClientState client = (ClientState)token;
         synchronized (this) {
-            Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */,
+            final Ops ops = getOpsRawLocked(uid, resolvedPackageName, true /* edit */,
                     false /* uidMismatchExpected */);
             if (ops == null) {
                 if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
                         + " package " + resolvedPackageName);
                 return AppOpsManager.MODE_ERRORED;
             }
-            Op op = getOpLocked(ops, code, true);
+            final Op op = getOpLocked(ops, code, true);
             if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             final int switchCode = AppOpsManager.opToSwitch(code);
-            UidState uidState = ops.uidState;
+            final UidState uidState = ops.uidState;
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
             if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
@@ -1345,7 +1464,7 @@
                     if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + op.mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + resolvedPackageName);
-                    op.rejectTime = System.currentTimeMillis();
+                    op.rejectTime[uidState.state] = System.currentTimeMillis();
                     return uidMode;
                 }
             } else {
@@ -1355,19 +1474,21 @@
                     if (DEBUG) Slog.d(TAG, "startOperation: reject #" + op.mode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
                             + resolvedPackageName);
-                    op.rejectTime = System.currentTimeMillis();
+                    op.rejectTime[uidState.state] = System.currentTimeMillis();
                     return switchOp.mode;
                 }
             }
             if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
                     + " package " + resolvedPackageName);
-            if (op.nesting == 0) {
-                op.time = System.currentTimeMillis();
-                op.rejectTime = 0;
+            if (op.startNesting == 0) {
+                op.startRealtime = SystemClock.elapsedRealtime();
+                op.time[uidState.state] = System.currentTimeMillis();
+                op.rejectTime[uidState.state] = 0;
                 op.duration = -1;
                 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, true);
             }
-            op.nesting++;
+            op.startNesting++;
+            uidState.startNesting++;
             if (client.mStartedOps != null) {
                 client.mStartedOps.add(op);
             }
@@ -1415,7 +1536,7 @@
                 return;
             }
             finishOperationLocked(op, /*finishNested*/ false);
-            if (op.nesting <= 0) {
+            if (op.startNesting <= 0) {
                 scheduleOpActiveChangedIfNeededLocked(code, uid, packageName, false);
             }
         }
@@ -1476,18 +1597,22 @@
     }
 
     void finishOperationLocked(Op op, boolean finishNested) {
-        if (op.nesting <= 1 || finishNested) {
-            if (op.nesting == 1 || finishNested) {
-                op.duration = (int)(System.currentTimeMillis() - op.time);
-                op.time += op.duration;
+        if (op.startNesting <= 1 || finishNested) {
+            if (op.startNesting == 1 || finishNested) {
+                op.duration = (int)(SystemClock.elapsedRealtime() - op.startRealtime);
+                op.time[op.uidState.state] = System.currentTimeMillis();
             } else {
                 Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg "
                         + op.packageName + " code " + op.op + " time=" + op.time
-                        + " duration=" + op.duration + " nesting=" + op.nesting);
+                        + " duration=" + op.duration + " nesting=" + op.startNesting);
             }
-            op.nesting = 0;
+            if (op.startNesting >= 1) {
+                op.uidState.startNesting -= op.startNesting;
+            }
+            op.startNesting = 0;
         } else {
-            op.nesting--;
+            op.startNesting--;
+            op.uidState.startNesting--;
         }
     }
 
@@ -1617,7 +1742,7 @@
             if (!edit) {
                 return null;
             }
-            op = new Op(ops.uidState.uid, ops.packageName, code);
+            op = new Op(ops.uidState, ops.packageName, code);
             ops.put(code, op);
         }
         if (edit) {
@@ -1750,7 +1875,7 @@
                 if (ops != null) {
                     final Op op = ops.get(AppOpsManager.OP_RUN_IN_BACKGROUND);
                     if (op != null && op.mode != AppOpsManager.opToDefaultMode(op.op)) {
-                        final Op copy = new Op(op.uid, op.packageName,
+                        final Op copy = new Op(op.uidState, op.packageName,
                                 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
                         copy.mode = op.mode;
                         ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
@@ -1860,37 +1985,86 @@
 
             String tagName = parser.getName();
             if (tagName.equals("op")) {
-                Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n")));
-                String mode = parser.getAttributeValue(null, "m");
-                if (mode != null) {
-                    op.mode = Integer.parseInt(mode);
-                }
-                String time = parser.getAttributeValue(null, "t");
-                if (time != null) {
-                    op.time = Long.parseLong(time);
-                }
-                time = parser.getAttributeValue(null, "r");
-                if (time != null) {
-                    op.rejectTime = Long.parseLong(time);
-                }
-                String dur = parser.getAttributeValue(null, "d");
-                if (dur != null) {
-                    op.duration = Integer.parseInt(dur);
-                }
-                String proxyUid = parser.getAttributeValue(null, "pu");
-                if (proxyUid != null) {
-                    op.proxyUid = Integer.parseInt(proxyUid);
-                }
-                String proxyPackageName = parser.getAttributeValue(null, "pp");
-                if (proxyPackageName != null) {
-                    op.proxyPackageName = proxyPackageName;
-                }
-
                 UidState uidState = getUidStateLocked(uid, true);
                 if (uidState.pkgOps == null) {
                     uidState.pkgOps = new ArrayMap<>();
                 }
 
+                Op op = new Op(uidState, pkgName,
+                        Integer.parseInt(parser.getAttributeValue(null, "n")));
+
+                for (int i = parser.getAttributeCount()-1; i >= 0; i--) {
+                    final String name = parser.getAttributeName(i);
+                    final String value = parser.getAttributeValue(i);
+                    switch (name) {
+                        case "m":
+                            op.mode = Integer.parseInt(value);
+                            break;
+                        case "d":
+                            op.duration = Integer.parseInt(value);
+                            break;
+                        case "pu":
+                            op.proxyUid = Integer.parseInt(value);
+                            break;
+                        case "pp":
+                            op.proxyPackageName = value;
+                            break;
+                        case "tp":
+                            op.time[AppOpsManager.UID_STATE_PERSISTENT] = Long.parseLong(value);
+                            break;
+                        case "tt":
+                            op.time[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
+                            break;
+                        case "tfs":
+                            op.time[AppOpsManager.UID_STATE_FOREGROUND_SERVICE]
+                                    = Long.parseLong(value);
+                            break;
+                        case "tf":
+                            op.time[AppOpsManager.UID_STATE_FOREGROUND] = Long.parseLong(value);
+                            break;
+                        case "tb":
+                            op.time[AppOpsManager.UID_STATE_BACKGROUND] = Long.parseLong(value);
+                            break;
+                        case "tc":
+                            op.time[AppOpsManager.UID_STATE_CACHED] = Long.parseLong(value);
+                            break;
+                        case "rp":
+                            op.rejectTime[AppOpsManager.UID_STATE_PERSISTENT]
+                                    = Long.parseLong(value);
+                            break;
+                        case "rt":
+                            op.rejectTime[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
+                            break;
+                        case "rfs":
+                            op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND_SERVICE]
+                                    = Long.parseLong(value);
+                            break;
+                        case "rf":
+                            op.rejectTime[AppOpsManager.UID_STATE_FOREGROUND]
+                                    = Long.parseLong(value);
+                            break;
+                        case "rb":
+                            op.rejectTime[AppOpsManager.UID_STATE_BACKGROUND]
+                                    = Long.parseLong(value);
+                            break;
+                        case "rc":
+                            op.rejectTime[AppOpsManager.UID_STATE_CACHED]
+                                    = Long.parseLong(value);
+                            break;
+                        case "t":
+                            // Backwards compat.
+                            op.time[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
+                            break;
+                        case "r":
+                            // Backwards compat.
+                            op.rejectTime[AppOpsManager.UID_STATE_TOP] = Long.parseLong(value);
+                            break;
+                        default:
+                            Slog.w(TAG, "Unknown attribute in 'op' tag: " + name);
+                            break;
+                    }
+                }
+
                 Ops ops = uidState.pkgOps.get(pkgName);
                 if (ops == null) {
                     ops = new Ops(pkgName, uidState, isPrivileged);
@@ -1977,13 +2151,17 @@
                             if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
                                 out.attribute(null, "m", Integer.toString(op.getMode()));
                             }
-                            long time = op.getTime();
-                            if (time != 0) {
-                                out.attribute(null, "t", Long.toString(time));
-                            }
-                            time = op.getRejectTime();
-                            if (time != 0) {
-                                out.attribute(null, "r", Long.toString(time));
+                            for (int k = 0; k < _NUM_UID_STATE; k++) {
+                                final long time = op.getTimeFor(k);
+                                if (time != 0) {
+                                    out.attribute(null, UID_STATE_TIME_ATTRS[k],
+                                            Long.toString(time));
+                                }
+                                final long rejectTime = op.getRejectTimeFor(k);
+                                if (rejectTime != 0) {
+                                    out.attribute(null, UID_STATE_REJECT_ATTRS[k],
+                                            Long.toString(rejectTime));
+                                }
                             }
                             int dur = op.getDuration();
                             if (dur != 0) {
@@ -2069,15 +2247,10 @@
         }
 
         int strModeToMode(String modeStr, PrintWriter err) {
-            switch (modeStr) {
-                case "allow":
-                    return AppOpsManager.MODE_ALLOWED;
-                case "deny":
-                    return AppOpsManager.MODE_ERRORED;
-                case "ignore":
-                    return AppOpsManager.MODE_IGNORED;
-                case "default":
-                    return AppOpsManager.MODE_DEFAULT;
+            for (int i = MODE_NAMES.length - 1; i >= 0; i--) {
+                if (MODE_NAMES[i].equals(modeStr)) {
+                    return i;
+                }
             }
             try {
                 return Integer.parseInt(modeStr);
@@ -2466,6 +2639,34 @@
         pw.println("  none");
     }
 
+    private void dumpTimesLocked(PrintWriter pw, String firstPrefix, String prefix, long[] times,
+            long now, SimpleDateFormat sdf, Date date) {
+        boolean hasTime = false;
+        for (int i = 0; i < _NUM_UID_STATE; i++) {
+            if (times[i] != 0) {
+                hasTime = true;
+                break;
+            }
+        }
+        if (!hasTime) {
+            return;
+        }
+        boolean first = true;
+        for (int i = 0; i < _NUM_UID_STATE; i++) {
+            if (times[i] != 0) {
+                pw.print(first ? firstPrefix : prefix);
+                first = false;
+                pw.print(UID_STATE_NAMES[i]);
+                pw.print(" = ");
+                date.setTime(times[i]);
+                pw.print(sdf.format(date));
+                pw.print(" (");
+                TimeUtils.formatDuration(times[i]-now, pw);
+                pw.println(")");
+            }
+        }
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
@@ -2491,6 +2692,9 @@
         synchronized (this) {
             pw.println("Current AppOps Service state:");
             final long now = System.currentTimeMillis();
+            final long nowElapsed = SystemClock.elapsedRealtime();
+            final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+            final Date date = new Date();
             boolean needSep = false;
             if (mOpModeWatchers.size() > 0) {
                 needSep = true;
@@ -2585,7 +2789,7 @@
                         pw.print("    "); pw.print(op);
                         pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage));
                         Restriction r = restrictions.valueAt(i);
-                        pw.print(": mode="); pw.println(r.mode);
+                        pw.print(": mode="); pw.println(MODE_NAMES[r.mode]);
                         if (!r.exceptionPackages.isEmpty()) {
                             pw.println("      Exceptions:");
                             for (int j=0; j<r.exceptionPackages.size(); j++) {
@@ -2602,6 +2806,12 @@
                 UidState uidState = mUidStates.valueAt(i);
 
                 pw.print("  Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
+                pw.print("    state=");
+                pw.println(UID_STATE_NAMES[uidState.state]);
+                if (uidState.startNesting != 0) {
+                    pw.print("    startNesting=");
+                    pw.println(uidState.startNesting);
+                }
                 needSep = true;
 
                 SparseIntArray opModes = uidState.opModes;
@@ -2611,7 +2821,7 @@
                         final int code = opModes.keyAt(j);
                         final int mode = opModes.valueAt(j);
                         pw.print("      "); pw.print(AppOpsManager.opToName(code));
-                        pw.print(": mode="); pw.println(mode);
+                        pw.print(": mode="); pw.println(MODE_NAMES[mode]);
                     }
                 }
 
@@ -2625,21 +2835,26 @@
                     for (int j=0; j<ops.size(); j++) {
                         Op op = ops.valueAt(j);
                         pw.print("      "); pw.print(AppOpsManager.opToName(op.op));
-                        pw.print(": mode="); pw.print(op.mode);
-                        if (op.time != 0) {
-                            pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw);
-                            pw.print(" ago");
-                        }
-                        if (op.rejectTime != 0) {
-                            pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw);
-                            pw.print(" ago");
-                        }
+                        pw.print(" ("); pw.print(MODE_NAMES[op.mode]); pw.println("): ");
+                        dumpTimesLocked(pw,
+                                "          Access: ",
+                                "                  ", op.time, now, sdf, date);
+                        dumpTimesLocked(pw,
+                                "          Reject: ",
+                                "                  ", op.rejectTime, now, sdf, date);
                         if (op.duration == -1) {
-                            pw.print(" (running)");
+                            pw.print("          Running start at: ");
+                            TimeUtils.formatDuration(nowElapsed-op.startRealtime, pw);
+                            pw.println();
                         } else if (op.duration != 0) {
-                            pw.print("; duration="); TimeUtils.formatDuration(op.duration, pw);
+                            pw.print("          duration=");
+                            TimeUtils.formatDuration(op.duration, pw);
+                            pw.println();
                         }
-                        pw.println();
+                        if (op.startNesting != 0) {
+                            pw.print("          startNesting=");
+                            pw.println(op.startNesting);
+                        }
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index ae14dfa..1cd853f 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -56,7 +56,10 @@
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (args != null) {
             for (final String arg : args) {
-                if ("--reset".equals(arg)) {
+                if ("-a".equals(arg)) {
+                    // We currently dump all information by default
+                    continue;
+                } else if ("--reset".equals(arg)) {
                     reset();
                     pw.println("binder_calls_stats reset.");
                     return;
@@ -78,7 +81,6 @@
                     return;
                 } else {
                     pw.println("Unknown option: " + arg);
-                    return;
                 }
             }
         }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 83fe976..59bf2a2 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -351,7 +351,7 @@
             mCallForwarding[i] =  false;
             mCellLocation[i] = new Bundle();
             mCellInfo.add(i, null);
-            mPhysicalChannelConfigs.add(i, null);
+            mPhysicalChannelConfigs.add(i, new ArrayList<PhysicalChannelConfig>());
         }
 
         // Note that location can be null for non-phone builds like
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 83d2bf7..ede870f 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -704,9 +704,11 @@
         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);
         } else if (vib.effect instanceof VibrationEffect.Waveform) {
             VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.effect;
+            waveform = waveform.resolve(mDefaultVibrationAmplitude);
             scaledEffect = waveform.scale(gamma, maxAmplitude);
         } else {
             Slog.w(TAG, "Unable to apply intensity scaling, unknown VibrationEffect type");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5d34f80..ac06ddd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -22929,6 +22929,7 @@
 
     private void noteUidProcessState(final int uid, final int state) {
         mBatteryStatsService.noteUidProcessState(uid, state);
+        mAppOpsService.updateUidProcState(uid, state);
         if (mTrackingAssociations) {
             for (int i1=0, N1=mAssociations.size(); i1<N1; i1++) {
                 ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> targetComponents
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index 676f0c7..1149e87 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -23,6 +23,7 @@
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
+import android.os.UserManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
@@ -59,11 +60,14 @@
         View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
             null);
 
-        FileDescriptor fileDescriptor = UserManagerService.getInstance()
-                .getUserIcon(mNewUser.id).getFileDescriptor();
-        Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
-        ((ImageView) view.findViewById(R.id.user_loading_avatar))
-            .setImageBitmap(bitmap);
+        UserManager userManager =
+                (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+        Bitmap bitmap = userManager.getUserIcon(mNewUser.id);
+        if (bitmap != null) {
+            ((ImageView) view.findViewById(R.id.user_loading_avatar))
+                    .setImageBitmap(bitmap);
+        }
+
         ((TextView) view.findViewById(R.id.user_loading))
             .setText(res.getString(R.string.car_loading_profile));
         setView(view);
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 550c37a..483fec6 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -219,6 +219,9 @@
     }
 
     public void unregisterCancelListenerLocked(IResultReceiver receiver) {
+        if (mCancelCallbacks == null) {
+            return; // Already unregistered or detached.
+        }
         mCancelCallbacks.unregister(receiver);
         if (mCancelCallbacks.getRegisteredCallbackCount() <= 0) {
             mCancelCallbacks = null;
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index c83bacb..06a3078 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -22,8 +22,10 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -1255,7 +1257,8 @@
         for (int i = 0; i < recentsCount; i++) {
             final TaskRecord tr = mTasks.get(i);
             if (task != tr) {
-                if (!task.hasCompatibleActivityType(tr) || task.userId != tr.userId) {
+                if (!hasCompatibleActivityTypeAndWindowingMode(task, tr)
+                        || task.userId != tr.userId) {
                     continue;
                 }
                 final Intent trIntent = tr.intent;
@@ -1547,4 +1550,29 @@
 
         return rti;
     }
+
+    /**
+     * @return Whether the activity types and windowing modes of the two tasks are considered
+     *         compatible. This is necessary because we currently don't persist the activity type
+     *         or the windowing mode with the task, so they can be undefined when restored.
+     */
+    private boolean hasCompatibleActivityTypeAndWindowingMode(TaskRecord t1, TaskRecord t2) {
+        final int activityType = t1.getActivityType();
+        final int windowingMode = t1.getWindowingMode();
+        final boolean isUndefinedType = activityType == ACTIVITY_TYPE_UNDEFINED;
+        final boolean isUndefinedMode = windowingMode == WINDOWING_MODE_UNDEFINED;
+        final int otherActivityType = t2.getActivityType();
+        final int otherWindowingMode = t2.getWindowingMode();
+        final boolean isOtherUndefinedType = otherActivityType == ACTIVITY_TYPE_UNDEFINED;
+        final boolean isOtherUndefinedMode = otherWindowingMode == WINDOWING_MODE_UNDEFINED;
+
+        // An activity type and windowing mode is compatible if they are the exact same type/mode,
+        // or if one of the type/modes is undefined
+        final boolean isCompatibleType = activityType == otherActivityType
+                || isUndefinedType || isOtherUndefinedType;
+        final boolean isCompatibleMode = windowingMode == otherWindowingMode
+                || isUndefinedMode || isOtherUndefinedMode;
+
+        return isCompatibleType && isCompatibleMode;
+    }
 }
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index b14f5b6..b5047ae 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -101,9 +101,7 @@
                         : ACTIVITY_TYPE_HOME;
         final ActivityStack targetStack = mDefaultDisplay.getStack(WINDOWING_MODE_UNDEFINED,
                 mTargetActivityType);
-        ActivityRecord targetActivity = targetStack != null
-                ? targetStack.getTopActivity()
-                : null;
+        ActivityRecord targetActivity = getTargetActivity(targetStack, intent.getComponent());
         final boolean hasExistingActivity = targetActivity != null;
         if (hasExistingActivity) {
             final ActivityDisplay display = targetActivity.getDisplay();
@@ -149,6 +147,14 @@
                 display.moveStackBehindBottomMostVisibleStack(targetStack);
                 if (DEBUG) Slog.d(TAG, "Moved stack=" + targetStack + " behind stack="
                             + display.getStackAbove(targetStack));
+
+                // If there are multiple tasks in the target stack (ie. the home stack, with 3p
+                // and default launchers coexisting), then move the task to the top as a part of
+                // moving the stack to the front
+                if (targetStack.topTask() != targetActivity.getTask()) {
+                    targetStack.addTask(targetActivity.getTask(), true /* toTop */,
+                            "startRecentsActivity");
+                }
             } else {
                 // No recents activity
                 ActivityOptions options = ActivityOptions.makeBasic();
@@ -332,4 +338,22 @@
         }
         return null;
     }
+
+    /**
+     * @return the top activity in the {@param targetStack} matching the {@param component}, or just
+     * the top activity of the top task if no task matches the component.
+     */
+    private ActivityRecord getTargetActivity(ActivityStack targetStack, ComponentName component) {
+        if (targetStack == null) {
+            return null;
+        }
+
+        for (int i = targetStack.getChildCount() - 1; i >= 0; i--) {
+            final TaskRecord task = (TaskRecord) targetStack.getChildAt(i);
+            if (task.getBaseIntent().getComponent().equals(component)) {
+                return task.getTopActivity();
+            }
+        }
+        return targetStack.getTopActivity();
+    }
 }
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index f74ac47..5db20b0 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -621,7 +621,7 @@
 
     private boolean clipboardAccessAllowed(int op, String callingPackage, int callingUid) {
         // Check the AppOp.
-        if (mAppOps.checkOp(op, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
+        if (mAppOps.noteOp(op, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
             return false;
         }
         try {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 312b21c..03046b6 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -818,37 +818,7 @@
             }
         };
 
-        mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) {
-            @Override
-            public boolean isAvailableInPlatform() {
-                return native_is_measurement_supported();
-            }
-
-            @Override
-            protected int registerWithService() {
-                int devOptions = Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED , 0);
-                int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(),
-                        Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING , 0);
-                boolean result = false;
-                if (devOptions == 1 /* Developer Mode enabled */
-                        && fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */) {
-                    result =  native_start_measurement_collection(true /* enableFullTracking */);
-                } else {
-                    result =  native_start_measurement_collection(false /* enableFullTracking */);
-                }
-                if (result) {
-                    return RemoteListenerHelper.RESULT_SUCCESS;
-                } else {
-                    return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
-                }
-            }
-
-            @Override
-            protected void unregisterFromService() {
-                native_stop_measurement_collection();
-            }
-
+        mGnssMeasurementsProvider = new GnssMeasurementsProvider(mContext, mHandler) {
             @Override
             protected boolean isGpsEnabled() {
                 return isEnabled();
@@ -1032,7 +1002,7 @@
                 Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
         }
     }
-    
+
     private void handleRequestLocation(boolean independentFromGnss) {
         if (isRequestLocationRateLimited()) {
             if (DEBUG) {
@@ -2790,13 +2760,6 @@
     private native void native_update_network_state(boolean connected, int type,
             boolean roaming, boolean available, String extraInfo, String defaultAPN);
 
-    // Gps Hal measurements support.
-    private static native boolean native_is_measurement_supported();
-
-    private native boolean native_start_measurement_collection(boolean enableFullTracking);
-
-    private native boolean native_stop_measurement_collection();
-
     // Gps Navigation message support.
     private static native boolean native_is_navigation_message_supported();
 
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index 477dae6..0add863 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -16,12 +16,16 @@
 
 package com.android.server.location;
 
+import android.content.Context;
 import android.location.GnssMeasurementsEvent;
 import android.location.IGnssMeasurementsListener;
 import android.os.Handler;
 import android.os.RemoteException;
+import android.provider.Settings;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * An base implementation for GPS measurements provider.
  * It abstracts out the responsibility of handling listeners, while still allowing technology
@@ -29,22 +33,73 @@
  *
  * @hide
  */
-public abstract class GnssMeasurementsProvider
-        extends RemoteListenerHelper<IGnssMeasurementsListener> {
+public abstract class GnssMeasurementsProvider extends
+        RemoteListenerHelper<IGnssMeasurementsListener> {
     private static final String TAG = "GnssMeasurementsProvider";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
-    protected GnssMeasurementsProvider(Handler handler) {
+    private final Context mContext;
+    private final GnssMeasurementProviderNative mNative;
+
+    private boolean mIsCollectionStarted;
+    private boolean mEnableFullTracking;
+
+    protected GnssMeasurementsProvider(Context context, Handler handler) {
+        this(context, handler, new GnssMeasurementProviderNative());
+    }
+
+    @VisibleForTesting
+    GnssMeasurementsProvider(Context context, Handler handler,
+            GnssMeasurementProviderNative aNative) {
         super(handler, TAG);
+        mContext = context;
+        mNative = aNative;
+    }
+
+    // TODO(b/37460011): Use this with death recovery logic.
+    void resumeIfStarted() {
+        if (DEBUG) {
+            Log.d(TAG, "resumeIfStarted");
+        }
+        if (mIsCollectionStarted) {
+            mNative.startMeasurementCollection(mEnableFullTracking);
+        }
+    }
+
+    @Override
+    public boolean isAvailableInPlatform() {
+        return mNative.isMeasurementSupported();
+    }
+
+    @Override
+    protected int registerWithService() {
+        int devOptions = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
+        int fullTrackingToggled = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, 0);
+        boolean enableFullTracking = (devOptions == 1 /* Developer Mode enabled */)
+                && (fullTrackingToggled == 1 /* Raw Measurements Full Tracking enabled */);
+        boolean result = mNative.startMeasurementCollection(enableFullTracking);
+        if (result) {
+            mIsCollectionStarted = true;
+            mEnableFullTracking = enableFullTracking;
+            return RemoteListenerHelper.RESULT_SUCCESS;
+        } else {
+            return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
+        }
+    }
+
+    @Override
+    protected void unregisterFromService() {
+        boolean stopped = mNative.stopMeasurementCollection();
+        if (stopped) {
+            mIsCollectionStarted = false;
+        }
     }
 
     public void onMeasurementsAvailable(final GnssMeasurementsEvent event) {
         ListenerOperation<IGnssMeasurementsListener> operation =
-                new ListenerOperation<IGnssMeasurementsListener>() {
-                    @Override
-                    public void execute(IGnssMeasurementsListener listener) throws RemoteException {
-                        listener.onGnssMeasurementsReceived(event);
-                    }
-                };
+                listener -> listener.onGnssMeasurementsReceived(event);
         foreach(operation);
     }
 
@@ -98,4 +153,25 @@
             listener.onStatusChanged(mStatus);
         }
     }
+
+    @VisibleForTesting
+    static class GnssMeasurementProviderNative {
+        public boolean isMeasurementSupported() {
+            return native_is_measurement_supported();
+        }
+
+        public boolean startMeasurementCollection(boolean enableFullTracking) {
+            return native_start_measurement_collection(enableFullTracking);
+        }
+
+        public boolean stopMeasurementCollection() {
+            return native_stop_measurement_collection();
+        }
+    }
+
+    private static native boolean native_is_measurement_supported();
+
+    private static native boolean native_start_measurement_collection(boolean enableFullTracking);
+
+    private static native boolean native_stop_measurement_collection();
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 50eaa5c..bb1f5c0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4223,6 +4223,11 @@
                     || appId == Process.ROOT_UID) {
                 return false;
             }
+            // Installer gets to see all static libs.
+            if (PackageManager.PERMISSION_GRANTED
+                    == checkUidPermission(Manifest.permission.INSTALL_PACKAGES, uid)) {
+                return false;
+            }
         }
 
         // No package means no static lib as it is always on internal storage
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index a9cdafd..507f0a8 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -155,11 +155,10 @@
         enforceAccess(pkg, uri);
         int user = Binder.getCallingUserHandle().getIdentifier();
         uri = maybeAddUserId(uri, user);
-        getOrCreatePinnedSlice(uri, pkg).pin(pkg, specs, token);
+        String slicePkg = getProviderPkg(uri, user);
+        getOrCreatePinnedSlice(uri, slicePkg).pin(pkg, specs, token);
 
-        Uri finalUri = uri;
         mHandler.post(() -> {
-            String slicePkg = getProviderPkg(finalUri, user);
             if (slicePkg != null && !Objects.equals(pkg, slicePkg)) {
                 mAppUsageStats.reportEvent(slicePkg, user,
                         isAssistant(pkg, user) || isDefaultHomeApp(pkg, user)
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index eab391e..19c5a3d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -922,6 +922,10 @@
      * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
      */
     boolean shouldMagnify() {
+        if (mSurfaceControl == null) {
+            return false;
+        }
+
         for (int i = 0; i < mChildren.size(); i++) {
             if (!mChildren.get(i).shouldMagnify()) {
                 return false;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6c2821d..674414f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4270,6 +4270,24 @@
         }
     }
 
+    private boolean skipDecorCrop() {
+        // The decor frame is used to specify the region not covered by the system
+        // decorations (nav bar, status bar). In case this is empty, for example with
+        // FLAG_TRANSLUCENT_NAVIGATION, we don't need to do any cropping.
+        if (mDecorFrame.isEmpty()) {
+            return true;
+        }
+
+        // But if we have a frame, and are an application window, then we must be cropped.
+        if (mAppToken != null) {
+            return false;
+        }
+
+        // For non application windows, we may be allowed to extend over the decor bars
+        // depending on our type and permissions assosciated with our token.
+        return mToken.canLayerAboveSystemBars();
+    }
+
     /**
      * Calculate the window crop according to system decor policy. In general this is
      * the system decor rect (see #calculateSystemDecorRect), but we also have some
@@ -4287,7 +4305,7 @@
             policyCrop.intersect(-mCompatFrame.left, -mCompatFrame.top,
                     displayInfo.logicalWidth - mCompatFrame.left,
                     displayInfo.logicalHeight - mCompatFrame.top);
-        } else if (mDecorFrame.isEmpty()) {
+        } else if (skipDecorCrop()) {
             // Windows without policy decor aren't cropped.
             policyCrop.set(0, 0, mCompatFrame.width(), mCompatFrame.height());
         } else {
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 14680d9..b97460a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -17,7 +17,7 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
@@ -336,4 +336,16 @@
     boolean okToAnimate() {
         return mDisplayContent != null && mDisplayContent.okToAnimate();
     }
+
+    /**
+     * Return whether windows from this token can layer above the
+     * system bars, or in other words extend outside of the "Decor Frame"
+     */
+    boolean canLayerAboveSystemBars() {
+        int layer = mService.mPolicy.getWindowLayerFromTypeLw(windowType,
+                mOwnerCanManageAppTokens);
+        int navLayer = mService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
+                mOwnerCanManageAppTokens);
+        return mOwnerCanManageAppTokens && (layer > navLayer);
+    }
 }
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 3a9bbe4..b3b37d6 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1799,7 +1799,7 @@
     return JNI_FALSE;
 }
 
-static jboolean android_location_GnssLocationProvider_is_measurement_supported(
+static jboolean android_location_GnssMeasurementsProvider_is_measurement_supported(
     JNIEnv* env, jclass clazz) {
     if (gnssMeasurementIface != nullptr) {
         return JNI_TRUE;
@@ -1808,7 +1808,7 @@
     return JNI_FALSE;
 }
 
-static jboolean android_location_GnssLocationProvider_start_measurement_collection(
+static jboolean android_location_GnssMeasurementsProvider_start_measurement_collection(
         JNIEnv* /* env */,
         jobject /* obj */,
         jboolean enableFullTracking) {
@@ -1842,7 +1842,7 @@
     return JNI_TRUE;
 }
 
-static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
+static jboolean android_location_GnssMeasurementsProvider_stop_measurement_collection(
         JNIEnv* env,
         jobject obj) {
     if (gnssMeasurementIface == nullptr) {
@@ -2178,18 +2178,6 @@
     {"native_update_network_state",
             "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
             reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
-    {"native_is_measurement_supported",
-            "()Z",
-            reinterpret_cast<void *>(
-                    android_location_GnssLocationProvider_is_measurement_supported)},
-    {"native_start_measurement_collection",
-             "(Z)Z",
-            reinterpret_cast<void *>(
-                    android_location_GnssLocationProvider_start_measurement_collection)},
-    {"native_stop_measurement_collection",
-            "()Z",
-            reinterpret_cast<void *>(
-                    android_location_GnssLocationProvider_stop_measurement_collection)},
     {"native_is_navigation_message_supported",
             "()Z",
             reinterpret_cast<void *>(
@@ -2269,6 +2257,22 @@
             reinterpret_cast<void *>(android_location_GnssGeofenceProvider_resume_geofence)},
 };
 
+static const JNINativeMethod sMeasurementMethods[] = {
+     /* name, signature, funcPtr */
+    {"native_is_measurement_supported",
+            "()Z",
+            reinterpret_cast<void *>(
+                    android_location_GnssMeasurementsProvider_is_measurement_supported)},
+    {"native_start_measurement_collection",
+             "(Z)Z",
+            reinterpret_cast<void *>(
+                    android_location_GnssMeasurementsProvider_start_measurement_collection)},
+    {"native_stop_measurement_collection",
+            "()Z",
+            reinterpret_cast<void *>(
+                    android_location_GnssMeasurementsProvider_stop_measurement_collection)},
+};
+
 int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
     jniRegisterNativeMethods(
             env,
@@ -2280,6 +2284,11 @@
             "com/android/server/location/GnssGeofenceProvider",
             sGeofenceMethods,
             NELEM(sGeofenceMethods));
+    jniRegisterNativeMethods(
+            env,
+            "com/android/server/location/GnssMeasurementsProvider",
+            sMeasurementMethods,
+            NELEM(sMeasurementMethods));
     return jniRegisterNativeMethods(
             env,
             "com/android/server/location/GnssLocationProvider",
diff --git a/services/net/java/android/net/dns/ResolvUtil.java b/services/net/java/android/net/dns/ResolvUtil.java
index 97d20f4..a2a6615 100644
--- a/services/net/java/android/net/dns/ResolvUtil.java
+++ b/services/net/java/android/net/dns/ResolvUtil.java
@@ -62,4 +62,13 @@
         final long netidForResolv = NETID_USE_LOCAL_NAMESERVERS | (long) network.netId;
         return new Network((int) netidForResolv);
     }
+
+    public static Network makeNetworkWithPrivateDnsBypass(Network network) {
+        return new Network(network) {
+            @Override
+            public InetAddress[] getAllByName(String host) throws UnknownHostException {
+                return blockingResolveAllLocally(network, host);
+            }
+        };
+    }
 }
diff --git a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
new file mode 100644
index 0000000..23d6cf6
--- /dev/null
+++ b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
@@ -0,0 +1,90 @@
+package com.android.server.location;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+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;
+
+/**
+ * Unit tests for {@link GnssMeasurementsProvider}.
+ */
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(
+        manifest = Config.NONE,
+        sdk = 27
+)
+@SystemLoaderPackages({"com.android.server.location"})
+@Presubmit
+public class GnssMeasurementsProviderTest {
+    @Mock
+    private GnssMeasurementsProvider.GnssMeasurementProviderNative mMockNative;
+    private GnssMeasurementsProvider mTestProvider;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mMockNative.startMeasurementCollection(anyBoolean())).thenReturn(true);
+        when(mMockNative.stopMeasurementCollection()).thenReturn(true);
+
+        mTestProvider = new GnssMeasurementsProvider(RuntimeEnvironment.application,
+                new Handler(Looper.myLooper()), mMockNative) {
+            @Override
+            public boolean isGpsEnabled() {
+                return true;
+            }
+        };
+    }
+
+    @Test
+    public void register_nativeStarted() {
+        mTestProvider.registerWithService();
+        verify(mMockNative).startMeasurementCollection(anyBoolean());
+    }
+
+    @Test
+    public void unregister_nativeStopped() {
+        mTestProvider.registerWithService();
+        mTestProvider.unregisterFromService();
+        verify(mMockNative).stopMeasurementCollection();
+    }
+
+    @Test
+    public void isSupported_nativeIsSupported() {
+        when(mMockNative.isMeasurementSupported()).thenReturn(true);
+        assertThat(mTestProvider.isAvailableInPlatform()).isTrue();
+
+        when(mMockNative.isMeasurementSupported()).thenReturn(false);
+        assertThat(mTestProvider.isAvailableInPlatform()).isFalse();
+    }
+
+    @Test
+    public void register_resume_started() {
+        mTestProvider.registerWithService();
+        mTestProvider.resumeIfStarted();
+        verify(mMockNative, times(2)).startMeasurementCollection(anyBoolean());
+    }
+
+    @Test
+    public void unregister_resume_notStarted() {
+        mTestProvider.registerWithService();
+        mTestProvider.unregisterFromService();
+        mTestProvider.resumeIfStarted();
+        verify(mMockNative, times(1)).startMeasurementCollection(anyBoolean());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 592f7b1..b73ac89 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -21,6 +21,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
@@ -303,6 +304,8 @@
 
     @Test
     public void testAddTaskCompatibleActivityType_expectRemove() throws Exception {
+        // Test with undefined activity type since the type is not persisted by the task persister
+        // and we want to ensure that a new task will match a restored task
         Configuration config1 = new Configuration();
         config1.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
         TaskRecord task1 = createTaskBuilder(".Task1")
@@ -355,6 +358,65 @@
     }
 
     @Test
+    public void testAddTaskCompatibleWindowingMode_expectRemove() throws Exception {
+        Configuration config1 = new Configuration();
+        config1.windowConfiguration.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+        TaskRecord task1 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK)
+                .setStack(mStack)
+                .build();
+        task1.onConfigurationChanged(config1);
+        assertTrue(task1.getWindowingMode() == WINDOWING_MODE_UNDEFINED);
+        mRecentTasks.add(task1);
+        mCallbacksRecorder.clear();
+
+        Configuration config2 = new Configuration();
+        config2.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        TaskRecord task2 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK)
+                .setStack(mStack)
+                .build();
+        task2.onConfigurationChanged(config2);
+        assertTrue(task2.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
+        mRecentTasks.add(task2);
+
+        assertTrue(mCallbacksRecorder.added.size() == 1);
+        assertTrue(mCallbacksRecorder.added.contains(task2));
+        assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+        assertTrue(mCallbacksRecorder.removed.size() == 1);
+        assertTrue(mCallbacksRecorder.removed.contains(task1));
+    }
+
+    @Test
+    public void testAddTaskIncompatibleWindowingMode_expectNoRemove() throws Exception {
+        Configuration config1 = new Configuration();
+        config1.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        TaskRecord task1 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK)
+                .setStack(mStack)
+                .build();
+        task1.onConfigurationChanged(config1);
+        assertTrue(task1.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
+        mRecentTasks.add(task1);
+
+        Configuration config2 = new Configuration();
+        config2.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
+        TaskRecord task2 = createTaskBuilder(".Task1")
+                .setFlags(FLAG_ACTIVITY_NEW_TASK)
+                .setStack(mStack)
+                .build();
+        task2.onConfigurationChanged(config2);
+        assertTrue(task2.getWindowingMode() == WINDOWING_MODE_PINNED);
+        mRecentTasks.add(task2);
+
+        assertTrue(mCallbacksRecorder.added.size() == 2);
+        assertTrue(mCallbacksRecorder.added.contains(task1));
+        assertTrue(mCallbacksRecorder.added.contains(task2));
+        assertTrue(mCallbacksRecorder.trimmed.isEmpty());
+        assertTrue(mCallbacksRecorder.removed.isEmpty());
+    }
+
+    @Test
     public void testUsersTasks() throws Exception {
         mRecentTasks.setOnlyTestVisibleRange();
 
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index d49ba3e..43a4e27 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -93,7 +93,7 @@
 
         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
         mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
-        verify(mService, times(1)).createPinnedSlice(eq(TEST_URI), eq("pkg"));
+        verify(mService, times(1)).createPinnedSlice(eq(TEST_URI), anyString());
     }
 
     @Test
@@ -126,4 +126,4 @@
         verify(mContextSpy).checkPermission(eq("perm2"), eq(Process.myPid()), eq(Process.myUid()));
     }
 
-}
\ No newline at end of file
+}
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 920a605..97c5ac9 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -81,7 +81,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.provider.Settings;
+import android.provider.Settings.Global;
 import android.telephony.TelephonyManager;
 import android.util.ArraySet;
 import android.util.KeyValueListParser;
@@ -1439,8 +1439,10 @@
         boolean isAppIdleEnabled() {
             final boolean buildFlag = mContext.getResources().getBoolean(
                     com.android.internal.R.bool.config_enableAutoPowerModes);
-            final boolean runtimeFlag = Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.APP_STANDBY_ENABLED, 1) == 1;
+            final boolean runtimeFlag = Global.getInt(mContext.getContentResolver(),
+                    Global.APP_STANDBY_ENABLED, 1) == 1
+                    && Global.getInt(mContext.getContentResolver(),
+                    Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED, 1) == 1;
             return buildFlag && runtimeFlag;
         }
 
@@ -1489,8 +1491,8 @@
         }
 
         String getAppIdleSettings() {
-            return Settings.Global.getString(mContext.getContentResolver(),
-                    Settings.Global.APP_IDLE_CONSTANTS);
+            return Global.getString(mContext.getContentResolver(),
+                    Global.APP_IDLE_CONSTANTS);
         }
     }
 
@@ -1610,7 +1612,7 @@
     };
 
     /**
-     * Observe settings changes for {@link Settings.Global#APP_IDLE_CONSTANTS}.
+     * Observe settings changes for {@link Global#APP_IDLE_CONSTANTS}.
      */
     private class SettingsObserver extends ContentObserver {
         /**
@@ -1650,10 +1652,11 @@
         }
 
         void registerObserver() {
-            mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.APP_IDLE_CONSTANTS), false, this);
-            mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.APP_STANDBY_ENABLED), false, this);
+            final ContentResolver cr = mContext.getContentResolver();
+            cr.registerContentObserver(Global.getUriFor(Global.APP_IDLE_CONSTANTS), false, this);
+            cr.registerContentObserver(Global.getUriFor(Global.APP_STANDBY_ENABLED), false, this);
+            cr.registerContentObserver(Global.getUriFor(Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED),
+                    false, this);
         }
 
         @Override
@@ -1665,11 +1668,14 @@
         void updateSettings() {
             if (DEBUG) {
                 Slog.d(TAG,
-                        "appidle=" + Settings.Global.getString(mContext.getContentResolver(),
-                                Settings.Global.APP_STANDBY_ENABLED));
-                Slog.d(TAG, "appidleconstants=" + Settings.Global.getString(
+                        "appidle=" + Global.getString(mContext.getContentResolver(),
+                                Global.APP_STANDBY_ENABLED));
+                Slog.d(TAG,
+                        "adaptivebat=" + Global.getString(mContext.getContentResolver(),
+                                Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED));
+                Slog.d(TAG, "appidleconstants=" + Global.getString(
                         mContext.getContentResolver(),
-                        Settings.Global.APP_IDLE_CONSTANTS));
+                        Global.APP_IDLE_CONSTANTS));
             }
             // Check if app_idle_enabled has changed
             setAppIdleEnabled(mInjector.isAppIdleEnabled());
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index c914689..0dce738 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -16,6 +16,7 @@
 package com.android.server.usage;
 
 import android.app.usage.ConfigurationStats;
+import android.app.usage.EventList;
 import android.app.usage.EventStats;
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
@@ -37,7 +38,7 @@
     public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>();
     public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>();
     public Configuration activeConfiguration;
-    public TimeSparseArray<UsageEvents.Event> events;
+    public EventList events;
 
     // A string cache. This is important as when we're parsing XML files, we don't want to
     // keep hundreds of strings that have the same contents. We will read the string
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index fe3a884..aa832ad 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -22,12 +22,11 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.app.usage.ConfigurationStats;
-import android.app.usage.TimeSparseArray;
+import android.app.usage.EventList;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
 import android.util.ArrayMap;
-import android.util.Pair;
 
 import java.io.IOException;
 import java.net.ProtocolException;
@@ -193,9 +192,9 @@
         }
 
         if (statsOut.events == null) {
-            statsOut.events = new TimeSparseArray<>();
+            statsOut.events = new EventList();
         }
-        statsOut.events.put(event.mTimeStamp, event);
+        statsOut.events.insert(event);
     }
 
     private static void writeUsageStats(XmlSerializer xml, final IntervalStats stats,
@@ -411,7 +410,7 @@
         xml.startTag(null, EVENT_LOG_TAG);
         final int eventCount = stats.events != null ? stats.events.size() : 0;
         for (int i = 0; i < eventCount; i++) {
-            writeEvent(xml, stats, stats.events.valueAt(i));
+            writeEvent(xml, stats, stats.events.get(i));
         }
         xml.endTag(null, EVENT_LOG_TAG);
     }
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index d9fc066..9cb98f3 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -17,15 +17,14 @@
 package com.android.server.usage;
 
 import android.app.usage.ConfigurationStats;
+import android.app.usage.EventList;
 import android.app.usage.EventStats;
-import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.res.Configuration;
 import android.os.SystemClock;
 import android.content.Context;
-import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -174,10 +173,10 @@
 
         // Add the event to the daily list.
         if (currentDailyStats.events == null) {
-            currentDailyStats.events = new TimeSparseArray<>();
+            currentDailyStats.events = new EventList();
         }
         if (event.mEventType != UsageEvents.Event.SYSTEM_INTERACTION) {
-            currentDailyStats.events.put(event.mTimeStamp, event);
+            currentDailyStats.events.insert(event);
         }
 
         boolean incrementAppLaunch = false;
@@ -367,18 +366,14 @@
                             return;
                         }
 
-                        final int startIndex = stats.events.closestIndexOnOrAfter(beginTime);
-                        if (startIndex < 0) {
-                            return;
-                        }
-
+                        final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
                         final int size = stats.events.size();
                         for (int i = startIndex; i < size; i++) {
-                            if (stats.events.keyAt(i) >= endTime) {
+                            if (stats.events.get(i).mTimeStamp >= endTime) {
                                 return;
                             }
 
-                            UsageEvents.Event event = stats.events.valueAt(i);
+                            UsageEvents.Event event = stats.events.get(i);
                             if (obfuscateInstantApps) {
                                 event = event.getObfuscatedIfInstantApp();
                             }
@@ -410,18 +405,14 @@
                         return;
                     }
 
-                    final int startIndex = stats.events.closestIndexOnOrAfter(beginTime);
-                    if (startIndex < 0) {
-                        return;
-                    }
-
+                    final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
                     final int size = stats.events.size();
                     for (int i = startIndex; i < size; i++) {
-                        if (stats.events.keyAt(i) >= endTime) {
+                        if (stats.events.get(i).mTimeStamp >= endTime) {
                             return;
                         }
 
-                        final UsageEvents.Event event = stats.events.valueAt(i);
+                        final UsageEvents.Event event = stats.events.get(i);
                         if (!packageName.equals(event.mPackage)) {
                             continue;
                         }
@@ -633,18 +624,14 @@
                             return;
                         }
 
-                        final int startIndex = stats.events.closestIndexOnOrAfter(beginTime);
-                        if (startIndex < 0) {
-                            return;
-                        }
-
+                        final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
                         final int size = stats.events.size();
                         for (int i = startIndex; i < size; i++) {
-                            if (stats.events.keyAt(i) >= endTime) {
+                            if (stats.events.get(i).mTimeStamp >= endTime) {
                                 return;
                             }
 
-                            UsageEvents.Event event = stats.events.valueAt(i);
+                            UsageEvents.Event event = stats.events.get(i);
                             if (pkg != null && !pkg.equals(event.mPackage)) {
                                 continue;
                             }
@@ -779,10 +766,10 @@
         if (!skipEvents) {
             pw.println("events");
             pw.increaseIndent();
-            final TimeSparseArray<UsageEvents.Event> events = stats.events;
+            final EventList events = stats.events;
             final int eventCount = events != null ? events.size() : 0;
             for (int i = 0; i < eventCount; i++) {
-                final UsageEvents.Event event = events.valueAt(i);
+                final UsageEvents.Event event = events.get(i);
                 if (pkg != null && !pkg.equals(event.mPackage)) {
                     continue;
                 }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 0ff2982..1524c6d 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -578,7 +579,8 @@
      * @param configs List of the current {@link PhysicalChannelConfig}s
      * @hide
      */
-    public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
+    public void onPhysicalChannelConfigurationChanged(
+            @NonNull List<PhysicalChannelConfig> configs) {
         // default implementation empty
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3880f2f..917cfb4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2786,6 +2786,22 @@
     }
 
     /**
+     * Test method to reload the UICC profile.
+     *
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void refreshUiccProfile() {
+        try {
+            ITelephony telephony = getITelephony();
+            telephony.refreshUiccProfile(mSubId);
+        } catch (RemoteException ex) {
+            Rlog.w(TAG, "RemoteException", ex);
+        }
+    }
+
+    /**
      * Map logicalSlot to physicalSlot, and activate the physicalSlot if it is inactive. For
      * example, passing the physicalSlots array [1, 0] means mapping the first item 1, which is
      * physical slot index 1, to the logical slot 0; and mapping the second item 0, which is
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 7e8b2de..27facef 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1509,4 +1509,10 @@
      * A test API to return installed carrier id list version.
      */
     int getCarrierIdListVersion(int subId);
+
+    /**
+     * A test API to reload the UICC profile.
+     * @hide
+     */
+    void refreshUiccProfile(int subId);
 }
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 6f213e1..34b46c5 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -117,8 +117,7 @@
 
 bool Reference::Flatten(android::Res_value* out_value) const {
   const ResourceId resid = id.value_or_default(ResourceId(0));
-  const bool dynamic = resid.is_valid_dynamic() && resid.package_id() != kFrameworkPackageId &&
-                       resid.package_id() < kAppPackageId;
+  const bool dynamic = resid.is_valid_dynamic() && is_dynamic;
 
   if (reference_type == Reference::Type::kResource) {
     if (dynamic) {
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 6371c4c..168ad61 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -157,6 +157,7 @@
   Maybe<ResourceId> id;
   Reference::Type reference_type;
   bool private_reference = false;
+  bool is_dynamic = false;
 
   Reference();
   explicit Reference(const ResourceNameRef& n, Type type = Type::kResource);
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index b90e7b3..0910040 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -129,6 +129,12 @@
   // Stable ID options.
   std::unordered_map<ResourceName, ResourceId> stable_id_map;
   Maybe<std::string> resource_id_map_path;
+
+  // When 'true', allow reserved package IDs to be used for applications. Pre-O, the platform
+  // treats negative resource IDs [those with a package ID of 0x80 or higher] as invalid.
+  // In order to work around this limitation, we allow the use of traditionally reserved
+  // resource IDs [those between 0x02 and 0x7E].
+  bool allow_reserved_package_id = false;
 };
 
 class LinkContext : public IAaptContext {
@@ -899,9 +905,7 @@
     // Capture the shared libraries so that the final resource table can be properly flattened
     // with support for shared libraries.
     for (auto& entry : asset_source->GetAssignedPackageIds()) {
-      if (entry.first > kFrameworkPackageId && entry.first < kAppPackageId) {
-        final_table_.included_packages_[entry.first] = entry.second;
-      } else if (entry.first == kAppPackageId) {
+      if (entry.first == kAppPackageId) {
         // Capture the included base feature package.
         included_feature_base_ = entry.second;
       } else if (entry.first == kFrameworkPackageId) {
@@ -915,6 +919,8 @@
           // android:versionCode from the framework AndroidManifest.xml.
           ExtractCompileSdkVersions(asset_source->GetAssetManager());
         }
+      } else if (asset_source->IsPackageDynamic(entry.first)) {
+        final_table_.included_packages_[entry.first] = entry.second;
       }
     }
 
@@ -1599,7 +1605,15 @@
     // If required, the package name is modifed before flattening, and then modified back
     // to its original name.
     ResourceTablePackage* package_to_rewrite = nullptr;
-    if (context_->GetPackageId() > kAppPackageId &&
+    // Pre-O, the platform treats negative resource IDs [those with a package ID of 0x80
+    // or higher] as invalid. In order to work around this limitation, we allow the use
+    // of traditionally reserved resource IDs [those between 0x02 and 0x7E]. Allow the
+    // definition of what a valid "split" package ID is to account for this.
+    const bool isSplitPackage = (options_.allow_reserved_package_id &&
+          context_->GetPackageId() != kAppPackageId &&
+          context_->GetPackageId() != kFrameworkPackageId)
+        || (!options_.allow_reserved_package_id && context_->GetPackageId() > kAppPackageId);
+    if (isSplitPackage &&
         included_feature_base_ == make_value(context_->GetCompilationPackage())) {
       // The base APK is included, and this is a feature split. If the base package is
       // the same as this package, then we are building an old style Android Instant Apps feature
@@ -2150,6 +2164,10 @@
                         "Generates a text file containing the resource symbols of the R class in\n"
                         "the specified folder.",
                         &options.generate_text_symbols_path)
+          .OptionalSwitch("--allow-reserved-package-id",
+                          "Allows the use of a reserved package ID. This should on be used for\n"
+                          "packages with a pre-O min-sdk\n",
+                          &options.allow_reserved_package_id)
           .OptionalSwitch("--auto-add-overlay",
                           "Allows the addition of new resources in overlays without\n"
                           "<add-resource> tags.",
@@ -2249,7 +2267,9 @@
     }
 
     const uint32_t package_id_int = maybe_package_id_int.value();
-    if (package_id_int < kAppPackageId || package_id_int > std::numeric_limits<uint8_t>::max()) {
+    if (package_id_int > std::numeric_limits<uint8_t>::max()
+        || package_id_int == kFrameworkPackageId
+        || (!options.allow_reserved_package_id && package_id_int < kAppPackageId)) {
       context.GetDiagnostics()->Error(
           DiagMessage() << StringPrintf(
               "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int));
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index 9aaaa69..3a5d585 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -340,6 +340,7 @@
     // against libraries without assigned IDs.
     // Ex: Linking against own resources when building a static library.
     reference->id = s->id;
+    reference->is_dynamic = s->is_dynamic;
     return true;
   }
 
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 2e97a2f..fc4c9b5 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -227,6 +227,10 @@
   return package_map;
 }
 
+bool AssetManagerSymbolSource::IsPackageDynamic(uint32_t packageId) const {
+  return assets_.getResources(false).isPackageDynamic(packageId);
+}
+
 static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable(
     const android::ResTable& table, ResourceId id) {
   // Try as a bag.
@@ -330,6 +334,7 @@
   } else {
     s = util::make_unique<SymbolTable::Symbol>();
     s->id = res_id;
+    s->is_dynamic = table.isResourceDynamic(res_id.id);
   }
 
   if (s) {
@@ -354,7 +359,6 @@
     // Exit early and avoid the error logs from AssetManager.
     return {};
   }
-
   const android::ResTable& table = assets_.getResources(false);
   Maybe<ResourceName> maybe_name = GetResourceName(table, id);
   if (!maybe_name) {
@@ -370,6 +374,7 @@
   } else {
     s = util::make_unique<SymbolTable::Symbol>();
     s->id = id;
+    s->is_dynamic = table.isResourceDynamic(id.id);
   }
 
   if (s) {
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index b676efb..51a2e37 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -68,6 +68,7 @@
     Maybe<ResourceId> id;
     std::shared_ptr<Attribute> attribute;
     bool is_public = false;
+    bool is_dynamic = false;
   };
 
   SymbolTable(NameMangler* mangler);
@@ -192,6 +193,7 @@
 
   bool AddAssetPath(const android::StringPiece& path);
   std::map<size_t, std::string> GetAssignedPackageIds() const;
+  bool IsPackageDynamic(uint32_t packageId) const;
 
   std::unique_ptr<SymbolTable::Symbol> FindByName(
       const ResourceName& name) override;