Merge "Import translations. DO NOT MERGE"
diff --git a/api/removed.txt b/api/removed.txt
index e7b573b..f52b39a 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -73,7 +73,6 @@
     method public deprecated java.lang.String getDeviceInitializerApp();
     method public deprecated android.content.ComponentName getDeviceInitializerComponent();
     method public void setAffiliationIds(android.content.ComponentName, java.util.List<java.lang.String>);
-    field public static final deprecated int FLAG_EVICT_CE_KEY = 1; // 0x1
   }
 
 }
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 15de5c4..9f3970d 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -71,7 +71,6 @@
     method public deprecated android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
     method public deprecated android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
     method public void setAffiliationIds(android.content.ComponentName, java.util.List<java.lang.String>);
-    field public static final deprecated int FLAG_EVICT_CE_KEY = 1; // 0x1
   }
 
 }
diff --git a/api/test-removed.txt b/api/test-removed.txt
index e7b573b..f52b39a 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -73,7 +73,6 @@
     method public deprecated java.lang.String getDeviceInitializerApp();
     method public deprecated android.content.ComponentName getDeviceInitializerComponent();
     method public void setAffiliationIds(android.content.ComponentName, java.util.List<java.lang.String>);
-    field public static final deprecated int FLAG_EVICT_CE_KEY = 1; // 0x1
   }
 
 }
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 588a1bf..b60aed6 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -51,6 +51,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.IUserManager;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
@@ -347,7 +348,7 @@
 
         private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
             @Override
-            public void send(int code, Intent intent, String resolvedType,
+            public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
                 try {
                     mResult.offer(intent, 5, TimeUnit.SECONDS);
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 000420f..5fedc9e 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -84,6 +84,11 @@
 
 int main(int argc, char** argv)
 {
+    // setThreadPoolMaxThreadCount(0) actually tells the kernel it's
+    // not allowed to spawn any additional threads, but we still spawn
+    // a binder thread from userspace when we call startThreadPool().
+    // See b/36066697 for rationale
+    ProcessState::self()->setThreadPoolMaxThreadCount(0);
     ProcessState::self()->startThreadPool();
 
     const char* pname = argv[0];
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6fa0a6d..a8183f2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -976,7 +976,7 @@
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
 
-        if (getApplicationInfo().targetSdkVersion >= O && mActivityInfo.isFixedOrientation()) {
+        if (getApplicationInfo().targetSdkVersion > O && mActivityInfo.isFixedOrientation()) {
             final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
             final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);
             ta.recycle();
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 0dfaf6a..e9ee1386 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -169,7 +169,8 @@
      *  Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions
      *  such as Power Save mode.
      */
-    public abstract void setPendingIntentWhitelistDuration(IIntentSender target, long duration);
+    public abstract void setPendingIntentWhitelistDuration(IIntentSender target,
+            IBinder whitelistToken, long duration);
 
     /**
      * Allow DeviceIdleController to tell us about what apps are whitelisted.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 68021d9..1dcc3e2 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -65,6 +65,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.IStorageManager;
+import android.os.storage.StorageManager;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -375,7 +376,9 @@
         checkMode(mode);
         if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O) {
             if (isCredentialProtectedStorage()
-                    && !getSystemService(UserManager.class).isUserUnlocked() && !isBuggy()) {
+                    && !getSystemService(StorageManager.class).isUserKeyUnlocked(
+                            UserHandle.myUserId())
+                    && !isBuggy()) {
                 throw new IllegalStateException("SharedPreferences in credential encrypted "
                         + "storage are not available until after user is unlocked");
             }
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 68fce75..9552d17 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -562,8 +562,8 @@
     void notifyLockedProfile(int userId);
     void startConfirmDeviceCredentialIntent(in Intent intent, in Bundle options);
     void sendIdleJobTrigger();
-    int sendIntentSender(in IIntentSender target, int code, in Intent intent,
-            in String resolvedType, in IIntentReceiver finishedReceiver,
+    int sendIntentSender(in IIntentSender target, in IBinder whitelistToken, int code,
+            in Intent intent, in String resolvedType, in IIntentReceiver finishedReceiver,
             in String requiredPermission, in Bundle options);
 
 
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index cc7e0fd..1c1883b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -71,6 +71,7 @@
     int getDeletedChannelCount(String pkg, int uid);
     void deleteNotificationChannelGroup(String pkg, String channelGroupId);
     ParceledListSlice getNotificationChannelGroups(String pkg);
+    boolean onlyHasDefaultChannel(String pkg, int uid);
 
     // TODO: Remove this when callers have been migrated to the equivalent
     // INotificationListener method.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 06509ae..4294eab 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -42,8 +42,10 @@
 import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.BadParcelableException;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
@@ -835,6 +837,22 @@
     public ArraySet<PendingIntent> allPendingIntents;
 
     /**
+     * Token identifying the notification that is applying doze/bgcheck whitelisting to the
+     * pending intents inside of it, so only those will get the behavior.
+     *
+     * @hide
+     */
+    static public IBinder whitelistToken;
+
+    /**
+     * Must be set by a process to start associating tokens with Notification objects
+     * coming in to it.  This is set by NotificationManagerService.
+     *
+     * @hide
+     */
+    static public IBinder processWhitelistToken;
+
+    /**
      * {@link #extras} key: this is the title of the notification,
      * as supplied to {@link Builder#setContentTitle(CharSequence)}.
      */
@@ -1823,6 +1841,13 @@
     {
         int version = parcel.readInt();
 
+        whitelistToken = parcel.readStrongBinder();
+        if (whitelistToken == null) {
+            whitelistToken = processWhitelistToken;
+        }
+        // Propagate this token to all pending intents that are unmarshalled from the parcel.
+        parcel.setClassCookie(PendingIntent.class, whitelistToken);
+
         when = parcel.readLong();
         creationTime = parcel.readLong();
         if (parcel.readInt() != 0) {
@@ -1929,6 +1954,7 @@
      * @hide
      */
     public void cloneInto(Notification that, boolean heavy) {
+        that.whitelistToken = this.whitelistToken;
         that.when = this.when;
         that.creationTime = this.creationTime;
         that.mSmallIcon = this.mSmallIcon;
@@ -2158,6 +2184,7 @@
     private void writeToParcelImpl(Parcel parcel, int flags) {
         parcel.writeInt(1);
 
+        parcel.writeStrongBinder(whitelistToken);
         parcel.writeLong(when);
         parcel.writeLong(creationTime);
         if (mSmallIcon == null && icon != 0) {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 704e912..bc7fcf5 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -101,21 +101,11 @@
     /**
      * @hide
      */
-    public static final int USER_LOCKED_ALLOWED = 0x00000040;
-
-    /**
-     * @hide
-     */
     public static final int USER_LOCKED_SHOW_BADGE = 0x00000080;
 
     /**
      * @hide
      */
-    public static final int USER_LOCKED_AUDIO_ATTRIBUTES = 0x00000100;
-
-    /**
-     * @hide
-     */
     public static final int[] LOCKABLE_FIELDS = new int[] {
             USER_LOCKED_PRIORITY,
             USER_LOCKED_VISIBILITY,
@@ -123,9 +113,7 @@
             USER_LOCKED_LIGHTS,
             USER_LOCKED_VIBRATION,
             USER_LOCKED_SOUND,
-            USER_LOCKED_ALLOWED,
             USER_LOCKED_SHOW_BADGE,
-            USER_LOCKED_AUDIO_ATTRIBUTES
     };
 
     private static final int DEFAULT_LIGHT_COLOR = 0;
@@ -273,6 +261,13 @@
     /**
      * @hide
      */
+    public void unlockFields(int field) {
+        mUserLockedFields &= ~field;
+    }
+
+    /**
+     * @hide
+     */
     public void setDeleted(boolean deleted) {
         mDeleted = deleted;
     }
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index dc432af..11d9b5e 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -93,6 +93,7 @@
  */
 public final class PendingIntent implements Parcelable {
     private final IIntentSender mTarget;
+    private IBinder mWhitelistToken;
 
     /** @hide */
     @IntDef(flag = true,
@@ -656,7 +657,7 @@
      *
      */
     public IntentSender getIntentSender() {
-        return new IntentSender(mTarget);
+        return new IntentSender(mTarget, mWhitelistToken);
     }
 
     /**
@@ -870,7 +871,7 @@
                     intent.resolveTypeIfNeeded(context.getContentResolver())
                     : null;
             int res = ActivityManager.getService().sendIntentSender(
-                    mTarget, code, intent, resolvedType,
+                    mTarget, mWhitelistToken, code, intent, resolvedType,
                     onFinished != null
                             ? new FinishedDispatcher(this, onFinished, handler)
                             : null,
@@ -1085,7 +1086,9 @@
             = new Parcelable.Creator<PendingIntent>() {
         public PendingIntent createFromParcel(Parcel in) {
             IBinder target = in.readStrongBinder();
-            return target != null ? new PendingIntent(target) : null;
+            return target != null
+                    ? new PendingIntent(target, in.getClassCookie(PendingIntent.class))
+                    : null;
         }
 
         public PendingIntent[] newArray(int size) {
@@ -1108,31 +1111,39 @@
     }
 
     /**
-     * Convenience function for reading either a Messenger or null pointer from
-     * a Parcel.  You must have previously written the Messenger with
+     * Convenience function for reading either a PendingIntent or null pointer from
+     * a Parcel.  You must have previously written the PendingIntent with
      * {@link #writePendingIntentOrNullToParcel}.
      *
-     * @param in The Parcel containing the written Messenger.
+     * @param in The Parcel containing the written PendingIntent.
      *
-     * @return Returns the Messenger read from the Parcel, or null if null had
+     * @return Returns the PendingIntent read from the Parcel, or null if null had
      * been written.
      */
     @Nullable
     public static PendingIntent readPendingIntentOrNullFromParcel(@NonNull Parcel in) {
         IBinder b = in.readStrongBinder();
-        return b != null ? new PendingIntent(b) : null;
+        return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null;
     }
 
     /*package*/ PendingIntent(IIntentSender target) {
         mTarget = target;
     }
 
-    /*package*/ PendingIntent(IBinder target) {
+    /*package*/ PendingIntent(IBinder target, Object cookie) {
         mTarget = IIntentSender.Stub.asInterface(target);
+        if (cookie != null) {
+            mWhitelistToken = (IBinder)cookie;
+        }
     }
 
     /** @hide */
     public IIntentSender getTarget() {
         return mTarget;
     }
+
+    /** @hide */
+    public IBinder getWhitelistToken() {
+        return mWhitelistToken;
+    }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index d26d7e5..c09b688 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3058,13 +3058,6 @@
      */
     public static final int FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY = 1;
 
-    /**
-     * Instead use {@link #FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY}.
-     * @removed
-     */
-    @Deprecated
-    public static final int FLAG_EVICT_CE_KEY = 1;
-
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag=true, value={FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY})
diff --git a/core/java/android/content/IIntentSender.aidl b/core/java/android/content/IIntentSender.aidl
index 45c62d4..21ea2fe 100644
--- a/core/java/android/content/IIntentSender.aidl
+++ b/core/java/android/content/IIntentSender.aidl
@@ -22,6 +22,6 @@
 
 /** @hide */
 oneway interface IIntentSender {
-    void send(int code, in Intent intent, String resolvedType,
+    void send(int code, in Intent intent, String resolvedType, in IBinder whitelistToken,
             IIntentReceiver finishedReceiver, String requiredPermission, in Bundle options);
 }
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 4adb5b7..0a456b5 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -56,6 +56,7 @@
  */
 public class IntentSender implements Parcelable {
     private final IIntentSender mTarget;
+    IBinder mWhitelistToken;
 
     /**
      * Exception thrown when trying to send through a PendingIntent that
@@ -187,7 +188,7 @@
             String resolvedType = intent != null ?
                     intent.resolveTypeIfNeeded(context.getContentResolver())
                     : null;
-            int res = ActivityManager.getService().sendIntentSender(mTarget,
+            int res = ActivityManager.getService().sendIntentSender(mTarget, mWhitelistToken,
                     code, intent, resolvedType,
                     onFinished != null
                             ? new FinishedDispatcher(this, onFinished, handler)
@@ -365,6 +366,12 @@
     }
 
     /** @hide */
+    public IntentSender(IIntentSender target, IBinder whitelistToken) {
+        mTarget = target;
+        mWhitelistToken = whitelistToken;
+    }
+
+    /** @hide */
     public IntentSender(IBinder target) {
         mTarget = IIntentSender.Stub.asInterface(target);
     }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9a5482a..ca15275 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -157,6 +157,7 @@
             MATCH_DISABLED_COMPONENTS,
             MATCH_DISABLED_UNTIL_USED_COMPONENTS,
             MATCH_INSTANT,
+            MATCH_STATIC_SHARED_LIBRARIES,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
     })
@@ -177,6 +178,7 @@
             MATCH_SYSTEM_ONLY,
             MATCH_UNINSTALLED_PACKAGES,
             MATCH_INSTANT,
+            MATCH_STATIC_SHARED_LIBRARIES,
             GET_DISABLED_COMPONENTS,
             GET_DISABLED_UNTIL_USED_COMPONENTS,
             GET_UNINSTALLED_PACKAGES,
@@ -475,6 +477,16 @@
     public static final int MATCH_EXPLICITLY_VISIBLE_ONLY = 0x02000000;
 
     /**
+     * Internal {@link PackageInfo} flag: include static shared libraries.
+     * Apps that depend on static shared libs can always access the version
+     * of the lib they depend on. System/shell/root can access all shared
+     * libs regardless of dependency but need to explicitly ask for them
+     * via this flag.
+     * @hide
+     */
+    public static final int MATCH_STATIC_SHARED_LIBRARIES = 0x04000000;
+
+    /**
      * Internal flag used to indicate that a system component has done their
      * homework and verified that they correctly handle packages and components
      * that come and go over time. In particular:
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 0b0f048..f33c751 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -103,7 +103,8 @@
     }
 
     /**
-     * Return the number of indices in the array that actually have data.
+     * Returns the number of indices in the array that actually have data. Attributes with a value
+     * of @empty are included, as this is an explicit indicator.
      *
      * @throws RuntimeException if the TypedArray has already been recycled.
      */
@@ -116,7 +117,8 @@
     }
 
     /**
-     * Returns an index in the array that has data.
+     * Returns an index in the array that has data. Attributes with a value of @empty are included,
+     * as this is an explicit indicator.
      *
      * @param at The index you would like to returned, ranging from 0 to
      *           {@link #getIndexCount()}.
@@ -1017,7 +1019,7 @@
      * @param outValue TypedValue object in which to place the attribute's
      *                 data.
      *
-     * @return {@code true} if the value was retrieved, false otherwise.
+     * @return {@code true} if the value was retrieved and not @empty, {@code false} otherwise.
      * @throws RuntimeException if the TypedArray has already been recycled.
      */
     public boolean getValue(@StyleableRes int index, TypedValue outValue) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 5edefb5..dadc5f5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -40,6 +40,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
 import android.provider.Settings;
 import android.telephony.SubscriptionManager;
 import android.util.ArrayMap;
@@ -2695,6 +2696,28 @@
         }
     }
 
+    /**
+     * Constant error codes used by ConnectivityService to communicate about failures and errors
+     * across a Binder boundary.
+     * @hide
+     */
+    public interface Errors {
+        static int TOO_MANY_REQUESTS = 1;
+    }
+
+    /** @hide */
+    public static class TooManyRequestsException extends RuntimeException {}
+
+    private static RuntimeException convertServiceException(ServiceSpecificException e) {
+        switch (e.errorCode) {
+            case Errors.TOO_MANY_REQUESTS:
+                return new TooManyRequestsException();
+            default:
+                Log.w(TAG, "Unknown service error code " + e.errorCode);
+                return new RuntimeException(e);
+        }
+    }
+
     private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER;
     /** @hide */
     public static final int CALLBACK_PRECHECK            = BASE + 1;
@@ -2886,6 +2909,8 @@
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw convertServiceException(e);
         }
         return request;
     }
@@ -3127,6 +3152,8 @@
             mService.pendingRequestForNetwork(request.networkCapabilities, operation);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw convertServiceException(e);
         }
     }
 
@@ -3226,6 +3253,8 @@
             mService.pendingListenForNetwork(request.networkCapabilities, operation);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } catch (ServiceSpecificException e) {
+            throw convertServiceException(e);
         }
     }
 
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 65025fb..8d85880 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -1548,6 +1548,7 @@
         Parcel p = Parcel.obtain();
         p.setDataPosition(0);
         p.appendFrom(parcel, offset, length);
+        p.adoptClassCookies(parcel);
         if (DEBUG) Log.d(TAG, "Retrieving "  + Integer.toHexString(System.identityHashCode(this))
                 + ": " + length + " bundle bytes starting at " + offset);
         p.setDataPosition(0);
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index c5c743b..f4a9ef6 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -204,6 +204,8 @@
     private boolean mOwnsNativeParcelObject;
     private long mNativeSize;
 
+    private ArrayMap<Class, Object> mClassCookies;
+
     private RuntimeException mStack;
 
     private static final int POOL_SIZE = 6;
@@ -293,6 +295,7 @@
     private static native long nativeWriteFileDescriptor(long nativePtr, FileDescriptor val);
 
     private static native byte[] nativeCreateByteArray(long nativePtr);
+    private static native boolean nativeReadByteArray(long nativePtr, byte[] dest, int destLen);
     private static native byte[] nativeReadBlob(long nativePtr);
     @FastNative
     private static native int nativeReadInt(long nativePtr);
@@ -497,6 +500,24 @@
         return nativeCompareData(mNativePtr, other.mNativePtr);
     }
 
+    /** @hide */
+    public final void setClassCookie(Class clz, Object cookie) {
+        if (mClassCookies == null) {
+            mClassCookies = new ArrayMap<>();
+        }
+        mClassCookies.put(clz, cookie);
+    }
+
+    /** @hide */
+    public final Object getClassCookie(Class clz) {
+        return mClassCookies != null ? mClassCookies.get(clz) : null;
+    }
+
+    /** @hide */
+    public final void adoptClassCookies(Parcel from) {
+        mClassCookies = from.mClassCookies;
+    }
+
     /**
      * Report whether the parcel contains any marshalled file descriptors.
      */
@@ -2197,11 +2218,8 @@
      * given byte array.
      */
     public final void readByteArray(byte[] val) {
-        // TODO: make this a native method to avoid the extra copy.
-        byte[] ba = createByteArray();
-        if (ba.length == val.length) {
-           System.arraycopy(ba, 0, val, 0, ba.length);
-        } else {
+        boolean valid = nativeReadByteArray(mNativePtr, val, (val != null) ? val.length : 0);
+        if (!valid) {
             throw new RuntimeException("bad array lengths");
         }
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7374586..39f48df 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6968,6 +6968,13 @@
         public static final String CMAS_ADDITIONAL_BROADCAST_PKG = "cmas_additional_broadcast_pkg";
 
         /**
+         * Whether the launcher should show any notification badges.
+         * The value is boolean (1 or 0).
+         * @hide
+         */
+        public static final String NOTIFICATION_BADGING = "notification_badging";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -7062,7 +7069,8 @@
             AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
             ASSIST_GESTURE_ENABLED,
             ASSIST_GESTURE_SENSITIVITY,
-            VR_DISPLAY_MODE
+            VR_DISPLAY_MODE,
+            NOTIFICATION_BADGING
         };
 
         /**
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index b3fe8a8..bf33519 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -56,7 +56,7 @@
 
     private final boolean mIsOwner;
     private final long mMemoryAddr;
-    private int mFd;
+    private int mFd = -1;
 
     /**
      * Creates a new instance.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3b15456..22329f4 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -16,10 +16,13 @@
 
 package android.view;
 
+import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+
 import android.graphics.Bitmap;
 import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.os.Binder;
 import android.os.IBinder;
 import android.util.Log;
 import android.view.Surface.OutOfResourcesException;
@@ -302,7 +305,7 @@
     public SurfaceControl(SurfaceSession session,
             String name, int w, int h, int format, int flags)
                     throws OutOfResourcesException {
-        this(session, name, w, h, format, flags, null, -1, -1);
+        this(session, name, w, h, format, flags, null, INVALID_WINDOW_TYPE, Binder.getCallingUid());
     }
 
     public SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ff42ff6..cea3263 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2858,6 +2858,14 @@
      */
     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
 
+    /**
+     * Flag indicating that when layout is completed we should notify
+     * that the view was entered for autofill purposes. To minimize
+     * showing autofill for views not visible to the user we evaluate
+     * user visibility which cannot be done until the view is laid out.
+     */
+    static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x4000;
+
     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
 
     static final int SCROLL_INDICATORS_NONE = 0x0000;
@@ -4462,6 +4470,7 @@
             sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
 
             Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
+            Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
 
             // In M and newer, our widgets can pass a "hint" value in the size
             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
@@ -6495,7 +6504,7 @@
 
             if (mParent != null) {
                 mParent.requestChildFocus(this, this);
-                setFocusedInCluster();
+                updateFocusedInCluster(oldFocus, direction);
             }
 
             if (mAttachInfo != null) {
@@ -6844,8 +6853,15 @@
         if (isAutofillable() && isAttachedToWindow()) {
             AutofillManager afm = getAutofillManager();
             if (afm != null) {
-                if (enter && hasWindowFocus() && isFocused() && isVisibleToUser()) {
-                    afm.notifyViewEntered(this);
+                if (enter && hasWindowFocus() && isFocused()) {
+                    // We have not been laid out yet, hence cannot evaluate
+                    // whether this view is visible to the user, we will do
+                    // the evaluation once layout is complete.
+                    if (!isLaidOut()) {
+                        mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
+                    } else if (isVisibleToUser()) {
+                        afm.notifyViewEntered(this);
+                    }
                 } else if (!hasWindowFocus() || !isFocused()) {
                     afm.notifyViewExited(this);
                 }
@@ -9911,22 +9927,47 @@
      * @hide
      */
     public final void setFocusedInCluster() {
-        View top = findKeyboardNavigationCluster();
-        if (top == this) {
+        setFocusedInCluster(findKeyboardNavigationCluster());
+    }
+
+    private void setFocusedInCluster(View cluster) {
+        if (this instanceof ViewGroup) {
+            ((ViewGroup) this).mFocusedInCluster = null;
+        }
+        if (cluster == this) {
             return;
         }
         ViewParent parent = mParent;
         View child = this;
         while (parent instanceof ViewGroup) {
-            ((ViewGroup) parent).setFocusedInCluster(child);
-            if (parent == top) {
-                return;
+            ((ViewGroup) parent).mFocusedInCluster = child;
+            if (parent == cluster) {
+                break;
             }
             child = (View) parent;
             parent = parent.getParent();
         }
     }
 
+    private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
+        if (oldFocus != null) {
+            View oldCluster = oldFocus.findKeyboardNavigationCluster();
+            View cluster = findKeyboardNavigationCluster();
+            if (oldCluster != cluster) {
+                // Going from one cluster to another, so save last-focused.
+                // This covers cluster jumps because they are always FOCUS_DOWN
+                oldFocus.setFocusedInCluster(oldCluster);
+                if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
+                    // This is a result of ordered navigation so consider navigation through
+                    // the previous cluster "complete" and clear its last-focused memory.
+                    if (oldFocus.mParent instanceof ViewGroup) {
+                        ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * Returns whether this View should receive focus when the focus is restored for the view
      * hierarchy containing this view.
@@ -19304,6 +19345,11 @@
 
         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
+
+        if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
+            mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
+            notifyEnterOrExitForAutoFillIfNeeded(true);
+        }
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 18c1b8c..50593f2 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -142,7 +142,7 @@
     // that is or contains a default-focus view.
     private View mDefaultFocus;
     // The last child of this ViewGroup which held focus within the current cluster
-    private View mFocusedInCluster;
+    View mFocusedInCluster;
 
     /**
      * A Transformation used when drawing children, to
@@ -806,10 +806,6 @@
         return mDefaultFocus != null || super.hasDefaultFocus();
     }
 
-    void setFocusedInCluster(View child) {
-        mFocusedInCluster = child;
-    }
-
     /**
      * Removes {@code child} (and associated focusedInCluster chain) from the cluster containing
      * it.
@@ -825,8 +821,11 @@
         ViewParent parent = this;
         do {
             ((ViewGroup) parent).mFocusedInCluster = null;
+            if (parent == top) {
+                break;
+            }
             parent = parent.getParent();
-        } while (parent != top && parent instanceof ViewGroup);
+        } while (parent instanceof ViewGroup);
     }
 
     @Override
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8445b37..3f91476 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -743,6 +743,12 @@
         public static final int LAST_SYSTEM_WINDOW      = 2999;
 
         /**
+         * @hide
+         * Used internally when there is no suitable type available.
+         */
+        public static final int INVALID_WINDOW_TYPE = -1;
+
+        /**
          * Return true if the window type is an alert window.
          *
          * @param type The window type.
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 1f3be84..32fae73 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -140,4 +140,14 @@
     @WorkerThread
     LinksInfo getLinks(
             @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales);
+
+    /**
+     * Logs a TextClassifier event.
+     *
+     * @param source the text classifier used to generate this event
+     * @param event the text classifier related event
+     * @hide
+     */
+    @WorkerThread
+    default void logEvent(String source, String event) {}
 }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 7362c70..5f72fc7 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -40,6 +40,7 @@
 import android.widget.TextViewMetrics;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.Preconditions;
 
 import java.io.File;
@@ -77,6 +78,8 @@
 
     private final Context mContext;
 
+    private final MetricsLogger mMetricsLogger = new MetricsLogger();
+
     private final Object mSmartSelectionLock = new Object();
     @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
     private Map<Locale, String> mModelFilePaths;
@@ -105,7 +108,8 @@
                 if (start <= end
                         && start >= 0 && end <= string.length()
                         && start <= selectionStartIndex && end >= selectionEndIndex) {
-                    final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end);
+                    final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end)
+                            .setLogSource(LOG_TAG);
                     final SmartSelection.ClassificationResult[] results =
                             smartSelection.classifyText(
                                     string, start, end,
@@ -173,6 +177,13 @@
         return TextClassifier.NO_OP.getLinks(text, linkMask, defaultLocales);
     }
 
+    @Override
+    public void logEvent(String source, String event) {
+        if (LOG_TAG.equals(source)) {
+            mMetricsLogger.count(event, 1);
+        }
+    }
+
     private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException {
         synchronized (mSmartSelectionLock) {
             localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 3172c13..9a66693 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -34,13 +34,16 @@
     private final int mEndIndex;
     @NonNull private final EntityConfidence<String> mEntityConfidence;
     @NonNull private final List<String> mEntities;
+    @NonNull private final String mLogSource;
 
     private TextSelection(
-            int startIndex, int endIndex, @NonNull EntityConfidence<String> entityConfidence) {
+            int startIndex, int endIndex, @NonNull EntityConfidence<String> entityConfidence,
+            @NonNull String logSource) {
         mStartIndex = startIndex;
         mEndIndex = endIndex;
         mEntityConfidence = new EntityConfidence<>(entityConfidence);
         mEntities = mEntityConfidence.getEntities();
+        mLogSource = logSource;
     }
 
     /**
@@ -87,6 +90,14 @@
         return mEntityConfidence.getConfidenceScore(entity);
     }
 
+    /**
+     * Returns a tag for the source classifier used to generate this result.
+     * @hide
+     */
+    public String getSourceClassifier() {
+        return mLogSource;
+    }
+
     @Override
     public String toString() {
         return String.format("TextSelection {%d, %d, %s}",
@@ -102,6 +113,7 @@
         private final int mEndIndex;
         @NonNull private final EntityConfidence<String> mEntityConfidence =
                 new EntityConfidence<>();
+        @NonNull private String mLogSource = "";
 
         /**
          * Creates a builder used to build {@link TextSelection} objects.
@@ -131,10 +143,19 @@
         }
 
         /**
+         * Sets a tag for the source classifier used to generate this result.
+         * @hide
+         */
+        Builder setLogSource(@NonNull String logSource) {
+            mLogSource = Preconditions.checkNotNull(logSource);
+            return this;
+        }
+
+        /**
          * Builds and returns {@link TextSelection} object.
          */
         public TextSelection build() {
-            return new TextSelection(mStartIndex, mEndIndex, mEntityConfidence);
+            return new TextSelection(mStartIndex, mEndIndex, mEntityConfidence, mLogSource);
         }
     }
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index b0d6395..bb658c1 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3925,6 +3925,8 @@
 
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+            getSelectionActionModeHelper().onSelectionAction();
+
             if (mProcessTextIntentActionsHandler.performMenuItemAction(item)) {
                 return true;
             }
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 16a1087..89182b0 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -56,13 +56,14 @@
     private TextClassification mTextClassification;
     private AsyncTask mTextClassificationAsyncTask;
 
-    private final SelectionInfo mSelectionInfo = new SelectionInfo();
+    private final SelectionTracker mSelectionTracker;
 
     SelectionActionModeHelper(@NonNull Editor editor) {
         mEditor = Preconditions.checkNotNull(editor);
         final TextView textView = mEditor.getTextView();
         mTextClassificationHelper = new TextClassificationHelper(
                 textView.getTextClassifier(), textView.getText(), 0, 1, textView.getTextLocales());
+        mSelectionTracker = new SelectionTracker(textView.getTextClassifier());
     }
 
     public void startActionModeAsync(boolean adjustSelection) {
@@ -99,8 +100,13 @@
         }
     }
 
+    public void onSelectionAction() {
+        mSelectionTracker.onSelectionAction(mTextClassificationHelper.getClassifierTag());
+    }
+
     public boolean resetSelection(int textIndex) {
-        if (mSelectionInfo.resetSelection(textIndex, mEditor)) {
+        if (mSelectionTracker.resetSelection(
+                textIndex, mEditor, mTextClassificationHelper.getClassifierTag())) {
             invalidateActionModeAsync();
             return true;
         }
@@ -113,7 +119,7 @@
     }
 
     public void onDestroyActionMode() {
-        mSelectionInfo.onSelectionDestroyed();
+        mSelectionTracker.onSelectionDestroyed();
         cancelAsyncTask();
     }
 
@@ -137,7 +143,7 @@
     private void startActionMode(@Nullable SelectionResult result) {
         final TextView textView = mEditor.getTextView();
         final CharSequence text = textView.getText();
-        mSelectionInfo.setOriginalSelection(
+        mSelectionTracker.setOriginalSelection(
                 textView.getSelectionStart(), textView.getSelectionEnd());
         if (result != null && text instanceof Spannable) {
             Selection.setSelection((Spannable) text, result.mStart, result.mEnd);
@@ -151,7 +157,8 @@
                 controller.show();
             }
             if (result != null) {
-                mSelectionInfo.onSelectionStarted(result.mStart, result.mEnd);
+                mSelectionTracker.onSelectionStarted(
+                        result.mStart, result.mEnd, mTextClassificationHelper.getClassifierTag());
             }
         }
         mEditor.setRestartActionModeOnNextRefresh(false);
@@ -165,7 +172,9 @@
             actionMode.invalidate();
         }
         final TextView textView = mEditor.getTextView();
-        mSelectionInfo.onSelectionUpdated(textView.getSelectionStart(), textView.getSelectionEnd());
+        mSelectionTracker.onSelectionUpdated(
+                textView.getSelectionStart(), textView.getSelectionEnd(),
+                mTextClassificationHelper.getClassifierTag());
         mTextClassificationAsyncTask = null;
     }
 
@@ -177,49 +186,111 @@
     }
 
     /**
-     * Holds information about the selection and uses it to decide on whether or not to update
-     * the selection when resetSelection is called.
-     * The expected UX here is to allow the user to select a word inside of the "smart selection" on
-     * a single tap.
+     * Tracks and logs smart selection changes.
+     * It is important to trigger this object's methods at the appropriate event so that it tracks
+     * smart selection events appropriately.
      */
-    private static final class SelectionInfo {
+    private static final class SelectionTracker {
+
+        // Log event: Smart selection happened.
+        private static final String LOG_EVENT_MULTI_SELECTION =
+                "textClassifier_multiSelection";
+
+        // Log event: Smart selection acted upon.
+        private static final String LOG_EVENT_MULTI_SELECTION_ACTION =
+                "textClassifier_multiSelection_action";
+
+        // Log event: Smart selection was reset to original selection.
+        private static final String LOG_EVENT_MULTI_SELECTION_RESET =
+                "textClassifier_multiSelection_reset";
+
+        // Log event: Smart selection was user modified.
+        private static final String LOG_EVENT_MULTI_SELECTION_MODIFIED =
+                "textClassifier_multiSelection_modified";
+
+        private final TextClassifier mClassifier;
 
         private int mOriginalStart;
         private int mOriginalEnd;
         private int mSelectionStart;
         private int mSelectionEnd;
 
-        private boolean mResetOriginal;
+        private boolean mSmartSelectionActive;
 
+        SelectionTracker(TextClassifier classifier) {
+            mClassifier = classifier;
+        }
+
+        /**
+         * Called to initialize the original selection before smart selection is triggered.
+         */
         public void setOriginalSelection(int selectionStart, int selectionEnd) {
             mOriginalStart = selectionStart;
             mOriginalEnd = selectionEnd;
-            mResetOriginal = false;
+            mSmartSelectionActive = false;
         }
 
-        public void onSelectionStarted(int selectionStart, int selectionEnd) {
-            // Set the reset flag to true if the selection changed.
+        /**
+         * Called when selection action mode is started.
+         * If the selection indices are different from the original selection indices, we have a
+         * smart selection.
+         */
+        public void onSelectionStarted(int selectionStart, int selectionEnd, String logTag) {
             mSelectionStart = selectionStart;
             mSelectionEnd = selectionEnd;
-            mResetOriginal = mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd;
+            // If the started selection is different from the original selection, we have a
+            // smart selection.
+            mSmartSelectionActive =
+                    mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd;
+            if (mSmartSelectionActive) {
+                mClassifier.logEvent(logTag, LOG_EVENT_MULTI_SELECTION);
+            }
         }
 
-        public void onSelectionUpdated(int selectionStart, int selectionEnd) {
-            // If the selection did not change, maintain the reset state. Otherwise, disable reset.
-            mResetOriginal &= selectionStart == mSelectionStart && selectionEnd == mSelectionEnd;
+        /**
+         * Called when selection bounds change.
+         */
+        public void onSelectionUpdated(int selectionStart, int selectionEnd, String logTag) {
+            final boolean selectionChanged =
+                    selectionStart != mSelectionStart || selectionEnd != mSelectionEnd;
+            if (selectionChanged) {
+                if (mSmartSelectionActive) {
+                    mClassifier.logEvent(logTag, LOG_EVENT_MULTI_SELECTION_MODIFIED);
+                }
+                mSmartSelectionActive = false;
+            }
         }
 
+        /**
+         * Called when the selection action mode is destroyed.
+         */
         public void onSelectionDestroyed() {
-            mResetOriginal = false;
+            mSmartSelectionActive = false;
         }
 
-        public boolean resetSelection(int textIndex, Editor editor) {
+        /**
+         * Logs if the action was taken on a smart selection.
+         */
+        public void onSelectionAction(String logTag) {
+            if (mSmartSelectionActive) {
+                mClassifier.logEvent(logTag, LOG_EVENT_MULTI_SELECTION_ACTION);
+            }
+        }
+
+        /**
+         * Returns true if the current smart selection should be reset to normal selection based on
+         * information that has been recorded about the original selection and the smart selection.
+         * The expected UX here is to allow the user to select a word inside of the smart selection
+         * on a single tap.
+         */
+        public boolean resetSelection(int textIndex, Editor editor, String logTag) {
             final CharSequence text = editor.getTextView().getText();
-            if (mResetOriginal
+            if (mSmartSelectionActive
                     && textIndex >= mSelectionStart && textIndex <= mSelectionEnd
                     && text instanceof Spannable) {
                 // Only allow a reset once.
-                mResetOriginal = false;
+                mSmartSelectionActive = false;
+                mClassifier.logEvent(logTag, LOG_EVENT_MULTI_SELECTION_RESET);
                 return editor.selectCurrentWord();
             }
             return false;
@@ -301,6 +372,7 @@
         /** End index relative to mText. */
         private int mSelectionEnd;
         private LocaleList mLocales;
+        private String mClassifierTag = "";
 
         /** Trimmed text starting from mTrimStart in mText. */
         private CharSequence mTrimmedText;
@@ -364,9 +436,14 @@
                     mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
             mSelectionStart = Math.max(0, sel.getSelectionStartIndex() + mTrimStart);
             mSelectionEnd = Math.min(mText.length(), sel.getSelectionEndIndex() + mTrimStart);
+            mClassifierTag = sel.getSourceClassifier();
             return classifyText();
         }
 
+        String getClassifierTag() {
+            return mClassifierTag;
+        }
+
         private void trimText() {
             mTrimStart = Math.max(0, mSelectionStart - TRIM_DELTA);
             final int referenceEnd = Math.min(mText.length(), mSelectionEnd + TRIM_DELTA);
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index fef85da..797cf2b 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -40,6 +40,7 @@
     public static String UPDATES = "UPDATES";
     public static String NETWORK_STATUS = "NETWORK_STATUS";
     public static String NETWORK_ALERTS = "NETWORK_ALERTS";
+    public static String NETWORK_AVAILABLE = "NETWORK_AVAILABLE";
     public static String VPN = "VPN";
     public static String DEVICE_ADMIN = "DEVICE_ADMIN";
     public static String ALERTS = "ALERTS";
@@ -99,6 +100,11 @@
         channelsList.add(networkAlertsChannel);
 
         channelsList.add(new NotificationChannel(
+                NETWORK_AVAILABLE,
+                context.getString(R.string.notification_channel_network_available),
+                NotificationManager.IMPORTANCE_LOW));
+
+        channelsList.add(new NotificationChannel(
                 VPN,
                 context.getString(R.string.notification_channel_vpn),
                 NotificationManager.IMPORTANCE_LOW));
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index a89427d..186b63a 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -9819,10 +9819,9 @@
                     }
                 });
 
-        // TODO: STOPSHIP, remove the "true" below after b/34961340 is fixed
-        if (DEBUG_ENERGY_CPU || true) {
-            Slog.d(TAG, "Reading cpu stats took " + (mClocks.elapsedRealtime() - startTimeMs) +
-                    " ms");
+        final long elapse = (mClocks.elapsedRealtime() - startTimeMs);
+        if (DEBUG_ENERGY_CPU || (elapse >= 100)) {
+            Slog.d(TAG, "Reading cpu stats took " + elapse + " ms");
         }
 
         if (mOnBatteryInternal && numWakelocks > 0) {
diff --git a/core/java/com/android/internal/os/KernelMemoryBandwidthStats.java b/core/java/com/android/internal/os/KernelMemoryBandwidthStats.java
index b5915aa..aa56e93 100644
--- a/core/java/com/android/internal/os/KernelMemoryBandwidthStats.java
+++ b/core/java/com/android/internal/os/KernelMemoryBandwidthStats.java
@@ -8,6 +8,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.BufferedReader;
+import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 
@@ -24,14 +25,25 @@
 public class KernelMemoryBandwidthStats {
     private static final String TAG = "KernelMemoryBandwidthStats";
 
-    final protected LongSparseLongArray mBandwidthEntries = new LongSparseLongArray();
     private static final String mSysfsFile = "/sys/kernel/memory_state_time/show_stat";
     private static final boolean DEBUG = false;
 
+    protected final LongSparseLongArray mBandwidthEntries = new LongSparseLongArray();
+    private boolean mStatsDoNotExist = false;
+
     public void updateStats() {
+        if (mStatsDoNotExist) {
+            // Skip reading.
+            return;
+        }
+
         StrictMode.ThreadPolicy policy = StrictMode.allowThreadDiskReads();
         try (BufferedReader reader = new BufferedReader(new FileReader(mSysfsFile))) {
             parseStats(reader);
+        } catch (FileNotFoundException e) {
+            Slog.w(TAG, "No kernel memory bandwidth stats available");
+            mBandwidthEntries.clear();
+            mStatsDoNotExist = true;
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read memory bandwidth: " + e.getMessage());
             mBandwidthEntries.clear();
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 56f68d4..5aea2b7 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -168,8 +168,8 @@
     }
 }
 
-static void android_os_Parcel_writeNative(JNIEnv* env, jclass clazz, jlong nativePtr, jobject data,
-                                          jint offset, jint length)
+static void android_os_Parcel_writeByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
+                                             jobject data, jint offset, jint length)
 {
     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
     if (parcel == NULL) {
@@ -350,6 +350,28 @@
     return ret;
 }
 
+static jboolean android_os_Parcel_readByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
+                                                jobject dest, jint destLen)
+{
+    jboolean ret = JNI_FALSE;
+    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+    if (parcel == NULL) {
+        return ret;
+    }
+
+    int32_t len = parcel->readInt32();
+    if (len >= 0 && len <= (int32_t)parcel->dataAvail() && len == destLen) {
+        jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)dest, 0);
+        if (ar) {
+            const void* data = parcel->readInplace(len);
+            memcpy(ar, data, len);
+            env->ReleasePrimitiveArrayCritical((jarray)dest, ar, 0);
+            ret = JNI_TRUE;
+        }
+    }
+    return ret;
+}
+
 static jbyteArray android_os_Parcel_readBlob(JNIEnv* env, jclass clazz, jlong nativePtr)
 {
     jbyteArray ret = NULL;
@@ -761,7 +783,7 @@
     // @FastNative
     {"nativeRestoreAllowFds",     "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
 
-    {"nativeWriteByteArray",      "(J[BII)V", (void*)android_os_Parcel_writeNative},
+    {"nativeWriteByteArray",      "(J[BII)V", (void*)android_os_Parcel_writeByteArray},
     {"nativeWriteBlob",           "(J[BII)V", (void*)android_os_Parcel_writeBlob},
     // @FastNative
     {"nativeWriteInt",            "(JI)V", (void*)android_os_Parcel_writeInt},
@@ -776,6 +798,7 @@
     {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)J", (void*)android_os_Parcel_writeFileDescriptor},
 
     {"nativeCreateByteArray",     "(J)[B", (void*)android_os_Parcel_createByteArray},
+    {"nativeReadByteArray",       "(J[BI)Z", (void*)android_os_Parcel_readByteArray},
     {"nativeReadBlob",            "(J)[B", (void*)android_os_Parcel_readBlob},
     // @FastNative
     {"nativeReadInt",             "(J)I", (void*)android_os_Parcel_readInt},
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index ea40fd5..8b73daf 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -503,6 +503,7 @@
     SettingProto demo_user_setup_complete = 165;
     SettingProto instant_apps_enabled = 166;
     SettingProto device_paired = 167;
+    SettingProto notification_badging = 168;
 }
 
 message SystemSettingsProto {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 44ddd0e..be53f2c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1010,6 +1010,9 @@
     <!-- Is the notification LED intrusive? Used to decide if there should be a disable option -->
     <bool name="config_intrusiveNotificationLed">false</bool>
 
+    <!-- De we do icon badges? Used to decide if there should be a disable option-->
+    <bool name="config_notificationBadging">true</bool>
+
     <!-- Default value for LED off time when the battery is low on charge in miliseconds -->
     <integer name="config_notificationsBatteryLedOff">2875</integer>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8fc57b1..21ab4c3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -629,6 +629,9 @@
     <!-- Text shown when viewing channel settings for notifications related to network alerts -->
     <string name="notification_channel_network_alerts">Network alerts</string>
 
+    <!-- Text shown when viewing the channel settings for notification about open nearby wireless networks. -->
+    <string name="notification_channel_network_available">Network available</string>
+
     <!-- Text shown when viewing channel settings for notifications related to vpn status -->
     <string name="notification_channel_vpn">VPN status</string>
 
@@ -2993,6 +2996,17 @@
     <!-- If there is ever a ringtone set for some setting, but that ringtone can no longer be resolved, t his is shown instead.  For example, if the ringtone was on a SD card and it had been removed, this woudl be shown for ringtones on that SD card. -->
     <string name="ringtone_unknown">Unknown</string>
 
+    <!-- A notification is shown when there are open wireless networks nearby.  This is the notification's title. -->
+    <plurals name="wifi_available">
+        <item quantity="one">Wi-Fi network available</item>
+        <item quantity="other">Wi-Fi networks available</item>
+    </plurals>
+    <!-- A notification is shown when there are open wireless networks nearby.  This is the notification's message. -->
+    <plurals name="wifi_available_detailed">
+        <item quantity="one">Open Wi-Fi network available</item>
+        <item quantity="other">Open Wi-Fi networks available</item>
+    </plurals>
+
     <!-- A notification is shown when a wifi captive portal network is detected.  This is the notification's title. -->
     <string name="wifi_available_sign_in">Sign in to Wi-Fi network</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6ceea9c..16e933a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1867,6 +1867,8 @@
   <java-symbol type="layout" name="safe_mode" />
   <java-symbol type="layout" name="simple_list_item_2_single_choice" />
   <java-symbol type="layout" name="app_error_dialog" />
+  <java-symbol type="plurals" name="wifi_available" />
+  <java-symbol type="plurals" name="wifi_available_detailed" />
   <java-symbol type="string" name="accessibility_binding_label" />
   <java-symbol type="string" name="adb_active_notification_message" />
   <java-symbol type="string" name="adb_active_notification_title" />
@@ -2095,6 +2097,7 @@
   <java-symbol type="string" name="config_wifi_tether_enable" />
   <java-symbol type="integer" name="config_wifi_wakeup_available" />
   <java-symbol type="bool" name="config_intrusiveNotificationLed" />
+  <java-symbol type="bool" name="config_notificationBadging" />
   <java-symbol type="dimen" name="preference_fragment_padding_bottom" />
   <java-symbol type="dimen" name="preference_fragment_padding_side" />
   <java-symbol type="drawable" name="expander_ic_maximized" />
@@ -2986,6 +2989,7 @@
   <java-symbol type="string" name="notification_channel_updates" />
   <java-symbol type="string" name="notification_channel_network_status" />
   <java-symbol type="string" name="notification_channel_network_alerts" />
+  <java-symbol type="string" name="notification_channel_network_available" />
   <java-symbol type="string" name="notification_channel_vpn" />
   <java-symbol type="string" name="notification_channel_device_admin" />
   <java-symbol type="string" name="notification_channel_alerts" />
diff --git a/core/tests/coretests/src/android/content/pm/AppCacheTest.java b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
index 1567046..15dbddf 100644
--- a/core/tests/coretests/src/android/content/pm/AppCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/AppCacheTest.java
@@ -25,11 +25,11 @@
 import android.os.ServiceManager;
 import android.os.StatFs;
 import android.os.UserHandle;
+import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.filters.Suppress;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
 import java.io.File;
@@ -48,14 +48,14 @@
     public final long WAIT_TIME_INCR=10*1000;
     private static final long THRESHOLD=5;
     private static final long ACTUAL_THRESHOLD=10;
-    
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         if(localLOGV) Log.i(TAG, "Cleaning up cache directory first");
         cleanUpCacheDirectory();
     }
-    
+
     void cleanUpDirectory(File pDir, String dirName) {
        File testDir = new File(pDir,  dirName);
        if(!testDir.exists()) {
@@ -72,13 +72,13 @@
         }
         testDir.delete();
     }
-    
+
     void cleanUpCacheDirectory() {
         File testDir = mContext.getCacheDir();
         if(!testDir.exists()) {
             return;
         }
-        
+
          String fList[] = testDir.list();
          if(fList == null) {
              testDir.delete();
@@ -93,7 +93,7 @@
              }
          }
      }
-    
+
     @SmallTest
     public void testDeleteAllCacheFiles() {
         String testName="testDeleteAllCacheFiles";
@@ -160,9 +160,9 @@
                     +(blks1-blks3));
         }
     }
-    
+
     /**
-     * This method opens an output file writes to it, opens the same file as an input 
+     * This method opens an output file writes to it, opens the same file as an input
      * stream, reads the contents and verifies the data that was written earlier can be read
      */
     public void openOutFileInAppFilesDir(File pFile, String pFileOut) {
@@ -180,7 +180,7 @@
             failStr(e.getMessage());
         } catch (IOException e) {
             failStr(e.getMessage());
-        } 
+        }
         int count = pFileOut.getBytes().length;
         byte[] buffer = new byte[count];
         try {
@@ -194,8 +194,8 @@
         }
         String str = new String(buffer);
         assertEquals(str, pFileOut);
-    } 
-    
+    }
+
     /*
      * This test case verifies that output written to a file
      * using Context.openFileOutput has executed successfully.
@@ -215,7 +215,7 @@
             failStr(e);
         }
     }
-    
+
     @SmallTest
     public void testAppCacheCreateFile() {
         String fileName = "testFile1.txt";
@@ -225,7 +225,7 @@
         openOutFileInAppFilesDir(file, fileOut);
         cleanUpCacheDirectory();
     }
-    
+
     @MediumTest
     public void testAppCreateCacheFiles() {
         File cacheDir = mContext.getCacheDir();
@@ -261,7 +261,7 @@
             }
         }
     }
-    
+
     byte[] getBuffer() {
         String sbuffer = "a";
         for(int i = 0; i < 10; i++) {
@@ -360,7 +360,7 @@
         }
         assertTrue("Files should have been removed", removedFlag);
     }
-    
+
     //createTestFiles(new File(super.getContext().getCacheDir(), "testtmp", "dir", 3)
     void createTestFiles1(File cacheDir, String testFilePrefix, int numTestFiles) {
         byte buffer[] = getBuffer();
@@ -439,7 +439,7 @@
             }
         }
     }
-    
+
     class PackageDataObserver extends IPackageDataObserver.Stub {
         public boolean retValue = false;
         private boolean doneFlag = false;
@@ -455,11 +455,11 @@
             return doneFlag;
         }
     }
-    
+
     IPackageManager getPm() {
         return  IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
     }
-    
+
     boolean invokePMDeleteAppCacheFiles() throws Exception {
         try {
             String packageName = mContext.getPackageName();
@@ -485,7 +485,7 @@
             return false;
         }
     }
-    
+
     boolean invokePMFreeApplicationCache(long idealStorageSize) throws Exception {
         try {
             String packageName = mContext.getPackageName();
@@ -512,7 +512,7 @@
         }
     }
 
-    boolean invokePMFreeStorage(long idealStorageSize, FreeStorageReceiver r, 
+    boolean invokePMFreeStorage(long idealStorageSize, FreeStorageReceiver r,
             PendingIntent pi) throws Exception {
         try {
             // Spin lock waiting for call back
@@ -536,7 +536,7 @@
             return false;
         }
     }
-    
+
     @LargeTest
     public void testDeleteAppCacheFiles() throws Exception {
         String testName="testDeleteAppCacheFiles";
@@ -551,7 +551,7 @@
         public boolean retValue = false;
         public PackageStats stats;
         private boolean doneFlag = false;
-        
+
         public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
                 throws RemoteException {
             synchronized(this) {
@@ -565,7 +565,7 @@
             return doneFlag;
         }
     }
-    
+
     public PackageStats invokePMGetPackageSizeInfo() throws Exception {
         try {
             String packageName = mContext.getPackageName();
@@ -593,7 +593,7 @@
             return null;
         }
     }
-    
+
     @SmallTest
     public void testGetPackageSizeInfo() throws Exception {
         String testName="testGetPackageSizeInfo";
@@ -603,7 +603,7 @@
         if(localLOGV) Log.i(TAG, "code="+stats.codeSize+", data="+stats.dataSize+
                 ", cache="+stats.cacheSize);
     }
-    
+
     @SmallTest
     public void testGetSystemSharedLibraryNames() throws Exception {
         try {
@@ -615,17 +615,17 @@
             }
         } catch (RemoteException e) {
             fail("Failed invoking getSystemSharedLibraryNames with exception:" + e);
-        }   
+        }
     }
-    
+
     class FreeStorageReceiver extends BroadcastReceiver {
         public static final String ACTION_FREE = "com.android.unit_tests.testcallback";
         private boolean doneFlag = false;
-        
+
         public boolean isDone() {
             return doneFlag;
         }
-        
+
         @Override
         public void onReceive(Context context, Intent intent) {
             if(intent.getAction().equalsIgnoreCase(ACTION_FREE)) {
@@ -637,7 +637,7 @@
             }
         }
     }
-    
+
     // TODO: flaky test, omit from LargeTest for now
     //@LargeTest
     public void testFreeStorage() throws Exception {
@@ -664,10 +664,10 @@
         if(localLOGV || TRACKING) Log.i(TAG, "Available blocks after freeing cache"+blks3);
         assertEquals(receiver.getResultCode(), 1);
         mContext.unregisterReceiver(receiver);
-        // Verify result  
+        // Verify result
         verifyTestFiles1(cacheDir, "testtmpdir", 5);
     }
-    
+
     /* utility method used to create observer and check async call back from PackageManager.
      * ClearApplicationUserData
      */
@@ -696,7 +696,7 @@
             return false;
         }
     }
-    
+
     void verifyUserDataCleared(File pDir) {
         if(localLOGV) Log.i(TAG, "Verifying "+pDir);
         if(pDir == null) {
@@ -717,7 +717,7 @@
             fail(pDir+" should be empty or contain only lib subdirectory. Found "+fileList[i]);
         }
     }
-    
+
     File getDataDir() {
         try {
             ApplicationInfo appInfo = getPm().getApplicationInfo(mContext.getPackageName(), 0,
@@ -727,7 +727,8 @@
             throw new RuntimeException("Pacakge manager dead", e);
         }
     }
-    
+
+    @Suppress
     @LargeTest
     public void testClearApplicationUserDataWithTestData() throws Exception {
         File cacheDir = mContext.getCacheDir();
@@ -740,14 +741,16 @@
         //confirm files dont exist
         verifyUserDataCleared(getDataDir());
     }
-    
+
+    @Suppress
     @SmallTest
     public void testClearApplicationUserDataWithNoTestData() throws Exception {
         assertTrue(invokePMClearApplicationUserData());
         //confirm files dont exist
         verifyUserDataCleared(getDataDir());
     }
-    
+
+    @Suppress
     @LargeTest
     public void testClearApplicationUserDataNoObserver() throws Exception {
         getPm().clearApplicationUserData(mContext.getPackageName(), null, UserHandle.myUserId());
@@ -756,5 +759,5 @@
         //confirm files dont exist
         verifyUserDataCleared(getDataDir());
     }
-    
+
 }
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 86ab3dc..19d2a31 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -45,6 +45,7 @@
     <permission name="android.permission.BLUETOOTH_STACK" >
         <group gid="bluetooth" />
         <group gid="wakelock" />
+        <group gid="uhid" />
     </permission>
 
     <permission name="android.permission.NET_TUNNELING" >
@@ -181,9 +182,6 @@
     <allow-in-power-save package="com.android.cellbroadcastreceiver" />
     <allow-in-power-save package="com.android.shell" />
 
-    <!-- STOPSHIP(b/36856786): Revert this once it is fixed properly -->
-    <allow-in-power-save package="com.google.android.apps.enterprise.dmagent" />
-
     <!-- These are the packages that are white-listed to be able to run as system user -->
     <system-user-whitelisted-app package="com.android.settings" />
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 2a2e14b..0301f2e 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -49,6 +49,8 @@
 public class Canvas extends BaseCanvas {
     /** @hide */
     public static boolean sCompatibilityRestore = false;
+    /** @hide */
+    public static boolean sCompatibilitySetBitmap = false;
 
     /** @hide */
     public long getNativeCanvasWrapper() {
@@ -172,6 +174,11 @@
             throw new RuntimeException("Can't set a bitmap device on a HW accelerated canvas");
         }
 
+        Matrix preservedMatrix = null;
+        if (bitmap != null && sCompatibilitySetBitmap) {
+            preservedMatrix = getMatrix();
+        }
+
         if (bitmap == null) {
             nSetBitmap(mNativeCanvasWrapper, null);
             mDensity = Bitmap.DENSITY_NONE;
@@ -185,6 +192,10 @@
             mDensity = bitmap.mDensity;
         }
 
+        if (preservedMatrix != null) {
+            setMatrix(preservedMatrix);
+        }
+
         mBitmap = bitmap;
     }
 
diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp
index 2771ade..60e3845 100644
--- a/libs/androidfw/AttributeResolution.cpp
+++ b/libs/androidfw/AttributeResolution.cpp
@@ -44,8 +44,7 @@
 };
 
 class BagAttributeFinder
-    : public BackTrackingAttributeFinder<BagAttributeFinder,
-                                         const ResTable::bag_entry*> {
+    : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
  public:
   BagAttributeFinder(const ResTable::bag_entry* start,
                      const ResTable::bag_entry* end)
@@ -76,8 +75,7 @@
   uint32_t def_style_bag_type_set_flags = 0;
   if (def_style_attr != 0) {
     Res_value value;
-    if (theme->getAttribute(def_style_attr, &value,
-                            &def_style_bag_type_set_flags) >= 0) {
+    if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) {
       if (value.dataType == Res_value::TYPE_REFERENCE) {
         def_style_res = value.data;
       }
@@ -127,18 +125,14 @@
         ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType,
               value.data);
       }
-    }
-
-    if (value.dataType == Res_value::TYPE_NULL) {
-      const ResTable::bag_entry* const def_style_entry =
-          def_style_attr_finder.Find(cur_ident);
+    } else {
+      const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident);
       if (def_style_entry != def_style_end) {
         block = def_style_entry->stringBlock;
         type_set_flags = def_style_type_set_flags;
         value = def_style_entry->map.value;
         if (kDebugStyles) {
-          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
-                value.data);
+          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
       }
     }
@@ -146,29 +140,24 @@
     uint32_t resid = 0;
     if (value.dataType != Res_value::TYPE_NULL) {
       // Take care of resolving the found resource to its final value.
-      ssize_t new_block = theme->resolveAttributeReference(
-          &value, block, &resid, &type_set_flags, &config);
+      ssize_t new_block =
+          theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
       if (new_block >= 0) block = new_block;
       if (kDebugStyles) {
-        ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
-              value.data);
+        ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
       }
-    } else {
+    } else if (value.data != Res_value::DATA_NULL_EMPTY) {
       // If we still don't have a value for this attribute, try to find
       // it in the theme!
-      ssize_t new_block =
-          theme->getAttribute(cur_ident, &value, &type_set_flags);
+      ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
       if (new_block >= 0) {
         if (kDebugStyles) {
-          ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
-                value.data);
+          ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
-        new_block = res.resolveReference(&value, new_block, &resid,
-                                         &type_set_flags, &config);
+        new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
         if (new_block >= 0) block = new_block;
         if (kDebugStyles) {
-          ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
-                value.data);
+          ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
       }
     }
@@ -184,8 +173,7 @@
     }
 
     if (kDebugStyles) {
-      ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
-            value.dataType, value.data);
+      ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
     }
 
     // Write the final value back to Java.
@@ -198,7 +186,8 @@
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
 
-    if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
+    if (out_indices != nullptr &&
+        (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY)) {
       indices_idx++;
       out_indices[indices_idx] = ii;
     }
@@ -247,8 +236,7 @@
     ssize_t idx = xml_parser->indexOfStyle();
     if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) {
       if (value.dataType == value.TYPE_ATTRIBUTE) {
-        if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) <
-            0) {
+        if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) {
           value.dataType = Res_value::TYPE_NULL;
         }
       }
@@ -318,41 +306,34 @@
       // We found the attribute we were looking for.
       xml_parser->getAttributeValue(xml_attr_idx, &value);
       if (kDebugStyles) {
-        ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType,
-              value.data);
+        ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
       }
     }
 
-    if (value.dataType == Res_value::TYPE_NULL) {
-      // Walk through the style class values looking for the requested
-      // attribute.
-      const ResTable::bag_entry* const style_attr_entry =
-          style_attr_finder.Find(cur_ident);
+    if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
+      // Walk through the style class values looking for the requested attribute.
+      const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident);
       if (style_attr_entry != style_attr_end) {
         // We found the attribute we were looking for.
         block = style_attr_entry->stringBlock;
         type_set_flags = style_type_set_flags;
         value = style_attr_entry->map.value;
         if (kDebugStyles) {
-          ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType,
-                value.data);
+          ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
       }
     }
 
-    if (value.dataType == Res_value::TYPE_NULL) {
-      // Walk through the default style values looking for the requested
-      // attribute.
-      const ResTable::bag_entry* const def_style_attr_entry =
-          def_style_attr_finder.Find(cur_ident);
+    if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) {
+      // Walk through the default style values looking for the requested attribute.
+      const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident);
       if (def_style_attr_entry != def_style_attr_end) {
         // We found the attribute we were looking for.
         block = def_style_attr_entry->stringBlock;
         type_set_flags = style_type_set_flags;
         value = def_style_attr_entry->map.value;
         if (kDebugStyles) {
-          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType,
-                value.data);
+          ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
       }
     }
@@ -360,35 +341,29 @@
     uint32_t resid = 0;
     if (value.dataType != Res_value::TYPE_NULL) {
       // Take care of resolving the found resource to its final value.
-      ssize_t new_block = theme->resolveAttributeReference(
-          &value, block, &resid, &type_set_flags, &config);
+      ssize_t new_block =
+          theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config);
       if (new_block >= 0) {
         block = new_block;
       }
 
       if (kDebugStyles) {
-        ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType,
-              value.data);
+        ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
       }
-    } else {
-      // If we still don't have a value for this attribute, try to find
-      // it in the theme!
-      ssize_t new_block =
-          theme->getAttribute(cur_ident, &value, &type_set_flags);
+    } else if (value.data != Res_value::DATA_NULL_EMPTY) {
+      // If we still don't have a value for this attribute, try to find it in the theme!
+      ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags);
       if (new_block >= 0) {
         if (kDebugStyles) {
-          ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType,
-                value.data);
+          ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
-        new_block = res.resolveReference(&value, new_block, &resid,
-                                         &type_set_flags, &config);
+        new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config);
         if (new_block >= 0) {
           block = new_block;
         }
 
         if (kDebugStyles) {
-          ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType,
-                value.data);
+          ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
         }
       }
     }
@@ -404,8 +379,7 @@
     }
 
     if (kDebugStyles) {
-      ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident,
-            value.dataType, value.data);
+      ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data);
     }
 
     // Write the final value back to Java.
@@ -418,7 +392,7 @@
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
 
-    if (value.dataType != Res_value::TYPE_NULL) {
+    if (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY) {
       indices_idx++;
 
       // out_indices must NOT be nullptr.
@@ -502,7 +476,8 @@
     out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags;
     out_values[STYLE_DENSITY] = config.density;
 
-    if (out_indices != nullptr && value.dataType != Res_value::TYPE_NULL) {
+    if (out_indices != nullptr &&
+        (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY)) {
       indices_idx++;
       out_indices[indices_idx] = ii;
     }
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index f661f29b..bab8883 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -3538,7 +3538,8 @@
                     attrRes, bag->map.value.dataType, bag->map.value.data,
                     curEntry->value.dataType);
         }
-        if (force || curEntry->value.dataType == Res_value::TYPE_NULL) {
+        if (force || (curEntry->value.dataType == Res_value::TYPE_NULL
+                && curEntry->value.data != Res_value::DATA_NULL_EMPTY)) {
             curEntry->stringBlock = bag->stringBlock;
             curEntry->typeSpecFlags |= bagTypeSpecFlags;
             curEntry->value = bag->map.value;
@@ -3674,7 +3675,8 @@
                             }
                             ALOGW("Too many attribute references, stopped at: 0x%08x\n", resID);
                             return BAD_INDEX;
-                        } else if (type != Res_value::TYPE_NULL) {
+                        } else if (type != Res_value::TYPE_NULL
+                                || te.value.data == Res_value::DATA_NULL_EMPTY) {
                             *outValue = te.value;
                             return te.stringBlock;
                         }
@@ -5997,16 +5999,14 @@
     char locale[RESTABLE_MAX_LOCALE_LEN];
 
     forEachConfiguration(false, false, includeSystemLocales, [&](const ResTable_config& cfg) {
-        if (cfg.locale != 0) {
-            cfg.getBcp47Locale(locale, mergeEquivalentLangs /* canonicalize if merging */);
+        cfg.getBcp47Locale(locale, mergeEquivalentLangs /* canonicalize if merging */);
 
-            const auto beginIter = locales->begin();
-            const auto endIter = locales->end();
+        const auto beginIter = locales->begin();
+        const auto endIter = locales->end();
 
-            auto iter = std::lower_bound(beginIter, endIter, locale, compareString8AndCString);
-            if (iter == endIter || strcmp(iter->string(), locale) != 0) {
-                locales->insertAt(String8(locale), std::distance(beginIter, iter));
-            }
+        auto iter = std::lower_bound(beginIter, endIter, locale, compareString8AndCString);
+        if (iter == endIter || strcmp(iter->string(), locale) != 0) {
+            locales->insertAt(String8(locale), std::distance(beginIter, iter));
         }
     });
 }
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index d8e5abf..fcae53b 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -264,7 +264,7 @@
 
   const ResolvedBag* bag_two = assetmanager.GetBag(app::R::style::StyleTwo);
   ASSERT_NE(nullptr, bag_two);
-  ASSERT_EQ(5u, bag_two->entry_count);
+  ASSERT_EQ(6u, bag_two->entry_count);
 
   // attr_one is inherited from StyleOne.
   EXPECT_EQ(app::R::attr::attr_one, bag_two->entries[0].key);
@@ -295,6 +295,11 @@
   EXPECT_EQ(Res_value::TYPE_INT_DEC, bag_two->entries[4].value.dataType);
   EXPECT_EQ(3u, bag_two->entries[4].value.data);
   EXPECT_EQ(0, bag_two->entries[4].cookie);
+
+  EXPECT_EQ(app::R::attr::attr_empty, bag_two->entries[5].key);
+  EXPECT_EQ(Res_value::TYPE_NULL, bag_two->entries[5].value.dataType);
+  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, bag_two->entries[5].value.data);
+  EXPECT_EQ(0, bag_two->entries[5].cookie);
 }
 
 TEST_F(AssetManager2Test, ResolveReferenceToResource) {
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index 1ff2ed4..2d73ce8 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -69,8 +69,8 @@
   ResTable::Theme theme(table_);
   ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
 
-  std::array<uint32_t, 4> attrs{
-      {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}};
+  std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
+                                 R::attr::attr_four, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
 
   ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
@@ -109,11 +109,21 @@
   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+
+  // @empty comes from the theme, so it has the same asset cookie and changing configurations flags
+  // as the theme.
+  values_cursor += STYLE_NUM_ENTRIES;
+  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
+  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
+  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
+  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
+  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
+  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
 }
 
 TEST_F(AttributeResolutionXmlTest, XmlParser) {
-  std::array<uint32_t, 4> attrs{
-      {R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, R::attr::attr_four}};
+  std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
+                                 R::attr::attr_four, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
 
   ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
@@ -121,7 +131,7 @@
 
   uint32_t* values_cursor = values.data();
   EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
-  EXPECT_EQ(0u, values_cursor[STYLE_DATA]);
+  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
@@ -150,16 +160,24 @@
   EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
   EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+
+  values_cursor += STYLE_NUM_ENTRIES;
+  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
+  EXPECT_EQ(Res_value::DATA_NULL_UNDEFINED, values_cursor[STYLE_DATA]);
+  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
+  EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
+  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
+  EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
 }
 
 TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
   ResTable::Theme theme(table_);
   ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
 
-  std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
-                                 R::attr::attr_four, R::attr::attr_five}};
+  std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
+                                 R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}};
   std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
-  std::array<uint32_t, attrs.size()> indices;
+  std::array<uint32_t, attrs.size() + 1> indices;
 
   ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
              attrs.size(), values.data(), indices.data());
@@ -167,12 +185,12 @@
   const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
 
   uint32_t* values_cursor = values.data();
-  EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
-  EXPECT_EQ(1u, values_cursor[STYLE_DATA]);
+  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
+  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
   EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
-  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
+  EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]);
   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
-  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+  EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
 
   values_cursor += STYLE_NUM_ENTRIES;
   EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]);
@@ -203,6 +221,20 @@
   EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
   EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
   EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+
+  // @empty comes from the theme, so it has the same asset cookie and changing configurations flags
+  // as the theme.
+  values_cursor += STYLE_NUM_ENTRIES;
+  EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
+  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]);
+  EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
+  EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
+  EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
+  EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+
+  // The first element of indices contains the number of indices.
+  std::array<uint32_t, 7> expected_indices = {{6u, 0u, 1u, 2u, 3u, 4u, 5u}};
+  EXPECT_EQ(expected_indices, indices);
 }
 
 } // namespace android
diff --git a/libs/androidfw/tests/data/styles/R.h b/libs/androidfw/tests/data/styles/R.h
index 68527c7..05073a8 100644
--- a/libs/androidfw/tests/data/styles/R.h
+++ b/libs/androidfw/tests/data/styles/R.h
@@ -33,6 +33,7 @@
       attr_five = 0x7f010004u,
       attr_indirect = 0x7f010005u,
       attr_six = 0x7f010006u,
+      attr_empty = 0x7f010007u,
     };
   };
 
diff --git a/libs/androidfw/tests/data/styles/build b/libs/androidfw/tests/data/styles/build
index 81f78b1..1ef8e6e 100755
--- a/libs/androidfw/tests/data/styles/build
+++ b/libs/androidfw/tests/data/styles/build
@@ -2,4 +2,5 @@
 
 set -e
 
-aapt package -F styles.apk -M AndroidManifest.xml -S res -f
+aapt2 compile -o compiled.flata --dir res
+aapt2 link -o styles.apk --manifest AndroidManifest.xml compiled.flata
diff --git a/libs/androidfw/tests/data/styles/res/layout/layout.xml b/libs/androidfw/tests/data/styles/res/layout/layout.xml
index f3aa0f8..2c5e947 100644
--- a/libs/androidfw/tests/data/styles/res/layout/layout.xml
+++ b/libs/androidfw/tests/data/styles/res/layout/layout.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <View xmlns:app="http://schemas.android.com/apk/res-auto"
     app:attr_four="?attr/attr_indirect"
-    app:attr_three="10" />
-
+    app:attr_three="10"
+    app:attr_one="@empty" />
diff --git a/libs/androidfw/tests/data/styles/res/values/styles.xml b/libs/androidfw/tests/data/styles/res/values/styles.xml
index da592f8..3c90317 100644
--- a/libs/androidfw/tests/data/styles/res/values/styles.xml
+++ b/libs/androidfw/tests/data/styles/res/values/styles.xml
@@ -33,6 +33,12 @@
     <public type="attr" name="attr_indirect" id="0x7f010005" />
     <attr name="attr_indirect" />
 
+    <public type="attr" name="attr_six" id="0x7f010006" />
+    <attr name="attr_six" />
+
+    <public type="attr" name="attr_empty" id="0x7f010007" />
+    <attr name="attr_empty" />
+
     <public type="string" name="string_one" id="0x7f030000" />
     <string name="string_one">Hi</string>
 
@@ -48,11 +54,9 @@
         <item name="attr_two">"string"</item>
         <item name="attr_three">?attr/attr_indirect</item>
         <item name="attr_five">@string/string_one</item>
+        <item name="attr_empty">@empty</item>
     </style>
-    
-    <public type="attr" name="attr_six" id="0x7f010006" />
-    <attr name="attr_six" />
-    
+
     <public type="style" name="StyleThree" id="0x7f020002" />
     <style name="StyleThree">
         <item name="attr_six">6</item>
diff --git a/libs/androidfw/tests/data/styles/styles.apk b/libs/androidfw/tests/data/styles/styles.apk
index d4ccb83..72abf8f 100644
--- a/libs/androidfw/tests/data/styles/styles.apk
+++ b/libs/androidfw/tests/data/styles/styles.apk
Binary files differ
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index c157a47..a19726c 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1067,7 +1067,7 @@
         private void applyLevelLimits() {
             int[] sampleRates = null;
             Range<Integer> sampleRateRange = null, bitRates = null;
-            int maxChannels = 0;
+            int maxChannels = MAX_INPUT_CHANNEL_COUNT;
             String mime = mParent.getMimeType();
 
             if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_MPEG)) {
@@ -1160,6 +1160,8 @@
             if (info.containsKey("max-channel-count")) {
                 maxInputChannels = Utils.parseIntSafely(
                         info.getString("max-channel-count"), maxInputChannels);
+            } else if ((mParent.mError & ERROR_UNSUPPORTED) != 0) {
+                maxInputChannels = 0;
             }
             if (info.containsKey("bitrate-range")) {
                 bitRates = bitRates.intersect(
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/LinkAccessibilityHelper.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/LinkAccessibilityHelper.java
deleted file mode 100644
index 74b0c6b..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/LinkAccessibilityHelper.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settingslib.accessibility;
-
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
-import android.support.v4.widget.ExploreByTouchHelper;
-import android.text.Layout;
-import android.text.Spanned;
-import android.text.style.ClickableSpan;
-import android.util.Log;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.TextView;
-
-import java.util.List;
-
-/**
- * COPIED FROM SETUP WIZARD An accessibility delegate that allows {@link
- * android.text.style.ClickableSpan} to be focused and clicked by accessibility services.
- *
- * <p>Sample usage:
- *
- * <pre>
- * LinkAccessibilityHelper mAccessibilityHelper;
- *
- * private void init() {
- *     mAccessibilityHelper = new LinkAccessibilityHelper(myTextView);
- *     ViewCompat.setAccessibilityDelegate(myTextView, mLinkHelper);
- * }
- *
- * {@literal @}Override
- * protected boolean dispatchHoverEvent({@literal @}NonNull MotionEvent event) {
- *     if (mAccessibilityHelper != null && mAccessibilityHelper.dispatchHoverEvent(event)) {
- *         return true;
- *     }
- *     return super.dispatchHoverEvent(event);
- * }
- * </pre>
- *
- * @see android.support.v4.widget.ExploreByTouchHelper
- */
-public class LinkAccessibilityHelper extends ExploreByTouchHelper {
-
-    private static final String TAG = "LinkAccessibilityHelper";
-
-    private final TextView mView;
-    private final Rect mTempRect = new Rect();
-
-    public LinkAccessibilityHelper(TextView view) {
-        super(view);
-        mView = view;
-    }
-
-    @Override
-    protected int getVirtualViewAt(float x, float y) {
-        final CharSequence text = mView.getText();
-        if (text instanceof Spanned) {
-            final Spanned spannedText = (Spanned) text;
-            final int offset = getOffsetForPosition(mView, x, y);
-            ClickableSpan[] linkSpans = spannedText.getSpans(offset, offset, ClickableSpan.class);
-            if (linkSpans.length == 1) {
-                ClickableSpan linkSpan = linkSpans[0];
-                return spannedText.getSpanStart(linkSpan);
-            }
-        }
-        return INVALID_ID;
-    }
-
-    @Override
-    protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
-        final CharSequence text = mView.getText();
-        if (text instanceof Spanned) {
-            final Spanned spannedText = (Spanned) text;
-            ClickableSpan[] linkSpans =
-                    spannedText.getSpans(0, spannedText.length(), ClickableSpan.class);
-            for (ClickableSpan span : linkSpans) {
-                virtualViewIds.add(spannedText.getSpanStart(span));
-            }
-        }
-    }
-
-    @Override
-    protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
-        final ClickableSpan span = getSpanForOffset(virtualViewId);
-        if (span != null) {
-            event.setContentDescription(getTextForSpan(span));
-        } else {
-            Log.e(TAG, "LinkSpan is null for offset: " + virtualViewId);
-            event.setContentDescription(mView.getText());
-        }
-    }
-
-    @Override
-    protected void onPopulateNodeForVirtualView(
-            int virtualViewId, AccessibilityNodeInfoCompat info) {
-        final ClickableSpan span = getSpanForOffset(virtualViewId);
-        if (span != null) {
-            info.setContentDescription(getTextForSpan(span));
-        } else {
-            Log.e(TAG, "LinkSpan is null for offset: " + virtualViewId);
-            info.setContentDescription(mView.getText());
-        }
-        info.setFocusable(true);
-        info.setClickable(true);
-        getBoundsForSpan(span, mTempRect);
-        if (mTempRect.isEmpty()) {
-            Log.e(TAG, "LinkSpan bounds is empty for: " + virtualViewId);
-            mTempRect.set(0, 0, 1, 1);
-        }
-        info.setBoundsInParent(mTempRect);
-        info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
-    }
-
-    @Override
-    protected boolean onPerformActionForVirtualView(
-            int virtualViewId, int action, Bundle arguments) {
-        if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
-            ClickableSpan span = getSpanForOffset(virtualViewId);
-            if (span != null) {
-                span.onClick(mView);
-                return true;
-            } else {
-                Log.e(TAG, "LinkSpan is null for offset: " + virtualViewId);
-            }
-        }
-        return false;
-    }
-
-    private ClickableSpan getSpanForOffset(int offset) {
-        CharSequence text = mView.getText();
-        if (text instanceof Spanned) {
-            Spanned spannedText = (Spanned) text;
-            ClickableSpan[] spans = spannedText.getSpans(offset, offset, ClickableSpan.class);
-            if (spans.length == 1) {
-                return spans[0];
-            }
-        }
-        return null;
-    }
-
-    private CharSequence getTextForSpan(ClickableSpan span) {
-        CharSequence text = mView.getText();
-        if (text instanceof Spanned) {
-            Spanned spannedText = (Spanned) text;
-            return spannedText.subSequence(
-                    spannedText.getSpanStart(span), spannedText.getSpanEnd(span));
-        }
-        return text;
-    }
-
-    // Find the bounds of a span. If it spans multiple lines, it will only return the bounds for the
-    // section on the first line.
-    private Rect getBoundsForSpan(ClickableSpan span, Rect outRect) {
-        CharSequence text = mView.getText();
-        outRect.setEmpty();
-        if (text instanceof Spanned) {
-            final Layout layout = mView.getLayout();
-            if (layout != null) {
-                Spanned spannedText = (Spanned) text;
-                final int spanStart = spannedText.getSpanStart(span);
-                final int spanEnd = spannedText.getSpanEnd(span);
-                final float xStart = layout.getPrimaryHorizontal(spanStart);
-                final float xEnd = layout.getPrimaryHorizontal(spanEnd);
-                final int lineStart = layout.getLineForOffset(spanStart);
-                final int lineEnd = layout.getLineForOffset(spanEnd);
-                layout.getLineBounds(lineStart, outRect);
-                if (lineEnd == lineStart) {
-                    // If the span is on a single line, adjust both the left and right bounds
-                    // so outrect is exactly bounding the span.
-                    outRect.left = (int) Math.min(xStart, xEnd);
-                    outRect.right = (int) Math.max(xStart, xEnd);
-                } else {
-                    // If the span wraps across multiple lines, only use the first line (as returned
-                    // by layout.getLineBounds above), and adjust the "start" of outrect to where
-                    // the span starts, leaving the "end" of outrect at the end of the line.
-                    // ("start" being left for LTR, and right for RTL)
-                    if (layout.getParagraphDirection(lineStart) == Layout.DIR_RIGHT_TO_LEFT) {
-                        outRect.right = (int) xStart;
-                    } else {
-                        outRect.left = (int) xStart;
-                    }
-                }
-
-                // Offset for padding
-                outRect.offset(mView.getTotalPaddingLeft(), mView.getTotalPaddingTop());
-            }
-        }
-        return outRect;
-    }
-
-    // Compat implementation of TextView#getOffsetForPosition().
-
-    private static int getOffsetForPosition(TextView view, float x, float y) {
-        if (view.getLayout() == null) return -1;
-        final int line = getLineAtCoordinate(view, y);
-        return getOffsetAtCoordinate(view, line, x);
-    }
-
-    private static float convertToLocalHorizontalCoordinate(TextView view, float x) {
-        x -= view.getTotalPaddingLeft();
-        // Clamp the position to inside of the view.
-        x = Math.max(0.0f, x);
-        x = Math.min(view.getWidth() - view.getTotalPaddingRight() - 1, x);
-        x += view.getScrollX();
-        return x;
-    }
-
-    private static int getLineAtCoordinate(TextView view, float y) {
-        y -= view.getTotalPaddingTop();
-        // Clamp the position to inside of the view.
-        y = Math.max(0.0f, y);
-        y = Math.min(view.getHeight() - view.getTotalPaddingBottom() - 1, y);
-        y += view.getScrollY();
-        return view.getLayout().getLineForVertical((int) y);
-    }
-
-    private static int getOffsetAtCoordinate(TextView view, int line, float x) {
-        x = convertToLocalHorizontalCoordinate(view, x);
-        return view.getLayout().getOffsetForHorizontal(line, x);
-    }
-}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/LinkTextView.java b/packages/SettingsLib/src/com/android/settingslib/widget/LinkTextView.java
index da86536..8b9315c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/widget/LinkTextView.java
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/LinkTextView.java
@@ -16,32 +16,25 @@
 package com.android.settingslib.widget;
 
 import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.v4.view.ViewCompat;
 import android.text.Spanned;
 import android.text.method.LinkMovementMethod;
 import android.text.style.ClickableSpan;
 import android.util.AttributeSet;
-import android.view.MotionEvent;
 import android.widget.TextView;
-import com.android.settingslib.accessibility.LinkAccessibilityHelper;
+
 /**
- * Copied from setup wizard. This TextView performs two functions. The first is to make it so the
- * link behaves properly and becomes clickable. The second is that it makes the link visible to
- * accessibility services.
+ * Copied from setup wizard. This TextView performed two functions. The first is to make it so the
+ * link behaves properly and becomes clickable. The second was that it made the link visible to
+ * accessibility services, but from O forward support for links is provided natively.
  */
 public class LinkTextView extends TextView {
 
-    private LinkAccessibilityHelper mAccessibilityHelper;
-
     public LinkTextView(Context context) {
         this(context, null);
     }
 
     public LinkTextView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mAccessibilityHelper = new LinkAccessibilityHelper(this);
-        ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
     }
 
     @Override
@@ -55,12 +48,4 @@
             }
         }
     }
-
-    @Override
-    protected boolean dispatchHoverEvent(@NonNull MotionEvent event) {
-        if (mAccessibilityHelper.dispatchHoverEvent(event)) {
-            return true;
-        }
-        return super.dispatchHoverEvent(event);
-    }
 }
\ No newline at end of file
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index f475361..9309359 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1434,6 +1434,9 @@
         dumpSetting(s, p,
                 Settings.Secure.DEVICE_PAIRED,
                 SecureSettingsProto.DEVICE_PAIRED);
+        dumpSetting(s, p,
+                Settings.Secure.NOTIFICATION_BADGING,
+                SecureSettingsProto.NOTIFICATION_BADGING);
     }
 
     private static void dumpProtoSystemSettingsLocked(
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 69d9de9..e3ef873 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -305,7 +305,6 @@
                   android:excludeFromRecents="true"
                   android:stateNotNeeded="true"
                   android:resumeWhilePausing="true"
-                  android:screenOrientation="behind"
                   android:resizeableActivity="true"
                   android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden"
                   android:theme="@style/RecentsTheme.Wallpaper">
diff --git a/packages/SystemUI/res/drawable/stat_sys_cast.xml b/packages/SystemUI/res/drawable/stat_sys_cast.xml
index 4a7cbb3..5228085 100644
--- a/packages/SystemUI/res/drawable/stat_sys_cast.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_cast.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -18,11 +18,11 @@
     android:insetRight="2.5dp">
     <vector android:width="17dp"
             android:height="17dp"
-            android:viewportWidth="48.0"
-            android:viewportHeight="48.0">
+            android:viewportWidth="17.0"
+            android:viewportHeight="17.0">
 
         <path
             android:fillColor="#FFFFFFFF"
-            android:pathData="M2.0,36.0l0.0,6.0l6.0,0.0C8.0,38.7 5.3,36.0 2.0,36.0zM2.0,28.0l0.0,4.0c5.5,0.0 10.0,4.5 10.0,10.0l4.0,0.0C16.0,34.3 9.7,28.0 2.0,28.0zM38.0,14.0L10.0,14.0l0.0,3.3c7.9,2.6 14.2,8.8 16.7,16.7L38.0,34.0L38.0,14.0zM2.0,20.0l0.0,4.0c9.9,0.0 18.0,8.1 18.0,18.0l4.0,0.0C24.0,29.8 14.1,20.0 2.0,20.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,6.0l4.0,0.0l0.0,-6.0l36.0,0.0l0.0,28.0L28.0,38.0l0.0,4.0l14.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0z"/>
+            android:pathData="M0.71,12.75v1.42c0,0.39 0.32,0.71 0.71,0.71h1.42C2.83,13.7 1.88,12.75 0.71,12.75zM0.69,10.67c-0.01,0.36 0.25,0.66 0.6,0.72c1.47,0.26 2.65,1.42 2.9,2.89c0.06,0.34 0.35,0.6 0.7,0.6c0.43,0 0.77,-0.38 0.71,-0.81c-0.34,-2.11 -2,-3.76 -4.11,-4.09C1.08,9.91 0.7,10.24 0.69,10.67zM13.46,4.96H3.54v1.15c2.81,0.91 5.02,3.12 5.93,5.93h3.99V4.96zM0.69,7.81C0.68,8.18 0.95,8.49 1.31,8.53c3.02,0.3 5.44,2.71 5.74,5.72c0.04,0.35 0.34,0.62 0.7,0.62c0.42,0 0.75,-0.36 0.71,-0.78c-0.37,-3.69 -3.3,-6.62 -6.99,-6.98C1.06,7.08 0.7,7.4 0.69,7.81zM14.88,2.12H2.12c-0.78,0 -1.42,0.64 -1.42,1.42v2.12h1.42V3.54h12.75v9.92H9.92v1.42h4.96c0.78,0 1.42,-0.64 1.42,-1.42V3.54C16.29,2.76 15.65,2.12 14.88,2.12z" />
     </vector>
 </inset>
diff --git a/packages/SystemUI/res/drawable/stat_sys_hotspot.xml b/packages/SystemUI/res/drawable/stat_sys_hotspot.xml
index 01e8888..5dcf5c8 100644
--- a/packages/SystemUI/res/drawable/stat_sys_hotspot.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_hotspot.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -19,11 +19,14 @@
     <vector
         android:width="17.0dp"
         android:height="17.0dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
-
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M24.000000,22.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000C28.000000,23.799999 26.200001,22.000000 24.000000,22.000000zM36.000000,26.000000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-6.600000,0.000000 -12.000000,5.400000 -12.000000,12.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-4.400000 3.600000,-8.000000 8.000000,-8.000000s8.000000,3.600000 8.000000,8.000000c0.000000,3.000000 -1.600000,5.500000 -4.000000,6.900000l2.000000,3.500000C33.599998,34.299999 36.000000,30.400000 36.000000,26.000000zM24.000000,6.000000C13.000000,6.000000 4.000000,15.000000 4.000000,26.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-8.800000 7.200000,-16.000000 16.000000,-16.000000s16.000000,7.200000 16.000000,16.000000c0.000000,5.900000 -3.200000,11.100000 -8.000000,13.800000l2.000000,3.500000c6.000000,-3.500000 10.000000,-9.900000 10.000000,-17.299999C44.000000,15.000000 35.000000,6.000000 24.000000,6.000000z"/>
+        android:viewportWidth="18.0"
+        android:viewportHeight="18.0">
+      <group
+          android:translateX="0.5"
+          android:translateY="0.5" >
+          <path
+              android:pathData="M8.5,7.79c-0.78,0 -1.42,0.64 -1.42,1.42c0,0.78 0.64,1.42 1.42,1.42s1.42,-0.64 1.42,-1.42C9.92,8.43 9.28,7.79 8.5,7.79zM12.75,9.21c0,-2.35 -1.9,-4.25 -4.25,-4.25c-0.18,0 -0.35,0.01 -0.53,0.03C6.11,5.22 4.58,6.7 4.3,8.55c-0.23,1.52 0.35,2.91 1.36,3.82C6,12.67 6.54,12.6 6.76,12.2c0.17,-0.3 0.1,-0.67 -0.16,-0.89c-0.78,-0.7 -1.12,-1.77 -0.86,-2.79C5.99,7.5 6.78,6.71 7.8,6.46C9.32,6.08 10.86,7 11.25,8.52c0.06,0.23 0.09,0.46 0.09,0.69c0,0.84 -0.36,1.58 -0.94,2.1c-0.25,0.23 -0.33,0.6 -0.16,0.9c0.22,0.38 0.74,0.49 1.06,0.2C12.22,11.6 12.75,10.43 12.75,9.21zM7.63,1.85C4.19,2.24 1.42,5.07 1.1,8.52c-0.26,2.61 0.88,5.15 2.99,6.7c0.36,0.26 0.86,0.15 1.09,-0.23c0.19,-0.32 0.1,-0.74 -0.19,-0.96c-1.7,-1.26 -2.71,-3.38 -2.35,-5.73c0.4,-2.6 2.57,-4.68 5.19,-4.97c3.59,-0.41 6.63,2.4 6.63,5.91c0,1.97 -0.96,3.7 -2.43,4.79c-0.3,0.22 -0.38,0.63 -0.19,0.96c0.22,0.39 0.73,0.49 1.09,0.23c1.9,-1.4 3.03,-3.62 3.03,-5.98C15.94,4.84 12.12,1.34 7.63,1.85z"
+              android:fillColor="#FFFFFFFF"/>
+      </group>
     </vector>
 </inset>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
index 2de2e36..b3cd455 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2017 The Android Open Source Project
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -16,12 +16,16 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
         android:height="18.41dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+        android:viewportWidth="21.2"
+        android:viewportHeight="21.2">
+      <group
+          android:translateX="0.5"
+          android:translateY="2.0">
+        <path
+            android:pathData="M18.79,9.79c-0.32,-0.32 -0.83,-0.32 -1.15,0L16.43,11l-1.21,-1.21c-0.32,-0.32 -0.83,-0.32 -1.15,0L14.06,9.8l0,0c-0.32,0.32 -0.32,0.83 0,1.15l1.21,1.21l-1.21,1.21l0,0c-0.32,0.32 -0.32,0.83 0,1.15l0.01,0.01c0.32,0.32 0.83,0.32 1.15,0l1.21,-1.21l1.21,1.21c0.32,0.32 0.83,0.32 1.15,0c0.32,-0.32 0.32,-0.83 0,-1.15l-1.21,-1.21l1.21,-1.21C19.1,10.64 19.1,10.13 18.79,9.79z"
+            android:fillColor="?attr/fillColor"/>
+        <path
+            android:pathData="M11.69,7.44h6.27L19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56c-1.6,-1.05 -5.04,-2.9 -9.62,-2.9c-4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0l0.78,-0.96V7.44z"
+            android:fillColor="?attr/backgroundColor"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0_fully.xml
index 60f7eb6..6c0fad8 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0_fully.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,11 +14,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+    android:width="18.41dp"
+    android:height="17dp"
+    android:viewportWidth="21.66"
+    android:viewportHeight="20">
+    <group
+        android:translateX="0.74"
+        android:translateY="1.2">
+        <path
+            android:pathData="M19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56 -1.6,-1.05 -5.04,-2.9 -9.62,-2.9 -4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0L19.95,5z"
+            android:fillColor="?attr/backgroundColor"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
index 144a7c1..2ebbaf2 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2017 The Android Open Source Project
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,17 +14,21 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18.41dp"
-        android:height="18.41dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
-        android:fillColor="?attr/fillColor"/>
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+    android:width="18.41dp"
+    android:height="18.41dp"
+    android:viewportWidth="21.7"
+    android:viewportHeight="21.7">
+    <group
+        android:translateY="2.2"
+        android:translateX="0.75">
+        <path
+            android:pathData="M11.69,7.44h6.27L19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56c-1.6,-1.05 -5.04,-2.9 -9.62,-2.9c-4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0l0.78,-0.96V7.44z"
+            android:fillColor="?attr/backgroundColor" />
+        <path
+            android:pathData="M5.02,10.86l4.25,5.21c0.42,0.52 1.22,0.52 1.64,0l0.78,-0.96V9.14c-0.51,-0.11 -1.05,-0.17 -1.59,-0.17C8.15,8.97 6.37,9.69 5.02,10.86z"
+            android:fillColor="?attr/fillColor" />
+        <path
+            android:pathData="M17.57,12.17l1.21,-1.21c0.32,-0.32 0.32,-0.83 0,-1.17c-0.32,-0.32 -0.83,-0.32 -1.15,0L16.43,11l-1.21,-1.21c-0.32,-0.32 -0.83,-0.32 -1.15,0L14.06,9.8c-0.32,0.32 -0.32,0.83 0,1.15l1.21,1.21l-1.21,1.21c-0.32,0.32 -0.32,0.83 0,1.15l0.01,0.01c0.32,0.32 0.83,0.32 1.15,0l1.21,-1.21l1.21,1.21c0.32,0.32 0.83,0.32 1.15,0c0.32,-0.32 0.32,-0.83 0,-1.15L17.57,12.17z"
+            android:fillColor="?attr/fillColor" />
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1_fully.xml
index 554350d..eaead9b 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1_fully.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,14 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M13.100000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.500000,6.500000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M13.100000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000L13.100000,22.000000z"/>
+    android:width="18.41dp"
+    android:height="17dp"
+    android:viewportWidth="21.66"
+    android:viewportHeight="20.0">
+    <group
+        android:translateX="0.79"
+        android:translateY="1.2">
+        <path
+            android:pathData="M19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56 -1.6,-1.05 -5.04,-2.9 -9.62,-2.9 -4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0L19.95,5z"
+            android:fillColor="?attr/backgroundColor"/>
+        <path
+            android:pathData="M10.1,8.97c-1.95,0 -3.72,0.72 -5.08,1.9l4.25,5.21c0.42,0.52 1.22,0.52 1.64,0l4.26,-5.22a7.702,7.702 0,0 0,-5.07 -1.89z"
+            android:fillColor="?attr/fillColor"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
index 6b7f712..809147c 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2017 The Android Open Source Project
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,17 +14,21 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18.41dp"
-        android:height="18.41dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
-        android:fillColor="?attr/fillColor"/>
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+    android:width="18.41dp"
+    android:height="18.41dp"
+    android:viewportWidth="21.7"
+    android:viewportHeight="21.7">
+    <group
+        android:translateX="0.75"
+        android:translateY="2.2" >
+        <path
+            android:pathData="M11.69,7.44h6.27L19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56c-1.6,-1.05 -5.04,-2.9 -9.62,-2.9c-4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0l0.78,-0.96V7.44z"
+            android:fillColor="?attr/backgroundColor"/>
+        <path
+            android:pathData="M10.09,6.44c-2.55,0 -4.88,0.93 -6.68,2.45l5.85,7.18c0.42,0.52 1.22,0.52 1.64,0l0.78,-0.96V7.44h2.84C13.18,6.8 11.68,6.44 10.09,6.44z"
+            android:fillColor="?attr/fillColor"/>
+        <path
+            android:pathData="M17.57,12.17l1.21,-1.21c0.32,-0.32 0.32,-0.83 0,-1.17c-0.32,-0.32 -0.83,-0.32 -1.15,0L16.43,11l-1.21,-1.21c-0.32,-0.32 -0.83,-0.32 -1.15,0L14.06,9.8c-0.32,0.32 -0.32,0.83 0,1.15l1.21,1.21l-1.21,1.21c-0.32,0.32 -0.32,0.83 0,1.15l0.01,0.01c0.32,0.32 0.83,0.32 1.15,0l1.21,-1.21l1.21,1.21c0.32,0.32 0.83,0.32 1.15,0c0.32,-0.32 0.32,-0.83 0,-1.15L17.57,12.17z"
+            android:fillColor="?attr/fillColor"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2_fully.xml
index 2c2465a..6d4fb77 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2_fully.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,14 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M13.000000,22.000000l7.600000,-9.400000C20.299999,12.400000 17.400000,10.000000 13.000000,10.000000s-7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+android:width="18.41dp"
+android:height="17dp"
+android:viewportWidth="21.86"
+android:viewportHeight="20.19">
+    <group
+        android:translateX="0.85"
+        android:translateY="1.4" >
+        <path
+            android:pathData="M19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56 -1.6,-1.05 -5.04,-2.9 -9.62,-2.9 -4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0L19.95,5z"
+            android:fillColor="?attr/backgroundColor" />
+        <path
+            android:pathData="M10.09,6.44c-2.55,0 -4.88,0.93 -6.68,2.45l5.85,7.18c0.42,0.52 1.22,0.52 1.64,0l5.86,-7.19a10.284,10.284 0,0 0,-6.67 -2.44z"
+            android:fillColor="?attr/fillColor" />
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
index d34b4de..4c479c0 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2017 The Android Open Source Project
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -16,15 +16,19 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="18.41dp"
         android:height="18.41dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/fillColor"/>
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/backgroundColor"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="?attr/fillColor"/>
+        android:viewportWidth="21.7"
+        android:viewportHeight="21.7">
+    <group
+            android:translateX="0.75"
+            android:translateY="2.3" >
+        <path
+            android:pathData="M11.69,7.44h6.27L19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56c-1.6,-1.05 -5.04,-2.9 -9.62,-2.9c-4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0l0.78,-0.96V7.44z"
+            android:fillColor="?attr/backgroundColor"/>
+        <path
+            android:pathData="M10.08,4.75c-2.96,0 -5.66,1.06 -7.74,2.82l6.93,8.5c0.21,0.26 0.51,0.39 0.82,0.39c0.22,0 0.44,-0.07 0.63,-0.2c0.07,-0.05 0.14,-0.11 0.2,-0.19l0.78,-0.96V7.44h5.98C15.6,5.77 12.96,4.75 10.08,4.75z"
+            android:fillColor="?attr/fillColor"/>
+        <path
+            android:pathData="M17.57,12.17l1.21,-1.21c0.32,-0.32 0.32,-0.83 0,-1.17c-0.32,-0.32 -0.83,-0.32 -1.15,0L16.43,11l-1.21,-1.21c-0.32,-0.32 -0.83,-0.32 -1.15,0L14.06,9.8c-0.32,0.32 -0.32,0.83 0,1.15l1.21,1.21l-1.21,1.21c-0.32,0.32 -0.32,0.83 0,1.15l0.01,0.01c0.32,0.32 0.83,0.32 1.15,0l1.21,-1.21l1.21,1.21c0.32,0.32 0.83,0.32 1.15,0c0.32,-0.32 0.32,-0.83 0,-1.15L17.57,12.17z"
+            android:fillColor="?attr/fillColor"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3_fully.xml
index 7d0f756..6c96300 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3_fully.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,14 +14,18 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/backgroundColor"
-        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
-    <path
-        android:fillColor="?attr/fillColor"
-        android:pathData="M13.000000,22.000000l9.200000,-11.400000c-0.400000,-0.300000 -3.900000,-3.200000 -9.200000,-3.200000s-8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+    android:width="18.41dp"
+    android:height="17dp"
+    android:viewportWidth="21.80"
+    android:viewportHeight="20.1">
+    <group
+        android:translateX="0.81"
+        android:translateY="1.29" >
+        <path
+            android:pathData="M19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56 -1.6,-1.05 -5.04,-2.9 -9.62,-2.9 -4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0L19.95,5z"
+            android:fillColor="?attr/backgroundColor"/>
+        <path
+            android:pathData="M10.08,4.75c-2.96,0 -5.66,1.06 -7.74,2.82l6.93,8.5c0.21,0.26 0.51,0.39 0.82,0.39 0.23,0 0.46,-0.07 0.65,-0.22 -0.02,0.02 -0.04,0.03 -0.07,0.05 0.09,-0.06 0.17,-0.13 0.24,-0.22l6.93,-8.5c-2.09,-1.74 -4.8,-2.82 -7.76,-2.82z"
+            android:fillColor="?attr/fillColor"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
index 7d1bfe1..8fb7a7b 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    Copyright (C) 2017 The Android Open Source Project
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,14 +14,16 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18.41dp"
-        android:height="18.41dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
-        android:fillColor="?attr/singleToneColor"/>
-    <path
-        android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
-        android:fillColor="?attr/singleToneColor"/>
+    android:width="18.41dp"
+    android:height="18.41dp"
+    android:viewportWidth="21.95"
+    android:viewportHeight="21.65">
+    <group
+        android:translateX="0.90"
+        android:translateY="2.25"
+        >
+        <path
+            android:pathData="M11.69,15.12l-0.78,0.96c-0.43,0.52 -1.22,0.52 -1.64,0L0.24,5c-0.4,-0.49 -0.29,-1.22 0.23,-1.56c1.59,-1.05 5.03,-2.9 9.62,-2.9c4.59,0 8.02,1.85 9.62,2.9c0.53,0.35 0.63,1.08 0.23,1.56l-1.99,2.44h-6.27V15.12zM18.79,9.79c-0.32,-0.32 -0.83,-0.32 -1.15,0L16.43,11l-1.21,-1.21c-0.32,-0.32 -0.83,-0.32 -1.15,0L14.06,9.8l0,0c-0.32,0.32 -0.32,0.83 0,1.15l1.21,1.21l-1.21,1.21l0,0c-0.32,0.32 -0.32,0.83 0,1.15l0.01,0.01c0.32,0.32 0.83,0.32 1.15,0l1.21,-1.21l1.21,1.21c0.32,0.32 0.83,0.32 1.15,0c0.32,-0.32 0.32,-0.83 0,-1.15l-1.21,-1.21l1.21,-1.21C19.1,10.64 19.1,10.13 18.79,9.79z"
+            android:fillColor="?attr/singleToneColor"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4_fully.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4_fully.xml
index a7e213f..bc3fdb5 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4_fully.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
 
    Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -14,11 +14,15 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="18.41dp"
-        android:height="17dp"
-        android:viewportWidth="26.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="?attr/singleToneColor"
-        android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+    android:width="18.41dp"
+    android:height="17dp"
+    android:viewportWidth="21.75"
+    android:viewportHeight="20.0">
+    <group
+        android:translateX="0.80"
+        android:translateY="1.25">
+        <path
+            android:pathData="M19.95,5c0.4,-0.49 0.3,-1.22 -0.23,-1.56 -1.6,-1.05 -5.04,-2.9 -9.62,-2.9 -4.59,0 -8.03,1.85 -9.62,2.9C-0.05,3.78 -0.16,4.51 0.24,5l9.02,11.08c0.42,0.52 1.22,0.52 1.64,0L19.95,5z"
+            android:fillColor="?attr/singleToneColor"/>
+    </group>
 </vector>
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index bdc0871..da2d38f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -73,7 +73,8 @@
             mTouchHandler.onActivityPinned();
             mMediaController.onActivityPinned();
             mMenuController.onActivityPinned();
-            mNotificationController.onActivityPinned(packageName);
+            mNotificationController.onActivityPinned(packageName,
+                    true /* deferUntilAnimationEnds */);
 
             SystemServicesProxy.getInstance(mContext).setPipVisibility(true);
         }
@@ -104,6 +105,7 @@
             mTouchHandler.setTouchEnabled(true);
             mTouchHandler.onPinnedStackAnimationEnded();
             mMenuController.onPinnedStackAnimationEnded();
+            mNotificationController.onPinnedStackAnimationEnded();
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java
index 53746e2..696fdbc 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java
@@ -60,6 +60,9 @@
 
     private PipMotionHelper mMotionHelper;
 
+    // Used when building a deferred notification
+    private String mDeferredNotificationPackageName;
+
     private AppOpsManager.OnOpChangedListener mAppOpsChangedListener = new OnOpChangedListener() {
         @Override
         public void onOpChanged(String op, String packageName) {
@@ -87,10 +90,47 @@
         mMotionHelper = motionHelper;
     }
 
-    public void onActivityPinned(String packageName) {
+    public void onActivityPinned(String packageName, boolean deferUntilAnimationEnds) {
         // Clear any existing notification
         mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
 
+        if (deferUntilAnimationEnds) {
+            mDeferredNotificationPackageName = packageName;
+        } else {
+            showNotificationForApp(mDeferredNotificationPackageName);
+        }
+
+        // Register for changes to the app ops setting for this package while it is in PiP
+        registerAppOpsListener(packageName);
+    }
+
+    public void onPinnedStackAnimationEnded() {
+        if (mDeferredNotificationPackageName != null) {
+            showNotificationForApp(mDeferredNotificationPackageName);
+            mDeferredNotificationPackageName = null;
+        }
+    }
+
+    public void onActivityUnpinned(ComponentName topPipActivity) {
+        // Unregister for changes to the previously PiP'ed package
+        unregisterAppOpsListener();
+
+        // Reset the deferred notification package
+        mDeferredNotificationPackageName = null;
+
+        if (topPipActivity != null) {
+            // onActivityUnpinned() is only called after the transition is complete, so we don't
+            // need to defer until the animation ends to update the notification
+            onActivityPinned(topPipActivity.getPackageName(), false /* deferUntilAnimationEnds */);
+        } else {
+            mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
+        }
+    }
+
+    /**
+     * Builds and shows the notification for the given app.
+     */
+    private void showNotificationForApp(String packageName) {
         // Build a new notification
         final Notification.Builder builder =
                 new Notification.Builder(mContext, NotificationChannels.GENERAL)
@@ -105,20 +145,6 @@
             // Show the new notification
             mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, builder.build());
         }
-
-        // Register for changes to the app ops setting for this package while it is in PiP
-        registerAppOpsListener(packageName);
-    }
-
-    public void onActivityUnpinned(ComponentName topPipActivity) {
-        // Unregister for changes to the previously PiP'ed package
-        unregisterAppOpsListener();
-
-        if (topPipActivity != null) {
-            onActivityPinned(topPipActivity.getPackageName());
-        } else {
-            mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
-        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 7518527a..e457d72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -77,6 +77,9 @@
 
         BatteryMeterView battery = findViewById(R.id.battery);
         battery.setForceShowPercent(true);
+        // Don't show the Wi-Fi indicator here, because it is shown just below in the tile.
+        SignalClusterView signalCluster = findViewById(R.id.signal_cluster);
+        signalCluster.setForceBlockWifi();
 
         mActivityStarter = Dependency.get(ActivityStarter.class);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 90c65580..8f24ec7 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -767,17 +767,22 @@
             mDockedStackMinimized = minimized;
         } else if (mDockedStackMinimized != minimized) {
             mIsInMinimizeInteraction = true;
-            if (minimized && (mCurrentAnimator == null || !mCurrentAnimator.isRunning())) {
+            if (minimized && (mCurrentAnimator == null || !mCurrentAnimator.isRunning())
+                    && (mDividerPositionBeforeMinimized <= 0 || !mAdjustedForIme)) {
                 mDividerPositionBeforeMinimized = getCurrentPosition();
             }
             mMinimizedSnapAlgorithm = null;
             mDockedStackMinimized = minimized;
             initializeSnapAlgorithm();
-            stopDragging(getCurrentPosition(), minimized ?
-                            mMinimizedSnapAlgorithm.getMiddleTarget() :
-                            mSnapAlgorithm.calculateNonDismissingSnapTarget(
+            stopDragging(minimized
+                            ? mDividerPositionBeforeMinimized
+                            : getCurrentPosition(),
+                    minimized
+                            ? mMinimizedSnapAlgorithm.getMiddleTarget()
+                            : mSnapAlgorithm.calculateNonDismissingSnapTarget(
                                     mDividerPositionBeforeMinimized),
                     animDuration, Interpolators.FAST_OUT_SLOW_IN, 0);
+            setAdjustedForIme(false, animDuration);
         }
         if (!minimized) {
             mBackground.animate().withEndAction(mResetBackgroundRunnable);
@@ -820,6 +825,9 @@
                 .setDuration(animDuration)
                 .start();
         mAdjustedForIme = adjustedForIme;
+        if (mHomeStackResizable && adjustedForIme) {
+            mDividerPositionBeforeMinimized = getCurrentPosition();
+        }
     }
 
     private void resetBackground() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 30ff30f..be221bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -341,14 +341,12 @@
 
     public void appTransitionPending(boolean forced) {
         synchronized (mLock) {
-            mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
             mHandler.obtainMessage(MSG_APP_TRANSITION_PENDING, forced ? 1 : 0, 0).sendToTarget();
         }
     }
 
     public void appTransitionCancelled() {
         synchronized (mLock) {
-            mHandler.removeMessages(MSG_APP_TRANSITION_CANCELLED);
             mHandler.sendEmptyMessage(MSG_APP_TRANSITION_CANCELLED);
         }
     }
@@ -359,7 +357,6 @@
 
     public void appTransitionStarting(long startTime, long duration, boolean forced) {
         synchronized (mLock) {
-            mHandler.removeMessages(MSG_APP_TRANSITION_STARTING);
             mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, forced ? 1 : 0, 0,
                     Pair.create(startTime, duration)).sendToTarget();
         }
@@ -368,7 +365,6 @@
     @Override
     public void appTransitionFinished() {
         synchronized (mLock) {
-            mHandler.removeMessages(MSG_APP_TRANSITION_FINISHED);
             mHandler.sendEmptyMessage(MSG_APP_TRANSITION_FINISHED);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index dc254f9..28a858c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -120,6 +120,7 @@
     private boolean mBlockWifi;
     private boolean mBlockEthernet;
     private boolean mActivityEnabled;
+    private boolean mForceBlockWifi;
 
     public SignalClusterView(Context context) {
         this(context, null);
@@ -151,6 +152,16 @@
         updateActivityEnabled();
     }
 
+    public void setForceBlockWifi() {
+        mForceBlockWifi = true;
+        mBlockWifi = true;
+        if (isAttachedToWindow()) {
+            // Re-register to get new callbacks.
+            mNetworkController.removeCallback(this);
+            mNetworkController.addCallback(this);
+        }
+    }
+
     @Override
     public void onTuningChanged(String key, String newValue) {
         if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
@@ -167,7 +178,7 @@
             mBlockAirplane = blockAirplane;
             mBlockMobile = blockMobile;
             mBlockEthernet = blockEthernet;
-            mBlockWifi = blockWifi;
+            mBlockWifi = blockWifi || mForceBlockWifi;
             // Re-register to get new callbacks.
             mNetworkController.removeCallback(this);
             mNetworkController.addCallback(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 96e0731..27fc6a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2514,7 +2514,7 @@
         if (animate) {
             mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount);
             mDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-            mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+            mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
             mDarkAnimator.start();
         } else {
             setDarkAmount(darkAmount);
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b2712ff..aad4431 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -4365,7 +4365,7 @@
                                     }
                                     addWidgetLocked(id);
                                 }
-                                if (id.provider.info != null) {
+                                if (id.provider != null && id.provider.info != null) {
                                     stashProviderRestoreUpdateLocked(id.provider,
                                             restoredId, id.appWidgetId);
                                 } else {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 0999580..41a78a7 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -20,6 +20,7 @@
 import static android.content.Context.AUTOFILL_MANAGER_SERVICE;
 
 import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sPartitionMaxCount;
 import static com.android.server.autofill.Helper.sVerbose;
 import static com.android.server.autofill.Helper.bundleToString;
 
@@ -397,6 +398,21 @@
         }
     }
 
+    // Called by Shell command.
+    public int getMaxPartitions() {
+        synchronized (mLock) {
+            return sPartitionMaxCount;
+        }
+    }
+
+    // Called by Shell command.
+    public void setMaxPartitions(int max) {
+        Slog.i(TAG, "setMaxPartitions(): " + max);
+        synchronized (mLock) {
+            sPartitionMaxCount = max;
+        }
+    }
+
     private void setDebugLocked(boolean debug) {
         com.android.server.autofill.Helper.sDebug = debug;
         android.view.autofill.Helper.sDebug = debug;
@@ -628,6 +644,7 @@
                     pw.print("Debug mode: "); pw.println(oldDebug);
                     pw.print("Verbose mode: "); pw.println(sVerbose);
                     pw.print("Disabled users: "); pw.println(mDisabledUsers);
+                    pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount);
                     final int size = mServicesCache.size();
                     pw.print("Cached services: ");
                     if (size == 0) {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index 1b9c86e..f3de557 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -70,9 +70,15 @@
             pw.println("  get log_level ");
             pw.println("    Gets the Autofill log level (off | debug | verbose).");
             pw.println("");
+            pw.println("  get max_partitions");
+            pw.println("    Gets the maximum number of partitions per session.");
+            pw.println("");
             pw.println("  set log_level [off | debug | verbose]");
             pw.println("    Sets the Autofill log level.");
             pw.println("");
+            pw.println("  set max_partitions number");
+            pw.println("    Sets the maximum number of partitions per session.");
+            pw.println("");
             pw.println("  list sessions [--user USER_ID]");
             pw.println("    List all pending sessions.");
             pw.println("");
@@ -86,9 +92,33 @@
     }
 
     private int requestGet(PrintWriter pw) {
-        if (!isNextArgLogLevel(pw, "get")) {
-            return -1;
+        final String what = getNextArgRequired();
+        switch(what) {
+            case "log_level":
+                return getLogLevel(pw);
+            case "max_partitions":
+                return getMaxPartitions(pw);
+            default:
+                pw.println("Invalid set: " + what);
+                return -1;
         }
+    }
+
+    private int requestSet(PrintWriter pw) {
+        final String what = getNextArgRequired();
+
+        switch(what) {
+            case "log_level":
+                return setLogLevel(pw);
+            case "max_partitions":
+                return setMaxPartitions();
+            default:
+                pw.println("Invalid set: " + what);
+                return -1;
+        }
+    }
+
+    private int getLogLevel(PrintWriter pw) {
         final int logLevel = mService.getLogLevel();
         switch (logLevel) {
             case AutofillManager.FLAG_ADD_CLIENT_VERBOSE:
@@ -106,11 +136,8 @@
         }
     }
 
-    private int requestSet(PrintWriter pw) {
-        if (!isNextArgLogLevel(pw, "set")) {
-            return -1;
-        }
-        final String logLevel = getNextArg();
+    private int setLogLevel(PrintWriter pw) {
+        final String logLevel = getNextArgRequired();
         switch (logLevel.toLowerCase()) {
             case "verbose":
                 mService.setLogLevel(AutofillManager.FLAG_ADD_CLIENT_VERBOSE);
@@ -127,6 +154,16 @@
         }
     }
 
+    private int getMaxPartitions(PrintWriter pw) {
+        pw.println(mService.getMaxPartitions());
+        return 0;
+    }
+
+    private int setMaxPartitions() {
+        mService.setMaxPartitions(Integer.parseInt(getNextArgRequired()));
+        return 0;
+    }
+
     private int requestDestroy(PrintWriter pw) {
         if (!isNextArgSessions(pw)) {
             return -1;
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index ffcde8d..0281f73 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -26,16 +26,23 @@
 
     /**
      * Defines a logging flag that can be dynamically changed at runtime using
-     * {@code cmd autofill debug [on|off]}.
+     * {@code cmd autofill set log_level debug}.
      */
     public static boolean sDebug = false;
 
     /**
      * Defines a logging flag that can be dynamically changed at runtime using
-     * {@code cmd autofill verbose [on|off]}.
+     * {@code cmd autofill set log_level verbose}.
      */
     public static boolean sVerbose = false;
 
+    /**
+     * Maximum number of partitions that can be allowed in a session.
+     *
+     * <p>Can be modified using {@code cmd autofill set max_partitions}.
+     */
+    static int sPartitionMaxCount = 10;
+
     private Helper() {
         throw new UnsupportedOperationException("contains static members only");
     }
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index a12ebb2..35f4fae 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -27,11 +27,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.ICancellationSignal;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.autofill.AutofillService;
 import android.service.autofill.FillRequest;
@@ -43,6 +45,7 @@
 import android.text.format.DateUtils;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.HandlerCaller;
 import com.android.server.FgThread;
 
@@ -63,6 +66,9 @@
     // How long after the last interaction with the service we would unbind
     private static final long TIMEOUT_IDLE_BIND_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS;
 
+    // How long after we make a remote request to a fill service we timeout
+    private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS;
+
     private final Context mContext;
 
     private final ComponentName mComponentName;
@@ -413,12 +419,18 @@
 
     private static final class PendingFillRequest extends PendingRequest {
         private final Object mLock = new Object();
+
         private final WeakReference<RemoteFillService> mWeakService;
         private final FillRequest mRequest;
         private final IFillCallback mCallback;
         private ICancellationSignal mCancellation;
+
+        @GuardedBy("mLock")
         private boolean mCancelled;
 
+        @GuardedBy("mLock")
+        private boolean mCompleted;
+
         public PendingFillRequest(FillRequest request, RemoteFillService service) {
             mRequest = request;
             mWeakService = new WeakReference<>(service);
@@ -443,8 +455,15 @@
 
                 @Override
                 public void onSuccess(FillResponse response) {
+                    synchronized (mLock) {
+                        if (mCompleted) {
+                            return;
+                        }
+                        mCompleted = true;
+                    }
                     RemoteFillService remoteService = mWeakService.get();
                     if (remoteService != null) {
+                        service.mHandler.getHandler().removeCallbacks(PendingFillRequest.this);
                         remoteService.dispatchOnFillRequestSuccess(PendingFillRequest.this,
                                 getCallingUid(), request.getFlags(), response);
                     }
@@ -452,13 +471,29 @@
 
                 @Override
                 public void onFailure(CharSequence message) {
+                    synchronized (mLock) {
+                        if (mCompleted) {
+                            return;
+                        }
+                        mCompleted = true;
+                    }
                     RemoteFillService remoteService = mWeakService.get();
                     if (remoteService != null) {
+                        service.mHandler.getHandler().removeCallbacks(PendingFillRequest.this);
                         remoteService.dispatchOnFillRequestFailure(
                                 PendingFillRequest.this, message);
                     }
                 }
             };
+            service.mHandler.getHandler().postAtTime(() -> {
+                cancel();
+                try {
+                    mCallback.onFailure(null);
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
+            }, PendingFillRequest.this,
+                    SystemClock.uptimeMillis() + TIMEOUT_REMOTE_REQUEST_MILLIS);
         }
 
         @Override
@@ -496,10 +531,15 @@
     }
 
     private static final class PendingSaveRequest extends PendingRequest {
+        private final Object mLock = new Object();
+
         private final WeakReference<RemoteFillService> mWeakService;
         private final SaveRequest mRequest;
         private final ISaveCallback mCallback;
 
+        @GuardedBy("mLock")
+        private boolean mCompleted;
+
         public PendingSaveRequest(@NonNull SaveRequest request,
                 @NonNull RemoteFillService service) {
             mRequest = request;
@@ -507,8 +547,16 @@
             mCallback = new ISaveCallback.Stub() {
                 @Override
                 public void onSuccess() {
+                    synchronized (mLock) {
+                        if (mCompleted) {
+                            return;
+                        }
+                        mCompleted = true;
+                    }
+                    cancel();
                     RemoteFillService service = mWeakService.get();
                     if (service != null) {
+                        service.mHandler.getHandler().removeCallbacks(PendingSaveRequest.this);
                         service.dispatchOnSaveRequestSuccess(
                                 PendingSaveRequest.this);
                     }
@@ -516,13 +564,29 @@
 
                 @Override
                 public void onFailure(CharSequence message) {
+                    synchronized (mLock) {
+                        if (mCompleted) {
+                            return;
+                        }
+                        mCompleted = true;
+                    }
                     RemoteFillService service = mWeakService.get();
                     if (service != null) {
+                        service.mHandler.getHandler().removeCallbacks(PendingSaveRequest.this);
                         service.dispatchOnSaveRequestFailure(
                                 PendingSaveRequest.this, message);
                     }
                 }
             };
+            service.mHandler.getHandler().postAtTime(() -> {
+                cancel();
+                try {
+                    mCallback.onFailure(null);
+                } catch (RemoteException e) {
+                    /* ignore */
+                }
+            }, PendingSaveRequest.this,
+                    SystemClock.uptimeMillis() + TIMEOUT_REMOTE_REQUEST_MILLIS);
         }
 
         @Override
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index ef5cdd1..4746ee9 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -26,6 +26,7 @@
 import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
 
 import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sPartitionMaxCount;
 import static com.android.server.autofill.Helper.sVerbose;
 import static com.android.server.autofill.ViewState.STATE_AUTOFILLED;
 import static com.android.server.autofill.ViewState.STATE_RESTARTED_SESSION;
@@ -162,6 +163,7 @@
     @GuardedBy("mLock")
     private boolean mIsSaving;
 
+
     /**
      * Receiver of assist data from the app's {@link Activity}.
      */
@@ -933,7 +935,6 @@
         }
     }
 
-    private static final int PARTITION_MAX_COUNT = 64;
     /**
      * Determines if a new partition should be started for an id.
      *
@@ -947,8 +948,9 @@
         }
 
         final int numResponses = mResponses.size();
-        if (numResponses >= PARTITION_MAX_COUNT) {
-            Slog.e(TAG, "Cannot create more than 64 partitions. Not creating a new partition.");
+        if (numResponses >= sPartitionMaxCount) {
+            Slog.e(TAG, "Not starting a new partition on " + id + " because session " + this.id
+                    + " reached maximum of " + sPartitionMaxCount);
             return false;
         }
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8555851..54b02a8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -91,6 +91,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.ServiceSpecificException;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -3951,7 +3952,8 @@
             synchronized (mUidToNetworkRequestCount) {
                 int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
                 if (networkRequests >= MAX_NETWORK_REQUESTS_PER_UID) {
-                    throw new IllegalArgumentException("Too many NetworkRequests filed");
+                    throw new ServiceSpecificException(
+                            ConnectivityManager.Errors.TOO_MANY_REQUESTS);
                 }
                 mUidToNetworkRequestCount.put(mUid, networkRequests);
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 1ed46a0..5e03508 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1493,12 +1493,13 @@
                     mAm.updateOomAdjLocked(r.binding.service.app, false);
                 }
             }
+
+            mAm.updateOomAdjLocked();
+
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
 
-        mAm.updateOomAdjLocked();
-
         return true;
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c6699b6..3541a3a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1466,6 +1466,20 @@
     boolean mOrigWaitForDebugger = false;
     boolean mAlwaysFinishActivities = false;
     boolean mForceResizableActivities;
+    /**
+     * Flag that indicates if multi-window is enabled.
+     *
+     * For any particular form of multi-window to be enabled, generic multi-window must be enabled
+     * in {@link com.android.internal.R.bool.config_supportsMultiWindow} config or
+     * {@link Settings.Global#DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES} development option set.
+     * At least one of the forms of multi-window must be enabled in order for this flag to be
+     * initialized to 'true'.
+     *
+     * @see #mSupportsSplitScreenMultiWindow
+     * @see #mSupportsFreeformWindowManagement
+     * @see #mSupportsPictureInPicture
+     * @see #mSupportsMultiDisplay
+     */
     boolean mSupportsMultiWindow;
     boolean mSupportsSplitScreenMultiWindow;
     boolean mSupportsFreeformWindowManagement;
@@ -4578,7 +4592,7 @@
                 mAppSwitchesAllowedTime = 0;
             }
         }
-        int ret = pir.sendInner(0, fillInIntent, resolvedType, null, null,
+        int ret = pir.sendInner(0, fillInIntent, resolvedType, null, null, null,
                 resultTo, resultWho, requestCode, flagsMask, flagsValues, bOptions, null);
         return ret;
     }
@@ -7484,11 +7498,12 @@
     }
 
     @Override
-    public int sendIntentSender(IIntentSender target, int code, Intent intent, String resolvedType,
+    public int sendIntentSender(IIntentSender target, IBinder whitelistToken, int code,
+            Intent intent, String resolvedType,
             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
         if (target instanceof PendingIntentRecord) {
             return ((PendingIntentRecord)target).sendWithResult(code, intent, resolvedType,
-                    finishedReceiver, requiredPermission, options);
+                    whitelistToken, finishedReceiver, requiredPermission, options);
         } else {
             if (intent == null) {
                 // Weird case: someone has given us their own custom IIntentSender, and now
@@ -7500,7 +7515,8 @@
                 intent = new Intent(Intent.ACTION_MAIN);
             }
             try {
-                target.send(code, intent, resolvedType, null, requiredPermission, options);
+                target.send(code, intent, resolvedType, whitelistToken, null,
+                        requiredPermission, options);
             } catch (RemoteException e) {
             }
             // Platform code can rely on getting a result back when the send is done, but if
@@ -7797,11 +7813,15 @@
     // be guarded by permission checking.
     int getUidState(int uid) {
         synchronized (this) {
-            UidRecord uidRec = mActiveUids.get(uid);
-            return uidRec == null ? ActivityManager.PROCESS_STATE_NONEXISTENT : uidRec.curProcState;
+            return getUidStateLocked(uid);
         }
     }
 
+    int getUidStateLocked(int uid) {
+        UidRecord uidRec = mActiveUids.get(uid);
+        return uidRec == null ? ActivityManager.PROCESS_STATE_NONEXISTENT : uidRec.curProcState;
+    }
+
     @Override
     public boolean isInMultiWindowMode(IBinder token) {
         final long origId = Binder.clearCallingIdentity();
@@ -13361,8 +13381,12 @@
     public void setRenderThread(int tid) {
         synchronized (this) {
             ProcessRecord proc;
+            int pid = Binder.getCallingPid();
+            if (pid == Process.myPid()) {
+                demoteSystemServerRenderThread(tid);
+                return;
+            }
             synchronized (mPidsSelfLocked) {
-                int pid = Binder.getCallingPid();
                 proc = mPidsSelfLocked.get(pid);
                 if (proc != null && proc.renderThreadTid == 0 && tid > 0) {
                     // ensure the tid belongs to the process
@@ -13395,6 +13419,16 @@
         }
     }
 
+    /**
+     * We only use RenderThread in system_server to store task snapshots to the disk, which should
+     * happen in the background. Thus, demote render thread from system_server to a lower priority.
+     *
+     * @param tid the tid of the RenderThread
+     */
+    private void demoteSystemServerRenderThread(int tid) {
+        setThreadPriority(tid, Process.THREAD_PRIORITY_BACKGROUND);
+    }
+
     @Override
     public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_VR_MODE)) {
@@ -13900,16 +13934,23 @@
             mAlwaysFinishActivities = alwaysFinishActivities;
             mSupportsLeanbackOnly = supportsLeanbackOnly;
             mForceResizableActivities = forceResizable;
-            if (supportsMultiWindow || forceResizable) {
+            final boolean multiWindowFormEnabled = freeformWindowManagement
+                    || supportsSplitScreenMultiWindow
+                    || supportsPictureInPicture
+                    || supportsMultiDisplay;
+            if ((supportsMultiWindow || forceResizable) && multiWindowFormEnabled) {
                 mSupportsMultiWindow = true;
-                mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
+                mSupportsFreeformWindowManagement = freeformWindowManagement;
+                mSupportsSplitScreenMultiWindow = supportsSplitScreenMultiWindow;
+                mSupportsPictureInPicture = supportsPictureInPicture;
+                mSupportsMultiDisplay = supportsMultiDisplay;
             } else {
                 mSupportsMultiWindow = false;
                 mSupportsFreeformWindowManagement = false;
+                mSupportsSplitScreenMultiWindow = false;
+                mSupportsPictureInPicture = false;
+                mSupportsMultiDisplay = false;
             }
-            mSupportsSplitScreenMultiWindow = supportsSplitScreenMultiWindow;
-            mSupportsPictureInPicture = supportsPictureInPicture;
-            mSupportsMultiDisplay = supportsMultiDisplay;
             mWindowManager.setForceResizableTasks(mForceResizableActivities);
             mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
             // This happens before any activities are started, so we can change global configuration
@@ -23617,12 +23658,13 @@
         }
 
         @Override
-        public void setPendingIntentWhitelistDuration(IIntentSender target, long duration) {
+        public void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
+                long duration) {
             if (!(target instanceof PendingIntentRecord)) {
                 Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
                 return;
             }
-            ((PendingIntentRecord) target).setWhitelistDurationLocked(duration);
+            ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index dab122f..6eae9e6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -22,11 +22,8 @@
 import android.app.IActivityContainer;
 import android.app.IActivityController;
 import android.app.IActivityManager;
-import android.app.IInstrumentationWatcher;
 import android.app.IStopUserCallback;
-import android.app.Instrumentation;
 import android.app.ProfilerInfo;
-import android.app.UiAutomationConnection;
 import android.app.WaitResult;
 import android.app.usage.ConfigurationStats;
 import android.app.usage.IUsageStatsManager;
@@ -37,7 +34,6 @@
 import android.content.IIntentReceiver;
 import android.content.Intent;
 import android.content.pm.IPackageManager;
-import android.content.pm.InstrumentationInfo;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 5c57be2..f13dad7 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -2180,7 +2180,7 @@
 
     void setRequestedOrientation(int requestedOrientation) {
         if (ActivityInfo.isFixedOrientation(requestedOrientation) && !fullscreen
-                && appInfo.targetSdkVersion >= O) {
+                && appInfo.targetSdkVersion > O) {
             throw new IllegalStateException("Only fullscreen activities can request orientation");
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f51635d..ca9d119 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -4719,7 +4719,7 @@
             checkEmbeddedAllowedInner(userId, pendingIntent.key.requestIntent,
                     pendingIntent.key.requestResolvedType);
 
-            return pendingIntent.sendInner(0, null, null, null, null, null, null, 0,
+            return pendingIntent.sendInner(0, null, null, null, null, null, null, null, 0,
                     FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
         }
 
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 7ba67c5..6eca3fa 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -32,6 +32,7 @@
 import android.os.RemoteException;
 import android.os.TransactionTooLargeException;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.TimeUtils;
 
@@ -51,7 +52,7 @@
     final WeakReference<PendingIntentRecord> ref;
     boolean sent = false;
     boolean canceled = false;
-    private long whitelistDuration = 0;
+    private ArrayMap<IBinder, Long> whitelistDuration;
     private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
 
     String stringName;
@@ -194,8 +195,19 @@
         ref = new WeakReference<PendingIntentRecord>(this);
     }
 
-    void setWhitelistDurationLocked(long duration) {
-        this.whitelistDuration = duration;
+    void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
+        if (duration > 0) {
+            if (whitelistDuration == null) {
+                whitelistDuration = new ArrayMap<>();
+            }
+            whitelistDuration.put(whitelistToken, duration);
+        } else if (whitelistDuration != null) {
+            whitelistDuration.remove(whitelistToken);
+            if (whitelistDuration.size() <= 0) {
+                whitelistDuration = null;
+            }
+
+        }
         this.stringName = null;
     }
 
@@ -219,19 +231,20 @@
         return listeners;
     }
 
-    public void send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
-            String requiredPermission, Bundle options) {
-        sendInner(code, intent, resolvedType, finishedReceiver,
-                requiredPermission, null, null, 0, 0, 0, options, null);
-    }
-
-    public int sendWithResult(int code, Intent intent, String resolvedType,
+    public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
             IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
-        return sendInner(code, intent, resolvedType, finishedReceiver,
+        sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
                 requiredPermission, null, null, 0, 0, 0, options, null);
     }
 
-    int sendInner(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver,
+    public int sendWithResult(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+            IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
+        return sendInner(code, intent, resolvedType, whitelistToken, finishedReceiver,
+                requiredPermission, null, null, 0, 0, 0, options, null);
+    }
+
+    int sendInner(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+            IIntentReceiver finishedReceiver,
             String requiredPermission, IBinder resultTo, String resultWho, int requestCode,
             int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
         if (intent != null) intent.setDefusable(true);
@@ -276,20 +289,29 @@
 
                 final long origId = Binder.clearCallingIdentity();
 
-                if (whitelistDuration > 0) {
-                    StringBuilder tag = new StringBuilder(64);
-                    tag.append("pendingintent:");
-                    UserHandle.formatUid(tag, callingUid);
-                    tag.append(":");
-                    if (finalIntent.getAction() != null) {
-                        tag.append(finalIntent.getAction());
-                    } else if (finalIntent.getComponent() != null) {
-                        finalIntent.getComponent().appendShortString(tag);
-                    } else if (finalIntent.getData() != null) {
-                        tag.append(finalIntent.getData());
+                if (whitelistDuration != null) {
+                    Long duration = whitelistDuration.get(whitelistToken);
+                    if (duration != null) {
+                        int procState = owner.getUidState(callingUid);
+                        if (!ActivityManager.isProcStateBackground(procState)) {
+                            StringBuilder tag = new StringBuilder(64);
+                            tag.append("pendingintent:");
+                            UserHandle.formatUid(tag, callingUid);
+                            tag.append(":");
+                            if (finalIntent.getAction() != null) {
+                                tag.append(finalIntent.getAction());
+                            } else if (finalIntent.getComponent() != null) {
+                                finalIntent.getComponent().appendShortString(tag);
+                            } else if (finalIntent.getData() != null) {
+                                tag.append(finalIntent.getData());
+                            }
+                            owner.tempWhitelistForPendingIntentLocked(callingPid,
+                                    callingUid, uid, duration, tag.toString());
+                        } else {
+                            Slog.w(TAG, "Not doing whitelist " + this + ": caller state="
+                                    + procState);
+                        }
                     }
-                    owner.tempWhitelistForPendingIntentLocked(callingPid,
-                            callingUid, uid, whitelistDuration, tag.toString());
                 }
 
                 boolean sendFinish = finishedReceiver != null;
@@ -425,10 +447,17 @@
             pw.print(prefix); pw.print("sent="); pw.print(sent);
                     pw.print(" canceled="); pw.println(canceled);
         }
-        if (whitelistDuration != 0) {
+        if (whitelistDuration != null) {
             pw.print(prefix);
             pw.print("whitelistDuration=");
-            TimeUtils.formatDuration(whitelistDuration, pw);
+            for (int i = 0; i < whitelistDuration.size(); i++) {
+                if (i != 0) {
+                    pw.print(", ");
+                }
+                pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
+                pw.print(":");
+                TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
+            }
             pw.println();
         }
         if (mCancelCallbacks != null) {
@@ -451,9 +480,16 @@
         sb.append(key.packageName);
         sb.append(' ');
         sb.append(key.typeName());
-        if (whitelistDuration > 0) {
+        if (whitelistDuration != null) {
             sb.append( " (whitelist: ");
-            TimeUtils.formatDuration(whitelistDuration, sb);
+            for (int i = 0; i < whitelistDuration.size(); i++) {
+                if (i != 0) {
+                    sb.append(",");
+                }
+                sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
+                sb.append(":");
+                TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
+            }
             sb.append(")");
         }
         sb.append('}');
diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java
index e6edaf1..1bd2085 100644
--- a/services/core/java/com/android/server/notification/BadgeExtractor.java
+++ b/services/core/java/com/android/server/notification/BadgeExtractor.java
@@ -41,9 +41,10 @@
             if (DBG) Slog.d(TAG, "missing config");
             return null;
         }
+        boolean userWantsBadges = mConfig.badgingEnabled(record.sbn.getUser());
         boolean appCanShowBadge =
                 mConfig.canShowBadge(record.sbn.getPackageName(), record.sbn.getUid());
-        if (!appCanShowBadge) {
+        if (!userWantsBadges || !appCanShowBadge) {
             record.setShowBadge(false);
         } else {
             record.setShowBadge(mConfig.getNotificationChannel(record.sbn.getPackageName(),
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7dcd6cd..9cd0dff 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -344,6 +344,7 @@
 
     private static final int MY_UID = Process.myUid();
     private static final int MY_PID = Process.myPid();
+    private static final IBinder WHITELIST_TOKEN = new Binder();
     private RankingHandler mRankingHandler;
     private long mLastOverRateLogTime;
     private float mMaxPackageEnqueueRate = DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
@@ -926,6 +927,8 @@
     };
 
     private final class SettingsObserver extends ContentObserver {
+        private final Uri NOTIFICATION_BADGING_URI
+                = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BADGING);
         private final Uri NOTIFICATION_LIGHT_PULSE_URI
                 = Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
         private final Uri NOTIFICATION_RATE_LIMIT_URI
@@ -937,6 +940,8 @@
 
         void observe() {
             ContentResolver resolver = getContext().getContentResolver();
+            resolver.registerContentObserver(NOTIFICATION_BADGING_URI,
+                    false, this, UserHandle.USER_ALL);
             resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI,
                     false, this, UserHandle.USER_ALL);
             resolver.registerContentObserver(NOTIFICATION_RATE_LIMIT_URI,
@@ -962,6 +967,9 @@
                 mMaxPackageEnqueueRate = Settings.Global.getFloat(resolver,
                             Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE, mMaxPackageEnqueueRate);
             }
+            if (uri == null || NOTIFICATION_BADGING_URI.equals(uri)) {
+                mRankingHelper.updateBadgingEnabled();
+            }
         }
     }
 
@@ -983,6 +991,7 @@
 
     public NotificationManagerService(Context context) {
         super(context);
+        Notification.processWhitelistToken = WHITELIST_TOKEN;
     }
 
     // TODO - replace these methods with a single VisibleForTesting constructor
@@ -1818,6 +1827,12 @@
         }
 
         @Override
+        public boolean onlyHasDefaultChannel(String pkg, int uid) {
+            enforceSystemOrSystemUI("onlyHasDefaultChannel");
+            return mRankingHelper.onlyHasDefaultChannel(pkg, uid);
+        }
+
+        @Override
         public int getDeletedChannelCount(String pkg, int uid) {
             enforceSystemOrSystemUI("getDeletedChannelCount");
             return mRankingHelper.getDeletedChannelCount(pkg, uid);
@@ -3256,7 +3271,8 @@
                 for (int i = 0; i < intentCount; i++) {
                     PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
                     if (pendingIntent != null) {
-                        am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(), duration);
+                        am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),
+                                WHITELIST_TOKEN, duration);
                     }
                 }
             }
@@ -3794,17 +3810,11 @@
             updateLightsLocked();
         }
         if (buzz || beep || blink) {
-            if (((record.getSuppressedVisualEffects()
-                    & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) != 0)) {
-                if (DBG) Slog.v(TAG, "Suppressed SystemUI from triggering screen on");
-            } else {
-                MetricsLogger.action(record.getLogMaker()
-                        .setCategory(MetricsEvent.NOTIFICATION_ALERT)
-                        .setType(MetricsEvent.TYPE_OPEN)
-                        .setSubtype((buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)));
-                EventLogTags.writeNotificationAlert(key,
-                        buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
-            }
+            MetricsLogger.action(record.getLogMaker()
+                    .setCategory(MetricsEvent.NOTIFICATION_ALERT)
+                    .setType(MetricsEvent.TYPE_OPEN)
+                    .setSubtype((buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)));
+            EventLogTags.writeNotificationAlert(key, buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
         }
     }
 
@@ -4025,6 +4035,7 @@
 
     private void handleRankingSort(Message msg) {
         if (!(msg.obj instanceof Boolean)) return;
+        if (mRankingHelper == null) return;
         boolean forceUpdate = ((Boolean) msg.obj == null) ? false : (boolean) msg.obj;
         synchronized (mNotificationLock) {
             final int N = mNotificationList.size();
@@ -4072,6 +4083,8 @@
                     | (mZenModeHelper.shouldSuppressWhenScreenOn()
                     ? SUPPRESSED_EFFECT_SCREEN_ON : 0);
             record.setSuppressedVisualEffects(suppressed);
+        } else {
+            record.setSuppressedVisualEffects(0);
         }
     }
 
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 4d19b52..36da04d 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -18,6 +18,7 @@
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.content.pm.ParceledListSlice;
+import android.os.UserHandle;
 
 import java.util.Collection;
 
@@ -27,6 +28,7 @@
     int getImportance(String packageName, int uid);
     void setShowBadge(String packageName, int uid, boolean showBadge);
     boolean canShowBadge(String packageName, int uid);
+    boolean badgingEnabled(UserHandle userHandle);
 
     Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
             int uid);
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 7758516..e83d453 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -21,6 +21,8 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.util.Preconditions;
 
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
@@ -33,10 +35,14 @@
 import android.metrics.LogMaker;
 import android.os.Build;
 import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
+import android.util.SparseBooleanArray;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -48,11 +54,13 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 
 public class RankingHelper implements RankingConfig {
     private static final String TAG = "RankingHelper";
@@ -89,6 +97,7 @@
     private final Context mContext;
     private final RankingHandler mRankingHandler;
     private final PackageManager mPm;
+    private SparseBooleanArray mBadgingEnabled;
 
     public RankingHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
             NotificationUsageStats usageStats, String[] extractorNames) {
@@ -98,6 +107,8 @@
 
         mPreliminaryComparator = new NotificationComparator(mContext);
 
+        updateBadgingEnabled();
+
         final int N = extractorNames.length;
         mSignalExtractors = new NotificationSignalExtractor[N];
         for (int i = 0; i < N; i++) {
@@ -301,7 +312,8 @@
 
     private void createDefaultChannelIfNeeded(Record r) throws NameNotFoundException {
         if (r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-            // Already exists
+            r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID).setName(
+                    mContext.getString(R.string.default_notification_channel_label));
             return;
         }
 
@@ -574,12 +586,8 @@
         updateConfig();
     }
 
-    private void clearLockedFields(NotificationChannel channel) {
-        int clearMask = 0;
-        for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
-            clearMask |= NotificationChannel.LOCKABLE_FIELDS[i];
-        }
-        channel.lockFields(~clearMask);
+    void clearLockedFields(NotificationChannel channel) {
+        channel.unlockFields(channel.getUserLockedFields());
     }
 
     @Override
@@ -597,6 +605,7 @@
         if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
             updatedChannel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
         }
+        lockFieldsForUpdate(channel, updatedChannel);
         r.channels.put(updatedChannel.getId(), updatedChannel);
 
         if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(updatedChannel.getId())) {
@@ -770,6 +779,21 @@
         return new ParceledListSlice<>(channels);
     }
 
+    /**
+     * True for pre-O apps that only have the default channel, or pre O apps that have no
+     * channels yet. This method will create the default channel for pre-O apps that don't have it.
+     * Should never be true for O+ targeting apps, but that's enforced on boot/when an app
+     * upgrades.
+     */
+    public boolean onlyHasDefaultChannel(String pkg, int uid) {
+        Record r = getOrCreateRecord(pkg, uid);
+        if (r.channels.size() == 1
+                && r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+            return true;
+        }
+        return false;
+    }
+
     public int getDeletedChannelCount(String pkg, int uid) {
         Preconditions.checkNotNull(pkg);
         int deletedCount = 0;
@@ -805,6 +829,35 @@
                 enabled ? DEFAULT_IMPORTANCE : NotificationManager.IMPORTANCE_NONE);
     }
 
+    @VisibleForTesting
+    void lockFieldsForUpdate(NotificationChannel original, NotificationChannel update) {
+        update.unlockFields(update.getUserLockedFields());
+        update.lockFields(original.getUserLockedFields());
+        if (original.canBypassDnd() != update.canBypassDnd()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
+        }
+        if (original.getLockscreenVisibility() != update.getLockscreenVisibility()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
+        }
+        if (original.getImportance() != update.getImportance()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+        }
+        if (original.shouldShowLights() != update.shouldShowLights()
+                || original.getLightColor() != update.getLightColor()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
+        }
+        if (!Objects.equals(original.getSound(), update.getSound())) {
+            update.lockFields(NotificationChannel.USER_LOCKED_SOUND);
+        }
+        if (!Arrays.equals(original.getVibrationPattern(), update.getVibrationPattern())
+                || original.shouldVibrate() != update.shouldVibrate()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
+        }
+        if (original.canShowBadge() != update.canShowBadge()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
+        }
+    }
+
     public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
         if (filter == null) {
             final int N = mSignalExtractors.length;
@@ -1083,6 +1136,38 @@
                         channel.getImportance());
     }
 
+    public void updateBadgingEnabled() {
+        if (mBadgingEnabled == null) {
+            mBadgingEnabled = new SparseBooleanArray();
+        }
+        boolean changed = false;
+        // update the cached values
+        for (int index = 0; index < mBadgingEnabled.size(); index++) {
+            int userId = mBadgingEnabled.keyAt(index);
+            final boolean oldValue = mBadgingEnabled.get(userId);
+            final boolean newValue = Secure.getIntForUser(mContext.getContentResolver(),
+                    Secure.NOTIFICATION_BADGING,
+                    DEFAULT_SHOW_BADGE ? 1 : 0, userId) != 0;
+            mBadgingEnabled.put(userId, newValue);
+            changed |= oldValue != newValue;
+        }
+        if (changed) {
+            mRankingHandler.requestSort(false);
+        }
+    }
+
+    public boolean badgingEnabled(UserHandle userHandle) {
+        int userId = userHandle.getIdentifier();
+        if (mBadgingEnabled.indexOfKey(userId) < 0) {
+            mBadgingEnabled.put(userId,
+                    Secure.getIntForUser(mContext.getContentResolver(),
+                            Secure.NOTIFICATION_BADGING,
+                            DEFAULT_SHOW_BADGE ? 1 : 0, userId) != 0);
+        }
+        return mBadgingEnabled.get(userId, DEFAULT_SHOW_BADGE);
+    }
+
+
     private static class Record {
         static int UNKNOWN_UID = UserHandle.USER_NULL;
 
diff --git a/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java b/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java
index bbd4048..575e0f9 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java
@@ -21,6 +21,7 @@
 import android.os.ShellCommand;
 
 import java.io.PrintWriter;
+import java.util.Locale;
 
 class OtaDexoptShellCommand extends ShellCommand {
     final IOtaDexopt mInterface;
@@ -93,7 +94,10 @@
     private int runOtaProgress() throws RemoteException {
         final float progress = mInterface.getProgress();
         final PrintWriter pw = getOutPrintWriter();
-        pw.format("%.2f", progress);
+        // Note: The float output is parsed by update_engine. It does needs to be non-localized,
+        //       as it's always expected to be "0.xy," never "0,xy" or similar. So use the ROOT
+        //       Locale for formatting. (b/37760573)
+        pw.format(Locale.ROOT, "%.2f", progress);
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8c1d9fb3..cab6f36 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3616,7 +3616,7 @@
             if (matchFactoryOnly) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 if (ps != null) {
-                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                         return null;
                     }
                     return generatePackageInfo(ps, flags, userId);
@@ -3631,14 +3631,14 @@
                 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
             if (p != null) {
                 if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
-                        Binder.getCallingUid(), userId)) {
+                        Binder.getCallingUid(), userId, flags)) {
                     return null;
                 }
                 return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
             }
             if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
-                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                     return null;
                 }
                 return generatePackageInfo(ps, flags, userId);
@@ -3647,13 +3647,17 @@
         return null;
     }
 
-
-    private boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId) {
-        // System/shell/root get to see all static libs
-        final int appId = UserHandle.getAppId(uid);
-        if (appId == Process.SYSTEM_UID || appId == Process.SHELL_UID
-                || appId == Process.ROOT_UID) {
-            return false;
+    private boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId,
+            int flags) {
+        // Callers can access only the libs they depend on, otherwise they need to explicitly
+        // ask for the shared libraries given the caller is allowed to access all static libs.
+        if ((flags & PackageManager.MATCH_STATIC_SHARED_LIBRARIES) != 0) {
+            // System/shell/root get to see all static libs
+            final int appId = UserHandle.getAppId(uid);
+            if (appId == Process.SYSTEM_UID || appId == Process.SHELL_UID
+                    || appId == Process.ROOT_UID) {
+                return false;
+            }
         }
 
         // No package means no static lib as it is always on internal storage
@@ -3848,7 +3852,7 @@
         if (!sUserManager.exists(userId)) return null;
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
-            if (filterSharedLibPackageLPr(ps, uid, userId)) {
+            if (filterSharedLibPackageLPr(ps, uid, userId, flags)) {
                 return null;
             }
             if (ps.pkg == null) {
@@ -3889,7 +3893,7 @@
             if (p != null) {
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) return null;
-                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                     return null;
                 }
                 // Note: isEnabledLP() does not apply here - always return info
@@ -4350,7 +4354,6 @@
                     }
                     final long identity = Binder.clearCallingIdentity();
                     try {
-                        // TODO: We will change version code to long, so in the new API it is long
                         PackageInfo packageInfo = getPackageInfoVersioned(
                                 libInfo.getDeclaringPackage(), flags, userId);
                         if (packageInfo == null) {
@@ -4493,7 +4496,8 @@
                     }
                     PackageSetting ps = mSettings.getPackageLPr(libEntry.apk);
                     if (ps != null && !filterSharedLibPackageLPr(ps, Binder.getCallingUid(),
-                            UserHandle.getUserId(Binder.getCallingUid()))) {
+                            UserHandle.getUserId(Binder.getCallingUid()),
+                            PackageManager.MATCH_STATIC_SHARED_LIBRARIES)) {
                         if (libs == null) {
                             libs = new ArraySet<>();
                         }
@@ -7548,7 +7552,7 @@
             if (listUninstalled) {
                 list = new ArrayList<>(mSettings.mPackages.size());
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                         continue;
                     }
                     final PackageInfo pi = generatePackageInfo(ps, flags, userId);
@@ -7560,7 +7564,7 @@
                 list = new ArrayList<>(mPackages.size());
                 for (PackageParser.Package p : mPackages.values()) {
                     if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
-                            Binder.getCallingUid(), userId)) {
+                            Binder.getCallingUid(), userId, flags)) {
                         continue;
                     }
                     final PackageInfo pi = generatePackageInfo((PackageSetting)
@@ -7665,7 +7669,7 @@
                         effectiveFlags |= PackageManager.MATCH_ANY_USER;
                     }
                     if (ps.pkg != null) {
-                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                             continue;
                         }
                         ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
@@ -7689,7 +7693,7 @@
                 for (PackageParser.Package p : mPackages.values()) {
                     if (p.mExtras != null) {
                         PackageSetting ps = (PackageSetting) p.mExtras;
-                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId)) {
+                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                             continue;
                         }
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index c1d68b8..3e920d4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -48,6 +48,7 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ShellCommand;
 import android.os.SystemProperties;
@@ -1686,7 +1687,7 @@
 
         private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
             @Override
-            public void send(int code, Intent intent, String resolvedType,
+            public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
                     IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
                 try {
                     mResult.offer(intent, 5, TimeUnit.SECONDS);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 857025d..6f5c070c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5325,7 +5325,7 @@
     @Override
     public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
             WindowState attached, WindowState imeTarget) {
-        final boolean visible = !win.isGoneForLayoutLw() && win.getAttrs().alpha > 0f;
+        final boolean visible = win.isVisibleLw() && win.getAttrs().alpha > 0f;
         if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
         applyKeyguardPolicyLw(win, imeTarget);
         final int fl = PolicyControl.getWindowFlags(win, attrs);
@@ -5960,15 +5960,23 @@
                             result &= ~ACTION_PASS_TO_USER;
                             break;
                         }
-                        if (telecomManager.isInCall()
-                                && (result & ACTION_PASS_TO_USER) == 0) {
-                            // If we are in call but we decided not to pass the key to
-                            // the application, just pass it to the session service.
-                            MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
-                                    event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
-                            break;
-                        }
                     }
+                    int audioMode = AudioManager.MODE_NORMAL;
+                    try {
+                        audioMode = getAudioService().getMode();
+                    } catch (Exception e) {
+                        Log.e(TAG, "Error getting AudioService in interceptKeyBeforeQueueing.", e);
+                    }
+                    boolean isInCall = (telecomManager != null && telecomManager.isInCall()) ||
+                            audioMode == AudioManager.MODE_IN_COMMUNICATION;
+                    if (isInCall && (result & ACTION_PASS_TO_USER) == 0) {
+                        // If we are in call but we decided not to pass the key to
+                        // the application, just pass it to the session service.
+                        MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent(
+                                event, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
+                        break;
+                    }
+
                 }
                 if (mUseTvRouting || mHandleVolumeKeysInWM) {
                     // Defer special key handlings to
@@ -6313,7 +6321,7 @@
                 try {
                     getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
                             AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
                 }
                 break;
@@ -6321,7 +6329,7 @@
                 try {
                     getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
                             AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
                 }
                 break;
@@ -6332,7 +6340,7 @@
                                 AudioManager.ADJUST_TOGGLE_MUTE,
                                 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG);
                     }
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
                 }
                 break;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 423bc0c..a8d19e94 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -4607,6 +4607,9 @@
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read last_reboot_reason file", e);
         }
+        if (line == null) {
+            return PowerManager.SHUTDOWN_REASON_UNKNOWN;
+        }
         switch (line) {
             case REASON_SHUTDOWN:
                 return PowerManager.SHUTDOWN_REASON_SHUTDOWN;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 70782dd..71c92b8 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -62,6 +62,7 @@
 import android.os.Environment;
 import android.os.FileObserver;
 import android.os.FileUtils;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.Process;
@@ -817,13 +818,35 @@
         @Override
         public void onServiceDisconnected(ComponentName name) {
             synchronized (mLock) {
+                Slog.w(TAG, "Wallpaper service gone: " + name);
+                if (!Objects.equals(name, mWallpaper.wallpaperComponent)) {
+                    Slog.e(TAG, "Does not match expected wallpaper component "
+                            + mWallpaper.wallpaperComponent);
+                }
                 mService = null;
                 mEngine = null;
                 if (mWallpaper.connection == this) {
-                    // The wallpaper disappeared.  If this isn't a system-default one, track
-                    // crashes and fall back to default if it continues to misbehave.
+                    // There is an inherent ordering race between this callback and the
+                    // package monitor that receives notice that a package is being updated,
+                    // so we cannot quite trust at this moment that we know for sure that
+                    // this is not an update.  If we think this is a genuine non-update
+                    // wallpaper outage, we do our "wait for reset" work as a continuation,
+                    // a short time in the future, specifically to allow any pending package
+                    // update message on this same looper thread to be processed.
+                    if (!mWallpaper.wallpaperUpdating) {
+                        mContext.getMainThreadHandler().postDelayed(() -> processDisconnect(this),
+                                1000);
+                    }
+                }
+            }
+        }
+
+        private void processDisconnect(final ServiceConnection connection) {
+            synchronized (mLock) {
+                // The wallpaper disappeared.  If this isn't a system-default one, track
+                // crashes and fall back to default if it continues to misbehave.
+                if (connection == mWallpaper.connection) {
                     final ComponentName wpService = mWallpaper.wallpaperComponent;
-                    Slog.w(TAG, "Wallpaper service gone: " + wpService);
                     if (!mWallpaper.wallpaperUpdating
                             && mWallpaper.userId == mCurrentUserId
                             && !Objects.equals(mDefaultWallpaperComponent, wpService)
@@ -836,7 +859,7 @@
                         // during {@link #MIN_WALLPAPER_CRASH_TIME} millis.
                         if (mWallpaper.lastDiedTime != 0
                                 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME
-                                    > SystemClock.uptimeMillis()) {
+                                > SystemClock.uptimeMillis()) {
                             Slog.w(TAG, "Reverting to built-in wallpaper!");
                             clearWallpaperLocked(true, FLAG_SYSTEM, mWallpaper.userId, null);
                         } else {
@@ -844,18 +867,22 @@
 
                             // If we didn't reset it right away, do so after we couldn't connect to
                             // it for an extended amount of time to avoid having a black wallpaper.
-                            FgThread.getHandler().removeCallbacks(mResetRunnable);
-                            FgThread.getHandler().postDelayed(mResetRunnable,
-                                    WALLPAPER_RECONNECT_TIMEOUT_MS);
+                            final Handler fgHandler = FgThread.getHandler();
+                            fgHandler.removeCallbacks(mResetRunnable);
+                            fgHandler.postDelayed(mResetRunnable, WALLPAPER_RECONNECT_TIMEOUT_MS);
                             if (DEBUG_LIVE) {
                                 Slog.i(TAG, "Started wallpaper reconnect timeout for " + wpService);
                             }
                         }
-                        final String flattened = name.flattenToString();
+                        final String flattened = wpService.flattenToString();
                         EventLog.writeEvent(EventLogTags.WP_WALLPAPER_CRASHED,
                                 flattened.substring(0, Math.min(flattened.length(),
                                         MAX_WALLPAPER_COMPONENT_LOG_LENGTH)));
                     }
+                } else {
+                    if (DEBUG_LIVE) {
+                        Slog.i(TAG, "Wallpaper changed during disconnect tracking; ignoring");
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 982561c..96ea5e5 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1248,11 +1248,11 @@
      */
     @Override
     int getOrientation(int candidate) {
-        // We do not allow non-fullscreen apps to influence orientation at and beyond O. While we do
+        // We do not allow non-fullscreen apps to influence orientation beyond O. While we do
         // throw an exception in {@link Activity#onCreate} and
         // {@link Activity#setRequestedOrientation}, we also ignore the orientation here so that
         // other calculations aren't affected.
-        if (!fillsParent() && mTargetSdk >= O) {
+        if (!fillsParent() && mTargetSdk > O) {
             // Can't specify orientation if app doesn't fill parent.
             return SCREEN_ORIENTATION_UNSET;
         }
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index b927e67..9c44c14 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 
 import android.app.ActivityManager.StackId;
 import android.app.RemoteAction;
@@ -285,13 +286,16 @@
             if (StackId.tasksAreFloating(mStackId)) {
                 // Floating tasks should not be resized to the screen's bounds.
 
-                if (bounds.width() == mTmpDisplayBounds.width() &&
+                if (mStackId == PINNED_STACK_ID && bounds.width() == mTmpDisplayBounds.width() &&
                         bounds.height() == mTmpDisplayBounds.height()) {
                     // If the bounds we are animating is the same as the fullscreen stack
                     // dimensions, then apply the same inset calculations that we normally do for
                     // the fullscreen stack, without intersecting it with the display bounds
                     stableBounds.inset(mTmpStableInsets);
                     nonDecorBounds.inset(mTmpNonDecorInsets);
+                    // Move app bounds to zero to apply intersection with parent correctly. They are
+                    // used only for evaluating width and height, so it's OK to move them around.
+                    config.appBounds.offsetTo(0, 0);
                     intersectParentBounds = true;
                 }
                 width = (int) (stableBounds.width() / density);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index b79173c..1bbe1d0 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -275,6 +275,15 @@
         mPersister.removeObsoleteFiles(persistentTaskIds, runningUserIds);
     }
 
+    /**
+     * Temporarily pauses/unpauses persisting of task snapshots.
+     *
+     * @param paused Whether task snapshot persisting should be paused.
+     */
+    void setPersisterPaused(boolean paused) {
+        mPersister.setPaused(paused);
+    }
+
     void dump(PrintWriter pw, String prefix) {
         mCache.dump(pw, prefix);
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index e5c7a72..0287070 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -60,6 +60,8 @@
     private final ArrayDeque<WriteQueueItem> mWriteQueue = new ArrayDeque<>();
     @GuardedBy("mLock")
     private boolean mQueueIdling;
+    @GuardedBy("mLock")
+    private boolean mPaused;
     private boolean mStarted;
     private final Object mLock = new Object();
     private final DirectoryResolver mDirectoryResolver;
@@ -127,6 +129,15 @@
         }
     }
 
+    void setPaused(boolean paused) {
+        synchronized (mLock) {
+            mPaused = paused;
+            if (!paused) {
+                mLock.notifyAll();
+            }
+        }
+    }
+
     @TestApi
     void waitForQueueEmpty() {
         while (true) {
@@ -142,7 +153,9 @@
     @GuardedBy("mLock")
     private void sendToQueueLocked(WriteQueueItem item) {
         mWriteQueue.offer(item);
-        mLock.notifyAll();
+        if (!mPaused) {
+            mLock.notifyAll();
+        }
     }
 
     private File getDirectory(int userId) {
@@ -185,7 +198,11 @@
             while (true) {
                 WriteQueueItem next;
                 synchronized (mLock) {
-                    next = mWriteQueue.poll();
+                    if (mPaused) {
+                        next = null;
+                    } else {
+                        next = mWriteQueue.poll();
+                    }
                 }
                 if (next != null) {
                     next.write();
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 067cc09..dd790a9 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -255,12 +255,19 @@
             mWindowPlacerLocked.requestTraversal();
         }
 
-        if (mAnimating && !wasAnimating && Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
-            Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+        if (mAnimating && !wasAnimating) {
+
+            // Usually app transitions but quite a load onto the system already (with all the things
+            // happening in app), so pause task snapshot persisting to not increase the load.
+            mService.mTaskSnapshotController.setPersisterPaused(true);
+            if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
+                Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
+            }
         }
 
         if (!mAnimating && wasAnimating) {
             mWindowPlacerLocked.requestTraversal();
+            mService.mTaskSnapshotController.setPersisterPaused(false);
             if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
                 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0);
             }
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index ddd1ca5..e576f2f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -41,6 +41,7 @@
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.os.Binder;
 import android.os.Debug;
 import android.os.Trace;
 import android.util.ArraySet;
@@ -683,9 +684,11 @@
             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
 
             // Create a new surface for the thumbnail
+            WindowState window = appToken.findMainWindow();
             SurfaceControl surfaceControl = new SurfaceControl(mService.mFxSession,
                     "thumbnail anim", dirty.width(), dirty.height(),
-                    PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+                    PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN,
+                    appToken.windowType, window.mOwnerUid);
             surfaceControl.setLayerStack(display.getLayerStack());
             if (SHOW_TRANSACTIONS) {
                 Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
diff --git a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
index 0cf4994..262516d 100644
--- a/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java
@@ -18,20 +18,19 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.when;
 
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+
 import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.Notification.Builder;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
-import android.content.Context;
 import android.os.UserHandle;
+import android.provider.Settings.Secure;
 import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -43,7 +42,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class BadgeExtractorTest {
+public class BadgeExtractorTest extends NotificationTestCase {
 
     @Mock RankingConfig mConfig;
 
@@ -59,7 +58,11 @@
         MockitoAnnotations.initMocks(this);
     }
 
-    private NotificationRecord getNotificationRecord(NotificationChannel channel) {
+    private NotificationRecord getNotificationRecord(boolean showBadge, int importanceHigh) {
+        NotificationChannel channel = new NotificationChannel("a", "a", importanceHigh);
+        channel.setShowBadge(showBadge);
+        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
+
         final Builder builder = new Builder(getContext())
                 .setContentTitle("foo")
                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -73,10 +76,6 @@
         return r;
     }
 
-    private Context getContext() {
-        return InstrumentationRegistry.getTargetContext();
-    }
-
     //
     // Tests
     //
@@ -86,13 +85,9 @@
         BadgeExtractor extractor = new BadgeExtractor();
         extractor.setConfig(mConfig);
 
+        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
         when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
-        NotificationChannel channel =
-                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
-        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
-        channel.setShowBadge(false);
-
-        NotificationRecord r = getNotificationRecord(channel);
+        NotificationRecord r = getNotificationRecord(false, IMPORTANCE_UNSPECIFIED);
 
         extractor.process(r);
 
@@ -104,13 +99,9 @@
         BadgeExtractor extractor = new BadgeExtractor();
         extractor.setConfig(mConfig);
 
+        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
         when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(false);
-        NotificationChannel channel =
-                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_HIGH);
-        channel.setShowBadge(true);
-        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
-
-        NotificationRecord r = getNotificationRecord(channel);
+        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_HIGH);
 
         extractor.process(r);
 
@@ -122,13 +113,9 @@
         BadgeExtractor extractor = new BadgeExtractor();
         extractor.setConfig(mConfig);
 
+        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
         when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
-        NotificationChannel channel =
-                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
-        channel.setShowBadge(true);
-        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
-
-        NotificationRecord r = getNotificationRecord(channel);
+        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
 
         extractor.process(r);
 
@@ -140,13 +127,23 @@
         BadgeExtractor extractor = new BadgeExtractor();
         extractor.setConfig(mConfig);
 
+        when(mConfig.badgingEnabled(mUser)).thenReturn(true);
         when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(false);
-        NotificationChannel channel =
-                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
-        channel.setShowBadge(false);
-        when(mConfig.getNotificationChannel(mPkg, mUid, "a", false)).thenReturn(channel);
+        NotificationRecord r = getNotificationRecord(false, IMPORTANCE_UNSPECIFIED);
 
-        NotificationRecord r = getNotificationRecord(channel);
+        extractor.process(r);
+
+        assertFalse(r.canShowBadge());
+    }
+
+    @Test
+    public void testAppYesChannelYesUserNo() throws Exception {
+        BadgeExtractor extractor = new BadgeExtractor();
+        extractor.setConfig(mConfig);
+
+        when(mConfig.badgingEnabled(mUser)).thenReturn(false);
+        when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
+        NotificationRecord r = getNotificationRecord(true, IMPORTANCE_HIGH);
 
         extractor.process(r);
 
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index d4904f5..39caa3c 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -34,7 +34,6 @@
 import android.app.Notification;
 import android.app.Notification.Builder;
 import android.app.NotificationManager;
-import android.content.Context;
 import android.app.NotificationChannel;
 import android.graphics.Color;
 import android.media.AudioAttributes;
@@ -47,7 +46,6 @@
 import android.os.VibrationEffect;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -69,7 +67,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class BuzzBeepBlinkTest {
+public class BuzzBeepBlinkTest extends NotificationTestCase {
 
     @Mock AudioManager mAudioManager;
     @Mock Vibrator mVibrator;
@@ -328,10 +326,6 @@
                 eq(CUSTOM_LIGHT_COLOR), anyInt(), eq(CUSTOM_LIGHT_ON), eq(CUSTOM_LIGHT_OFF));
     }
 
-    private Context getContext() {
-        return InstrumentationRegistry.getTargetContext();
-    }
-
     //
     // Tests
     //
diff --git a/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
index 24cb72e..f92bd84 100644
--- a/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/GlobalSortKeyComparatorTest.java
@@ -25,7 +25,6 @@
 import android.app.NotificationManager;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -38,7 +37,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class GlobalSortKeyComparatorTest {
+public class GlobalSortKeyComparatorTest extends NotificationTestCase {
 
     private final String PKG = "PKG";
     private final int UID = 1111111;
@@ -46,24 +45,23 @@
 
     @Test
     public void testComparator() throws Exception {
-        Notification n = new Notification.Builder(
-                InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+        Notification n = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .build();
-        NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+        NotificationRecord left = new NotificationRecord(getContext(),
                 new StatusBarNotification(PKG,
                         PKG, 1, "media", UID, UID, n,
                         new UserHandle(UserHandle.myUserId()),
                         "", 1499), getDefaultChannel());
         left.setGlobalSortKey("first");
 
-        NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+        NotificationRecord right = new NotificationRecord(getContext(),
                 new StatusBarNotification(PKG,
                         PKG, 1, "media", UID, UID, n,
                         new UserHandle(UserHandle.myUserId()),
                         "", 1499), getDefaultChannel());
         right.setGlobalSortKey("second");
 
-        NotificationRecord last = new NotificationRecord(InstrumentationRegistry.getContext(),
+        NotificationRecord last = new NotificationRecord(getContext(),
                 new StatusBarNotification(PKG,
                         PKG, 1, "media", UID, UID, n,
                         new UserHandle(UserHandle.myUserId()),
@@ -86,16 +84,15 @@
 
     @Test
     public void testNoCrash_leftNull() throws Exception {
-        Notification n = new Notification.Builder(
-                InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+        Notification n = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .build();
-        NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+        NotificationRecord left = new NotificationRecord(getContext(),
                 new StatusBarNotification(PKG,
                         PKG, 1, "media", UID, UID, n,
                         new UserHandle(UserHandle.myUserId()),
                         "", 1499), getDefaultChannel());
 
-        NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+        NotificationRecord right = new NotificationRecord(getContext(),
                 new StatusBarNotification(PKG,
                         PKG, 1, "media", UID, UID, n,
                         new UserHandle(UserHandle.myUserId()),
@@ -117,17 +114,16 @@
 
     @Test
     public void testNoCrash_rightNull() throws Exception {
-        Notification n = new Notification.Builder(
-                InstrumentationRegistry.getContext(), TEST_CHANNEL_ID)
+        Notification n = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
                 .build();
-        NotificationRecord left = new NotificationRecord(InstrumentationRegistry.getContext(),
+        NotificationRecord left = new NotificationRecord(getContext(),
                 new StatusBarNotification(PKG,
                         PKG, 1, "media", UID, UID, n,
                         new UserHandle(UserHandle.myUserId()),
                         "", 1499), getDefaultChannel());
         left.setGlobalSortKey("not null");
 
-        NotificationRecord right = new NotificationRecord(InstrumentationRegistry.getContext(),
+        NotificationRecord right = new NotificationRecord(getContext(),
                 new StatusBarNotification(PKG,
                         PKG, 1, "media", UID, UID, n,
                         new UserHandle(UserHandle.myUserId()),
diff --git a/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java b/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
index 05c33a4..8dd1779 100644
--- a/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/GroupHelperTest.java
@@ -34,10 +34,8 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.content.Context;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -46,15 +44,11 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class GroupHelperTest {
+public class GroupHelperTest extends NotificationTestCase {
     private @Mock GroupHelper.Callback mCallback;
 
     private GroupHelper mGroupHelper;
 
-    private Context getContext() {
-        return InstrumentationRegistry.getTargetContext();
-    }
-
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
diff --git a/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java b/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
index 3dbd803..d325e10 100644
--- a/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/ImportanceExtractorTest.java
@@ -24,10 +24,8 @@
 import android.app.Notification.Builder;
 import android.app.NotificationManager;
 import android.app.NotificationChannel;
-import android.content.Context;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -43,7 +41,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class ImportanceExtractorTest {
+public class ImportanceExtractorTest extends NotificationTestCase {
 
     @Mock RankingConfig mConfig;
 
@@ -75,10 +73,6 @@
         return r;
     }
 
-    private Context getContext() {
-        return InstrumentationRegistry.getTargetContext();
-    }
-
     //
     // Tests
     //
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
index dde08fc..1e5f96f 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationComparatorTest.java
@@ -35,7 +35,6 @@
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.telecom.TelecomManager;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -51,7 +50,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class NotificationComparatorTest {
+public class NotificationComparatorTest extends NotificationTestCase {
     @Mock Context mContext;
     @Mock TelecomManager mTm;
     @Mock RankingHandler handler;
@@ -83,10 +82,8 @@
         MockitoAnnotations.initMocks(this);
         int userId = UserHandle.myUserId();
 
-        when(mContext.getResources()).thenReturn(
-                InstrumentationRegistry.getTargetContext().getResources());
-        when(mContext.getContentResolver()).thenReturn(
-                InstrumentationRegistry.getTargetContext().getContentResolver());
+        when(mContext.getResources()).thenReturn(getContext().getResources());
+        when(mContext.getContentResolver()).thenReturn(getContext().getContentResolver());
         when(mContext.getPackageManager()).thenReturn(mPm);
         when(mContext.getSystemService(eq(Context.TELECOM_SERVICE))).thenReturn(mTm);
         when(mTm.getDefaultDialerPackage()).thenReturn(callPkg);
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java
index f0f4c4d..725e8f2 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -38,7 +38,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class NotificationListenerServiceTest {
+public class NotificationListenerServiceTest extends NotificationTestCase {
 
     private String[] mKeys = new String[] { "key", "key1", "key2", "key3"};
 
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 177c02d..9afb2d2 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -52,9 +52,9 @@
 import android.os.Binder;
 import android.os.Process;
 import android.os.UserHandle;
+import android.provider.Settings.Secure;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -75,7 +75,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
-public class NotificationManagerServiceTest {
+public class NotificationManagerServiceTest extends NotificationTestCase {
     private static final long WAIT_FOR_IDLE_TIMEOUT = 2;
     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
     private final int uid = Binder.getCallingUid();
@@ -86,7 +86,7 @@
     private IPackageManager mPackageManager;
     @Mock
     private PackageManager mPackageManagerClient;
-    private Context mContext = InstrumentationRegistry.getTargetContext();
+    private Context mContext = getContext();
     private final String PKG = mContext.getPackageName();
     private TestableLooper mTestableLooper;
     @Mock
@@ -122,6 +122,12 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+
+        // most tests assume badging is enabled
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 1,
+                UserHandle.getUserHandleForUid(uid).getIdentifier());
+
         mNotificationManagerService = new TestableNotificationManagerService(mContext);
 
         // MockPackageManager - default returns ApplicationInfo with matching calling UID
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 1c8ca84..267d2a6d 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -40,7 +40,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -56,7 +55,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class NotificationRecordTest {
+public class NotificationRecordTest extends NotificationTestCase {
 
     private final Context mMockContext = Mockito.mock(Context.class);
     @Mock PackageManager mPm;
@@ -96,8 +95,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        when(mMockContext.getResources()).thenReturn(
-                InstrumentationRegistry.getContext().getResources());
+        when(mMockContext.getResources()).thenReturn(getContext().getResources());
         when(mMockContext.getPackageManager()).thenReturn(mPm);
 
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationTestCase.java b/services/tests/notification/src/com/android/server/notification/NotificationTestCase.java
new file mode 100644
index 0000000..cc30aab
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/NotificationTestCase.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.notification;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.testing.TestableContext;
+
+import org.junit.Rule;
+
+
+public class NotificationTestCase {
+    @Rule
+    public final TestableContext mContext =
+            new TestableContext(InstrumentationRegistry.getContext(), null);
+
+    protected Context getContext() {
+        return mContext;
+    }
+}
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 7bef033..0f8c815 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -49,12 +49,16 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
+import android.provider.Settings.Secure;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableContext;
+import android.testing.TestableSettingsProvider;
 import android.util.ArrayMap;
+import android.util.Slog;
 import android.util.Xml;
 
 import java.io.BufferedInputStream;
@@ -80,16 +84,19 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class RankingHelperTest {
+public class RankingHelperTest extends NotificationTestCase {
     private static final String PKG = "com.android.server.notification";
     private static final int UID = 0;
+    private static final UserHandle USER = UserHandle.getUserHandleForUid(UID);
     private static final String UPDATED_PKG = "updatedPkg";
     private static final int UID2 = 1111111;
+    private static final UserHandle USER2 = UserHandle.getUserHandleForUid(UID2);
     private static final String TEST_CHANNEL_ID = "test_channel_id";
 
     @Mock NotificationUsageStats mUsageStats;
     @Mock RankingHandler mHandler;
     @Mock PackageManager mPm;
+    @Mock Context mContext;
 
     private Notification mNotiGroupGSortA;
     private Notification mNotiGroupGSortB;
@@ -104,69 +111,11 @@
     private RankingHelper mHelper;
     private AudioAttributes mAudioAttributes;
 
-    private Context getContext() {
-        return InstrumentationRegistry.getTargetContext();
-    }
-
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         UserHandle user = UserHandle.ALL;
 
-        mHelper = new RankingHelper(getContext(), mPm, mHandler, mUsageStats,
-                new String[] {ImportanceExtractor.class.getName()});
-
-        mNotiGroupGSortA = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
-                .setContentTitle("A")
-                .setGroup("G")
-                .setSortKey("A")
-                .setWhen(1205)
-                .build();
-        mRecordGroupGSortA = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, mNotiGroupGSortA, user,
-                null, System.currentTimeMillis()), getDefaultChannel());
-
-        mNotiGroupGSortB = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
-                .setContentTitle("B")
-                .setGroup("G")
-                .setSortKey("B")
-                .setWhen(1200)
-                .build();
-        mRecordGroupGSortB = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, mNotiGroupGSortB, user,
-                null, System.currentTimeMillis()), getDefaultChannel());
-
-        mNotiNoGroup = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
-                .setContentTitle("C")
-                .setWhen(1201)
-                .build();
-        mRecordNoGroup = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, mNotiNoGroup, user,
-                null, System.currentTimeMillis()), getDefaultChannel());
-
-        mNotiNoGroup2 = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
-                .setContentTitle("D")
-                .setWhen(1202)
-                .build();
-        mRecordNoGroup2 = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, mNotiNoGroup2, user,
-                null, System.currentTimeMillis()), getDefaultChannel());
-
-        mNotiNoGroupSortA = new Notification.Builder(getContext(), TEST_CHANNEL_ID)
-                .setContentTitle("E")
-                .setWhen(1201)
-                .setSortKey("A")
-                .build();
-        mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification(
-                "package", "package", 1, null, 0, 0, mNotiNoGroupSortA, user,
-                null, System.currentTimeMillis()), getDefaultChannel());
-
-        mAudioAttributes = new AudioAttributes.Builder()
-                .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
-                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
-                .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
-                .build();
-
         final ApplicationInfo legacy = new ApplicationInfo();
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
         final ApplicationInfo upgrade = new ApplicationInfo();
@@ -174,6 +123,67 @@
         when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy);
         when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(upgrade);
         when(mPm.getPackageUidAsUser(eq(PKG), anyInt())).thenReturn(UID);
+        when(mContext.getResources()).thenReturn(
+                InstrumentationRegistry.getContext().getResources());
+        when(mContext.getPackageManager()).thenReturn(mPm);
+        when(mContext.getApplicationInfo()).thenReturn(legacy);
+        // most tests assume badging is enabled
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 1, UserHandle.getUserId(UID));
+
+        mHelper = new RankingHelper(getContext(), mPm, mHandler, mUsageStats,
+                new String[] {ImportanceExtractor.class.getName()});
+
+        mNotiGroupGSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentTitle("A")
+                .setGroup("G")
+                .setSortKey("A")
+                .setWhen(1205)
+                .build();
+        mRecordGroupGSortA = new NotificationRecord(mContext, new StatusBarNotification(
+                PKG, PKG, 1, null, 0, 0, mNotiGroupGSortA, user,
+                null, System.currentTimeMillis()), getDefaultChannel());
+
+        mNotiGroupGSortB = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentTitle("B")
+                .setGroup("G")
+                .setSortKey("B")
+                .setWhen(1200)
+                .build();
+        mRecordGroupGSortB = new NotificationRecord(mContext, new StatusBarNotification(
+                PKG, PKG, 1, null, 0, 0, mNotiGroupGSortB, user,
+                null, System.currentTimeMillis()), getDefaultChannel());
+
+        mNotiNoGroup = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentTitle("C")
+                .setWhen(1201)
+                .build();
+        mRecordNoGroup = new NotificationRecord(mContext, new StatusBarNotification(
+                PKG, PKG, 1, null, 0, 0, mNotiNoGroup, user,
+                null, System.currentTimeMillis()), getDefaultChannel());
+
+        mNotiNoGroup2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentTitle("D")
+                .setWhen(1202)
+                .build();
+        mRecordNoGroup2 = new NotificationRecord(mContext, new StatusBarNotification(
+                PKG, PKG, 1, null, 0, 0, mNotiNoGroup2, user,
+                null, System.currentTimeMillis()), getDefaultChannel());
+
+        mNotiNoGroupSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setContentTitle("E")
+                .setWhen(1201)
+                .setSortKey("A")
+                .build();
+        mRecordNoGroupSortA = new NotificationRecord(mContext, new StatusBarNotification(
+                PKG, PKG, 1, null, 0, 0, mNotiNoGroupSortA, user,
+                null, System.currentTimeMillis()), getDefaultChannel());
+
+        mAudioAttributes = new AudioAttributes.Builder()
+                .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+                .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
+                .build();
     }
 
     private NotificationChannel getDefaultChannel() {
@@ -229,6 +239,10 @@
         assertEquals(expected.getName(), actual.getName());
     }
 
+    private NotificationChannel getChannel() {
+        return new NotificationChannel("id", "name", IMPORTANCE_LOW);
+    }
+
     @Test
     public void testFindAfterRankingWithASplitGroup() throws Exception {
         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3);
@@ -644,14 +658,119 @@
     }
 
     @Test
+    public void testClearLockedFields() throws Exception {
+        final NotificationChannel channel = getChannel();
+        mHelper.clearLockedFields(channel);
+        assertEquals(0, channel.getUserLockedFields());
+
+        channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_IMPORTANCE);
+        mHelper.clearLockedFields(channel);
+        assertEquals(0, channel.getUserLockedFields());
+    }
+
+    @Test
+    public void testLockFields_soundAndVibration() throws Exception {
+        mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
+
+        final NotificationChannel update1 = getChannel();
+        update1.setSound(new Uri.Builder().scheme("test").build(),
+                new AudioAttributes.Builder().build());
+        update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); // should be ignored
+        mHelper.updateNotificationChannel(PKG, UID, update1);
+        assertEquals(NotificationChannel.USER_LOCKED_SOUND,
+                mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
+                        .getUserLockedFields());
+
+        NotificationChannel update2 = getChannel();
+        update2.enableVibration(true);
+        mHelper.updateNotificationChannel(PKG, UID, update2);
+        assertEquals(NotificationChannel.USER_LOCKED_SOUND
+                        | NotificationChannel.USER_LOCKED_VIBRATION,
+                mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
+    public void testLockFields_vibrationAndLights() throws Exception {
+        mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
+
+        final NotificationChannel update1 = getChannel();
+        update1.setVibrationPattern(new long[]{7945, 46 ,246});
+        mHelper.updateNotificationChannel(PKG, UID, update1);
+        assertEquals(NotificationChannel.USER_LOCKED_VIBRATION,
+                mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update2 = getChannel();
+        update2.enableLights(true);
+        mHelper.updateNotificationChannel(PKG, UID, update2);
+        assertEquals(NotificationChannel.USER_LOCKED_VIBRATION
+                        | NotificationChannel.USER_LOCKED_LIGHTS,
+                mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
+    public void testLockFields_lightsAndImportance() throws Exception {
+        mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
+
+        final NotificationChannel update1 = getChannel();
+        update1.setLightColor(Color.GREEN);
+        mHelper.updateNotificationChannel(PKG, UID, update1);
+        assertEquals(NotificationChannel.USER_LOCKED_LIGHTS,
+                mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update2 = getChannel();
+        update2.setImportance(IMPORTANCE_DEFAULT);
+        mHelper.updateNotificationChannel(PKG, UID, update2);
+        assertEquals(NotificationChannel.USER_LOCKED_LIGHTS
+                        | NotificationChannel.USER_LOCKED_IMPORTANCE,
+                mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
+    public void testLockFields_visibilityAndDndAndBadge() throws Exception {
+        mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
+        assertEquals(0,
+                mHelper.getNotificationChannel(PKG, UID, getChannel().getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update1 = getChannel();
+        update1.setBypassDnd(true);
+        mHelper.updateNotificationChannel(PKG, UID, update1);
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY,
+                mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update2 = getChannel();
+        update2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        mHelper.updateNotificationChannel(PKG, UID, update2);
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
+                        | NotificationChannel.USER_LOCKED_VISIBILITY,
+                mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update3 = getChannel();
+        update3.setShowBadge(false);
+        mHelper.updateNotificationChannel(PKG, UID, update3);
+        assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
+                        | NotificationChannel.USER_LOCKED_VISIBILITY
+                        | NotificationChannel.USER_LOCKED_SHOW_BADGE,
+                mHelper.getNotificationChannel(PKG, UID, update3.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
     public void testDeleteNonExistentChannel() throws Exception {
         mHelper.deleteNotificationChannelGroup(PKG, UID, "does not exist");
     }
 
     @Test
     public void testGetDeletedChannel() throws Exception {
-        NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        NotificationChannel channel = getChannel();
         channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.enableLights(true);
         channel.setBypassDnd(true);
@@ -754,6 +873,15 @@
     }
 
     @Test
+    public void testOnlyHasDefaultChannel() throws Exception {
+        assertTrue(mHelper.onlyHasDefaultChannel(PKG, UID));
+        assertFalse(mHelper.onlyHasDefaultChannel(UPDATED_PKG, UID2));
+
+        mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
+        assertFalse(mHelper.onlyHasDefaultChannel(PKG, UID));
+    }
+
+    @Test
     public void testCreateChannel_defaultChannelId() throws Exception {
         try {
             mHelper.createNotificationChannel(PKG, UID, new NotificationChannel(
@@ -1084,4 +1212,36 @@
                     object.getInt("channelCount"));
         }
     }
+
+    @Test
+    public void testBadgingOverrideTrue() throws Exception {
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 1,
+                USER.getIdentifier());
+        mHelper.updateBadgingEnabled(); // would be called by settings observer
+        assertTrue(mHelper.badgingEnabled(USER));
+    }
+
+    @Test
+    public void testBadgingOverrideFalse() throws Exception {
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 0,
+                USER.getIdentifier());
+        mHelper.updateBadgingEnabled(); // would be called by settings observer
+        assertFalse(mHelper.badgingEnabled(USER));
+    }
+
+    @Test
+    public void testBadgingOverrideUserIsolation() throws Exception {
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 0,
+                USER.getIdentifier());
+        Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.NOTIFICATION_BADGING, 1,
+                USER2.getIdentifier());
+        mHelper.updateBadgingEnabled(); // would be called by settings observer
+        assertFalse(mHelper.badgingEnabled(USER));
+        assertTrue(mHelper.badgingEnabled(USER2));
+    }
+
 }
diff --git a/services/tests/notification/src/com/android/server/notification/RateEstimatorTest.java b/services/tests/notification/src/com/android/server/notification/RateEstimatorTest.java
index 07f3162..e354267 100644
--- a/services/tests/notification/src/com/android/server/notification/RateEstimatorTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RateEstimatorTest.java
@@ -26,7 +26,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class RateEstimatorTest {
+public class RateEstimatorTest extends NotificationTestCase {
     private long mTestStartTime;
     private RateEstimator mEstimator;
 
diff --git a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
index bc25860..07b21fb 100644
--- a/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/SnoozeHelperTest.java
@@ -27,11 +27,9 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.content.Context;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
-import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Slog;
@@ -51,7 +49,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class SnoozeHelperTest {
+public class SnoozeHelperTest extends NotificationTestCase {
     private static final String TEST_CHANNEL_ID = "test_channel_id";
 
     @Mock SnoozeHelper.Callback mCallback;
@@ -60,10 +58,6 @@
 
     private SnoozeHelper mSnoozeHelper;
 
-    private Context getContext() {
-        return InstrumentationRegistry.getTargetContext();
-    }
-
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
diff --git a/services/tests/notification/src/com/android/server/notification/ValidateNotificationPeopleTest.java b/services/tests/notification/src/com/android/server/notification/ValidateNotificationPeopleTest.java
index d09b858..4ac0c65 100644
--- a/services/tests/notification/src/com/android/server/notification/ValidateNotificationPeopleTest.java
+++ b/services/tests/notification/src/com/android/server/notification/ValidateNotificationPeopleTest.java
@@ -32,7 +32,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class ValidateNotificationPeopleTest {
+public class ValidateNotificationPeopleTest extends NotificationTestCase {
 
     @Test
     public void testNoExtra() throws Exception {
diff --git a/services/tests/servicestests/res/raw/backup_file_with_long_name b/services/tests/servicestests/res/raw/backup_file_with_long_name
new file mode 100644
index 0000000..265a0ba
--- /dev/null
+++ b/services/tests/servicestests/res/raw/backup_file_with_long_name
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 8784dd5..6b25d12 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -47,6 +47,7 @@
 
 import com.android.frameworks.servicestests.R;
 import com.android.server.backup.FileMetadata;
+import com.android.server.backup.RefactoredBackupManagerService;
 import com.android.server.backup.restore.PerformAdbRestoreTask;
 import com.android.server.backup.restore.RestorePolicy;
 import com.android.server.backup.testutils.PackageManagerStub;
@@ -61,6 +62,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.io.InputStream;
+import java.util.Arrays;
 import java.util.List;
 
 @SmallTest
@@ -71,6 +73,7 @@
     private static final String TELEPHONY_PACKAGE_SIGNATURE_SHA256 =
             "301aa3cb081134501c45f1422abc66c24224fd5ded5fdc8f17e697176fd866aa";
     private static final int TELEPHONY_PACKAGE_VERSION = 25;
+    private static final String TEST_PACKAGE_NAME = "com.android.backup.testing";
     private static final Signature FAKE_SIGNATURE_1 = new Signature("1234");
     private static final Signature FAKE_SIGNATURE_2 = new Signature("5678");
 
@@ -122,6 +125,45 @@
     }
 
     @Test
+    public void readTarHeaders_backupNotEncrypted_correctlyReadsPaxHeader() throws Exception {
+        // Files with long names (>100 chars) will force backup to add PAX header.
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_file_with_long_name);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+
+        // Read manifest file.
+        FileMetadata fileMetadata = tarBackupReader.readTarHeaders();
+        Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
+                fileMetadata);
+        RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
+                mPackageManagerStub, false /* allowApks */, fileMetadata, signatures);
+
+        assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
+        assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
+        assertThat(fileMetadata.path).isEqualTo(
+                RefactoredBackupManagerService.BACKUP_MANIFEST_FILENAME);
+
+        tarBackupReader.skipTarPadding(fileMetadata.size);
+
+        // Read actual file (PAX header will only exist here).
+        fileMetadata = tarBackupReader.readTarHeaders();
+        signatures = tarBackupReader.readAppManifestAndReturnSignatures(
+                fileMetadata);
+        restorePolicy = tarBackupReader.chooseRestorePolicy(
+                mPackageManagerStub, false /* allowApks */, fileMetadata, signatures);
+
+        assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
+        assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
+        char[] expectedFileNameChars = new char[200];
+        Arrays.fill(expectedFileNameChars, '1');
+        String expectedFileName = new String(expectedFileNameChars);
+        assertThat(fileMetadata.path).isEqualTo(expectedFileName);
+    }
+
+    @Test
     public void readAppManifest_backupEncrypted_correctlyParsesAppManifest() throws Exception {
         InputStream inputStream = mContext.getResources().openRawResource(
                 R.raw.backup_telephony_with_password);
@@ -331,7 +373,8 @@
     }
 
     @Test
-    public void chooseRestorePolicy_systemAppWithBackupAgentAndRestoreAnyVersion_returnsAccept() throws Exception {
+    public void chooseRestorePolicy_systemAppWithBackupAgentAndRestoreAnyVersion_returnsAccept()
+            throws Exception {
         InputStream inputStream = mContext.getResources().openRawResource(
                 R.raw.backup_telephony_no_password);
         InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
@@ -486,5 +529,5 @@
         assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
                 LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER);
     }
+}
 
-}
\ No newline at end of file
diff --git a/services/usb/Android.mk b/services/usb/Android.mk
index 4cc0cef..55bfccf 100644
--- a/services/usb/Android.mk
+++ b/services/usb/Android.mk
@@ -7,9 +7,10 @@
 LOCAL_SRC_FILES += \
       $(call all-java-files-under,java)
 
-LOCAL_JAVA_LIBRARIES := services.core
-LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java-static \
-android.hardware.usb-V1.1-java-static \
-android.hidl.manager-V1.0-java-static
+LOCAL_JAVA_LIBRARIES := services.core \
+android.hidl.manager-V1.0-java
+
+LOCAL_STATIC_JAVA_LIBRARIES := android.hardware.usb-V1.0-java \
+android.hardware.usb-V1.1-java
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/telephony/java/android/telephony/MbmsStreamingManager.java b/telephony/java/android/telephony/MbmsStreamingManager.java
index fc406ee..58262e1 100644
--- a/telephony/java/android/telephony/MbmsStreamingManager.java
+++ b/telephony/java/android/telephony/MbmsStreamingManager.java
@@ -22,7 +22,6 @@
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.os.DeadObjectException;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.telephony.mbms.IMbmsStreamingManagerCallback;
@@ -96,15 +95,15 @@
     /**
      * Create a new MbmsStreamingManager using the given subscription ID.
      *
-     * Note that this call will bind a remote service and that may take a bit.  This
-     * may throw an {@link MbmsException}, indicating errors that may happen during
-     * the initialization or binding process.
+     * Note that this call will bind a remote service. You may not call this method on your app's
+     * main thread. This may throw an {@link MbmsException}, indicating errors that may happen
+     * during the initialization or binding process.
      *
-     * @param context
-     * @param listener
-     * @param streamingAppName
-     * @param subscriptionId
-     * @return
+     * @param context The {@link Context} to use.
+     * @param listener A callback object on which you wish to receive results of asynchronous
+     *                 operations.
+     * @param streamingAppName The name of the streaming app, as specified by the carrier.
+     * @param subscriptionId The subscription ID to use.
      */
     public static MbmsStreamingManager create(Context context,
             IMbmsStreamingManagerCallback listener, String streamingAppName, int subscriptionId)
@@ -117,9 +116,7 @@
 
     /**
      * Create a new MbmsStreamingManager using the system default data subscription ID.
-     *
-     * Note that this call will bind a remote service and that may take a bit.  This
-     * may throw an IllegalArgumentException or RemoteException.
+     * See {@link #create(Context, IMbmsStreamingManagerCallback, String, int)}.
      */
     public static MbmsStreamingManager create(Context context,
             IMbmsStreamingManagerCallback listener, String streamingAppName)
@@ -156,19 +153,29 @@
      *
      * Multiple calls replace the list of serviceClasses of interest.
      *
-     * May throw an IllegalArgumentException or RemoteException.
+     * This may throw an {@link MbmsException} containing one of the following errors:
+     * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
+     * {@link MbmsException#ERROR_NOT_YET_INITIALIZED}
+     * {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
      *
-     * Synchronous responses include
-     * <li>SUCCESS</li>
-     * <li>ERROR_MSDC_CONCURRENT_SERVICE_LIMIT_REACHED</li>
-     *
-     * Asynchronous errors through the listener include any of the errors except
-     * <li>ERROR_MSDC_UNABLE_TO_)START_SERVICE</li>
-     * <li>ERROR_MSDC_INVALID_SERVICE_ID</li>
-     * <li>ERROR_MSDC_END_OF_SESSION</li>
+     * Asynchronous error codes via the {@link IMbmsStreamingManagerCallback#error(int, String)}
+     * callback can include any of the errors except:
+     * {@link MbmsException#ERROR_UNABLE_TO_START_SERVICE}
+     * {@link MbmsException#ERROR_INVALID_SERVICE_ID}
+     * {@link MbmsException#ERROR_END_OF_SESSION}
      */
-    public int getStreamingServices(List<String> classList) {
-        return 0;
+    public void getStreamingServices(List<String> classList) throws MbmsException {
+        if (mService == null) {
+            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
+        }
+        try {
+            int returnCode = mService.getStreamingServices(mAppName, mSubscriptionId, classList);
+            if (returnCode != MbmsException.SUCCESS) {
+                throw new MbmsException(returnCode);
+            }
+        } catch (RemoteException e) {
+            throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
+        }
     }
 
     /**
@@ -262,7 +269,7 @@
             } catch (RemoteException e) {
                 mService = null;
                 Log.e(LOG_TAG, "Service died before initialization");
-                throw new MbmsException(MbmsException.ERROR_INITIALIZATION_REMOTE_EXCEPTION);
+                throw new MbmsException(MbmsException.ERROR_UNKNOWN_REMOTE_EXCEPTION);
             }
         }
     }
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index d6e74cf..dcdda86 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -463,9 +463,28 @@
      */
     public static SubmitPdu getSubmitPdu(String scAddress,
             String destinationAddress, String message, boolean statusReportRequested) {
-        SubmitPduBase spb;
+        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested,
+                SubscriptionManager.getDefaultSmsSubscriptionId());
+    }
 
-        if (useCdmaFormatForMoSms()) {
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message.
+     * This method will not attempt to use any GSM national language 7 bit encodings.
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @param destinationAddress the address of the destination for the message.
+     * @param message String representation of the message payload.
+     * @param statusReportRequested Indicates whether a report is requested for this message.
+     * @param subId Subscription of the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message, boolean statusReportRequested, int subId) {
+        SubmitPduBase spb;
+        if (useCdmaFormatForMoSms(subId)) {
             spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
                     destinationAddress, message, statusReportRequested, null);
         } else {
@@ -758,12 +777,27 @@
      * @return true if Cdma format should be used for MO SMS, false otherwise.
      */
     private static boolean useCdmaFormatForMoSms() {
-        if (!SmsManager.getDefault().isImsSmsSupported()) {
+        // IMS is registered with SMS support, check the SMS format supported
+        return useCdmaFormatForMoSms(SubscriptionManager.getDefaultSmsSubscriptionId());
+    }
+
+    /**
+     * Determines whether or not to use CDMA format for MO SMS.
+     * If SMS over IMS is supported, then format is based on IMS SMS format,
+     * otherwise format is based on current phone type.
+     *
+     * @param subId Subscription for which phone type is returned.
+     *
+     * @return true if Cdma format should be used for MO SMS, false otherwise.
+     */
+    private static boolean useCdmaFormatForMoSms(int subId) {
+        SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
+        if (!smsManager.isImsSmsSupported()) {
             // use Voice technology to determine SMS format.
-            return isCdmaVoice();
+            return isCdmaVoice(subId);
         }
         // IMS is registered with SMS support, check the SMS format supported
-        return (SmsConstants.FORMAT_3GPP2.equals(SmsManager.getDefault().getImsSmsFormat()));
+        return (SmsConstants.FORMAT_3GPP2.equals(smsManager.getImsSmsFormat()));
     }
 
     /**
@@ -772,10 +806,18 @@
      * @return true if current phone type is cdma, false otherwise.
      */
     private static boolean isCdmaVoice() {
-        int activePhone = TelephonyManager.getDefault().getCurrentPhoneType();
-        return (PHONE_TYPE_CDMA == activePhone);
+        return isCdmaVoice(SubscriptionManager.getDefaultSmsSubscriptionId());
     }
 
+     /**
+      * Determines whether or not to current phone type is cdma
+      *
+      * @return true if current phone type is cdma, false otherwise.
+      */
+     private static boolean isCdmaVoice(int subId) {
+         int activePhone = TelephonyManager.getDefault().getCurrentPhoneType(subId);
+         return (PHONE_TYPE_CDMA == activePhone);
+   }
     /**
      * Decide if the carrier supports long SMS.
      * {@hide}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0dd6c0b..c8ff08c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6611,5 +6611,26 @@
         }
         return false;
     }
+
+    /**
+     * Get the most recently available signal strength information.
+     *
+     * Get the most recent SignalStrength information reported by the modem. Due
+     * to power saving this information may not always be current.
+     * @return the most recent cached signal strength info from the modem
+     * @hide
+     */
+    @Nullable
+    public SignalStrength getSignalStrength() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.getSignalStrength(getSubId());
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#getSignalStrength", e);
+        }
+        return null;
+    }
 }
 
diff --git a/telephony/java/android/telephony/mbms/MbmsException.java b/telephony/java/android/telephony/mbms/MbmsException.java
index cc4a02a..e8680ea 100644
--- a/telephony/java/android/telephony/mbms/MbmsException.java
+++ b/telephony/java/android/telephony/mbms/MbmsException.java
@@ -16,16 +16,21 @@
 
 package android.telephony.mbms;
 
-import android.os.RemoteException;
-
 /** @hide */
-public class MbmsException extends RemoteException {
+public class MbmsException extends Exception {
     public static final int SUCCESS = 0;
     public static final int ERROR_NO_SERVICE_INSTALLED = 1;
     public static final int ERROR_MULTIPLE_SERVICES_INSTALLED = 2;
     public static final int ERROR_BIND_TIMEOUT_OR_FAILURE = 3;
-    public static final int ERROR_INITIALIZATION_REMOTE_EXCEPTION = 4;
+    public static final int ERROR_UNKNOWN_REMOTE_EXCEPTION = 4;
     public static final int ERROR_ALREADY_INITIALIZED = 5;
+    public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 6;
+    public static final int ERROR_MIDDLEWARE_NOT_BOUND = 7;
+    public static final int ERROR_UNABLE_TO_START_SERVICE = 8;
+    public static final int ERROR_INVALID_SERVICE_ID = 9;
+    public static final int ERROR_END_OF_SESSION = 10;
+    public static final int ERROR_NOT_YET_INITIALIZED = 11;
+    public static final int ERROR_APP_PERMISSIONS_NOT_GRANTED = 12;
 
     private final int mErrorCode;
 
diff --git a/telephony/java/android/telephony/mbms/ServiceInfo.java b/telephony/java/android/telephony/mbms/ServiceInfo.java
index cb621c8..f167f0ab 100644
--- a/telephony/java/android/telephony/mbms/ServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/ServiceInfo.java
@@ -114,6 +114,7 @@
         sessionEndTime = (java.util.Date) in.readSerializable();
     }
 
+    @Override
     public void writeToParcel(Parcel dest, int flags) {
         Set<Locale> keySet = names.keySet();
         dest.writeInt(keySet.size());
@@ -128,7 +129,33 @@
         dest.writeSerializable(sessionEndTime);
     }
 
+    @Override
     public int describeContents() {
         return 0;
     }
+
+    public Map<Locale, String> getNames() {
+        return names;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public Locale getLocale() {
+        return locale;
+    }
+
+    public String getServiceId() {
+        return serviceId;
+    }
+
+    public Date getSessionStartTime() {
+        return sessionStartTime;
+    }
+
+    public Date getSessionEndTime() {
+        return sessionEndTime;
+    }
+
 }
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
index ddc661d..fed0a40 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
@@ -29,22 +29,8 @@
  */
 interface IMbmsStreamingService
 {
-    /**
-     * Initialize streaming service
-     * Registers this listener, subId with this appName
-     *
-     */
     int initialize(IMbmsStreamingManagerCallback listener, String appName, int subId);
 
-
-    /**
-     * - Registers serviceClasses of interest with the uid/appName/subId key.
-     * - Starts asynch fetching data on streaming services of matching classes to be reported
-     * later by callback.
-     *
-     * Note that subsequent calls with the same callback, appName, subId and uid will replace
-     * the service class list.
-     */
     int getStreamingServices(String appName, int subId, in List<String> serviceClasses);
 
     /**
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
index 9f0c0e9..e23d12b 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
@@ -20,7 +20,7 @@
 import android.os.RemoteException;
 import android.telephony.mbms.IMbmsStreamingManagerCallback;
 import android.telephony.mbms.IStreamingServiceCallback;
-import android.telephony.mbms.StreamingService;
+import android.telephony.mbms.MbmsException;
 
 import java.util.List;
 
@@ -29,16 +29,42 @@
  * TODO: future systemapi
  */
 public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
-
+    /**
+     * Initialize streaming service for this app and subId, registering the listener.
+     *
+     * @param listener The callback to use to communicate with the app.
+     * @param appName The app name as negotiated with the wireless carrier.
+     * @param subscriptionId The subscription ID to use.
+     * @return {@link MbmsException#SUCCESS}, {@link MbmsException#ERROR_ALREADY_INITIALIZED}, or
+     *         {@link MbmsException#ERROR_APP_PERMISSIONS_NOT_GRANTED}
+     */
     @Override
-    public int initialize(IMbmsStreamingManagerCallback listener, String appName, int subId)
-            throws RemoteException {
+    public int initialize(IMbmsStreamingManagerCallback listener, String appName,
+            int subscriptionId) throws RemoteException {
         return 0;
     }
 
+    /**
+     * Registers serviceClasses of interest with the appName/subId key.
+     * Starts async fetching data on streaming services of matching classes to be reported
+     * later via {@link IMbmsStreamingManagerCallback#streamingServicesUpdated(List)}
+     *
+     * Note that subsequent calls with the same uid, appName and subId will replace
+     * the service class list.
+     *
+     * @param appName The app name as negotiated with the wireless carrier.
+     * @param subscriptionId The subscription id to use.
+     * @param serviceClasses The service classes that the app wishes to get info on. The strings
+     *                       may contain arbitrary data as negotiated between the app and the
+     *                       carrier.
+     * @return One of {@link MbmsException#SUCCESS},
+     *         {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND},
+     *         {@link MbmsException#ERROR_NOT_YET_INITIALIZED}, or
+     *         {@link MbmsException#ERROR_CONCURRENT_SERVICE_LIMIT_REACHED}
+     */
     @Override
-    public int getStreamingServices(String appName, int subId, List<String> serviceClasses)
-            throws RemoteException {
+    public int getStreamingServices(String appName, int subscriptionId,
+            List<String> serviceClasses) throws RemoteException {
         return 0;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 7c74729..c53f5d3 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -34,6 +34,7 @@
 import android.telephony.NetworkScanRequest;
 import android.telephony.RadioAccessFamily;
 import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
 import android.telephony.TelephonyHistogram;
 import android.telephony.VisualVoicemailSmsFilterSettings;
 import com.android.ims.internal.IImsServiceController;
@@ -1343,4 +1344,15 @@
      * @hide
      */
     boolean getEmergencyCallbackMode(int subId);
+
+    /**
+     * Get the most recently available signal strength information.
+     *
+     * Get the most recent SignalStrength information reported by the modem. Due
+     * to power saving this information may not always be current.
+     * @param subId Subscription index
+     * @return the most recent cached signal strength info from the modem
+     * @hide
+     */
+    SignalStrength getSignalStrength(int subId);
 }
diff --git a/test-runner/src/android/test/AndroidTestRunner.java b/test-runner/src/android/test/AndroidTestRunner.java
index 50eaafb..7313a28 100644
--- a/test-runner/src/android/test/AndroidTestRunner.java
+++ b/test-runner/src/android/test/AndroidTestRunner.java
@@ -20,8 +20,7 @@
 import android.content.Context;
 import android.os.PerformanceCollector.PerformanceResultsWriter;
 
-import com.google.android.collect.Lists;
-
+import java.util.ArrayList;
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestListener;
@@ -48,7 +47,7 @@
     private Context mContext;
     private boolean mSkipExecution = false;
 
-    private List<TestListener> mTestListeners = Lists.newArrayList();
+    private List<TestListener> mTestListeners = new ArrayList<>();
     private Instrumentation mInstrumentation;
     private PerformanceResultsWriter mPerfWriter;
 
@@ -58,7 +57,8 @@
 
         if (shouldRunSingleTestMethod(testMethodName, testClass)) {
             TestCase testCase = buildSingleTestMethod(testClass, testMethodName);
-            mTestCases = Lists.newArrayList(testCase);
+            mTestCases = new ArrayList<>();
+            mTestCases.add(testCase);
             mTestClassName = testClass.getSimpleName();
         } else {
             setTest(getTest(testClass), testClass);
diff --git a/test-runner/src/android/test/ClassPathPackageInfo.java b/test-runner/src/android/test/ClassPathPackageInfo.java
index 1ab7c7f..2cf76af 100644
--- a/test-runner/src/android/test/ClassPathPackageInfo.java
+++ b/test-runner/src/android/test/ClassPathPackageInfo.java
@@ -16,9 +16,8 @@
 
 package android.test;
 
-import com.google.android.collect.Sets;
-
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -44,7 +43,7 @@
     }
 
     public Set<ClassPathPackageInfo> getSubpackages() {
-        Set<ClassPathPackageInfo> info = Sets.newHashSet();
+        Set<ClassPathPackageInfo> info = new HashSet<>();
         for (String name : subpackageNames) {
             info.add(source.getPackageInfo(name));
         }
@@ -52,7 +51,7 @@
     }
 
     public Set<Class<?>> getTopLevelClassesRecursive() {
-        Set<Class<?>> set = Sets.newHashSet();
+        Set<Class<?>> set = new HashSet<>();
         addTopLevelClassesTo(set);
         return set;
     }
diff --git a/test-runner/src/android/test/ClassPathPackageInfoSource.java b/test-runner/src/android/test/ClassPathPackageInfoSource.java
index 89bb494..9bcc25a 100644
--- a/test-runner/src/android/test/ClassPathPackageInfoSource.java
+++ b/test-runner/src/android/test/ClassPathPackageInfoSource.java
@@ -17,13 +17,13 @@
 package android.test;
 
 import android.util.Log;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
 import dalvik.system.DexFile;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
@@ -57,7 +57,7 @@
     private static String[] apkPaths;
 
     // A cache of jar file contents
-    private final Map<File, Set<String>> jarFiles = Maps.newHashMap();
+    private final Map<File, Set<String>> jarFiles = new HashMap<>();
     private ClassLoader classLoader;
 
     ClassPathPackageInfoSource() {
@@ -76,7 +76,7 @@
     private ClassPathPackageInfo createPackageInfo(String packageName) {
         Set<String> subpackageNames = new TreeSet<String>();
         Set<String> classNames = new TreeSet<String>();
-        Set<Class<?>> topLevelClasses = Sets.newHashSet();
+        Set<Class<?>> topLevelClasses = new HashSet<>();
         findClasses(packageName, classNames, subpackageNames);
         for (String className : classNames) {
             if (className.endsWith(".R") || className.endsWith(".Manifest")) {
@@ -248,7 +248,7 @@
             throws IOException {
         Set<String> entryNames = jarFiles.get(jarFile);
         if (entryNames == null) {
-            entryNames = Sets.newHashSet();
+            entryNames = new HashSet<>();
             ZipFile zipFile = new ZipFile(jarFile);
             Enumeration<? extends ZipEntry> entries = zipFile.entries();
             while (entries.hasMoreElements()) {
diff --git a/test-runner/src/android/test/DatabaseTestUtils.java b/test-runner/src/android/test/DatabaseTestUtils.java
index 42ef48b..1980d92 100644
--- a/test-runner/src/android/test/DatabaseTestUtils.java
+++ b/test-runner/src/android/test/DatabaseTestUtils.java
@@ -16,11 +16,10 @@
 
 package android.test;
 
-import com.google.android.collect.Sets;
-
 import android.database.sqlite.SQLiteDatabase;
 import android.database.Cursor;
 
+import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -42,7 +41,7 @@
     }
 
     private static Set<String> getSchemaSet(SQLiteDatabase db) {
-        Set<String> schemaSet = Sets.newHashSet();
+        Set<String> schemaSet = new HashSet<>();
 
         Cursor entityCursor = db.rawQuery("SELECT sql FROM sqlite_master", null);
         try {
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index 3abf38f..0b77c00 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -16,8 +16,6 @@
 
 package android.test;
 
-import com.google.android.collect.Lists;
-
 import android.accounts.AccountManager;
 import android.accounts.AccountManagerCallback;
 import android.accounts.AccountManagerFuture;
@@ -38,6 +36,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 import java.util.List;
 
@@ -55,7 +54,7 @@
     private ContentResolver mResolver;
     private final MockAccountManager mMockAccountManager;
 
-    private List<Intent> mBroadcastIntents = Lists.newArrayList();
+    private List<Intent> mBroadcastIntents = new ArrayList<>();
 
     public IsolatedContext(
             ContentResolver resolver, Context targetContext) {
@@ -67,7 +66,7 @@
     /** Returns the list of intents that were broadcast since the last call to this method. */
     public List<Intent> getAndClearBroadcastIntents() {
         List<Intent> intents = mBroadcastIntents;
-        mBroadcastIntents = Lists.newArrayList();
+        mBroadcastIntents = new ArrayList<>();
         return intents;
     }
 
diff --git a/test-runner/src/android/test/RenamingDelegatingContext.java b/test-runner/src/android/test/RenamingDelegatingContext.java
index 36786b0..fd33321 100644
--- a/test-runner/src/android/test/RenamingDelegatingContext.java
+++ b/test-runner/src/android/test/RenamingDelegatingContext.java
@@ -16,20 +16,24 @@
 
 package android.test;
 
-import com.google.android.collect.Sets;
-
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.ContentProvider;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
-import android.os.FileUtils;
 import android.util.Log;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.util.EnumSet;
+import java.util.HashSet;
 import java.util.Set;
 
 /**
@@ -48,8 +52,8 @@
     private File mCacheDir;
     private final Object mSync = new Object();
 
-    private Set<String> mDatabaseNames = Sets.newHashSet();
-    private Set<String> mFileNames = Sets.newHashSet();
+    private Set<String> mDatabaseNames = new HashSet<>();
+    private Set<String> mFileNames = new HashSet<>();
 
     public static <T extends ContentProvider> T providerWithRenamedContext(
             Class<T> contentProvider, Context c, String filePrefix)
@@ -237,10 +241,14 @@
                     Log.w("RenamingDelegatingContext", "Unable to create cache directory");
                     return null;
                 }
-                FileUtils.setPermissions(
-                        mCacheDir.getPath(),
-                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-                        -1, -1);
+                try {
+                    // Give the directory all possible permissions.
+                    Files.setPosixFilePermissions(mCacheDir.toPath(),
+                            EnumSet.allOf(PosixFilePermission.class));
+                } catch (IOException e) {
+                    Log.e("RenamingDelegatingContext",
+                            "Could not set permissions of test cacheDir", e);
+                }
             }
         }
         return mCacheDir;
diff --git a/test-runner/src/android/test/TestCaseUtil.java b/test-runner/src/android/test/TestCaseUtil.java
index c46d403..dc053a2 100644
--- a/test-runner/src/android/test/TestCaseUtil.java
+++ b/test-runner/src/android/test/TestCaseUtil.java
@@ -16,8 +16,7 @@
 
 package android.test;
 
-import com.google.android.collect.Lists;
-
+import java.util.ArrayList;
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
@@ -44,7 +43,7 @@
     @SuppressWarnings("unchecked")
     public static List<String> getTestCaseNames(Test test, boolean flatten) {
         List<Test> tests = (List<Test>) getTests(test, flatten);
-        List<String> testCaseNames = Lists.newArrayList();
+        List<String> testCaseNames = new ArrayList<>();
         for (Test aTest : tests) {
             testCaseNames.add(getTestName(aTest));
         }
@@ -57,7 +56,7 @@
 
     private static List<? extends Test> getTests(Test test, boolean flatten,
             Set<Class<?>> seen) {
-        List<Test> testCases = Lists.newArrayList();
+        List<Test> testCases = new ArrayList<>();
         if (test != null) {
 
             Test workingTest = null;
diff --git a/test-runner/src/android/test/TestRunner.java b/test-runner/src/android/test/TestRunner.java
index beecc6f..ff045c3 100644
--- a/test-runner/src/android/test/TestRunner.java
+++ b/test-runner/src/android/test/TestRunner.java
@@ -32,7 +32,6 @@
 import junit.framework.TestListener;
 import junit.framework.Test;
 import junit.framework.TestResult;
-import com.google.android.collect.Lists;
 
 /**
  * Support class that actually runs a test. Android uses this class,
@@ -54,7 +53,7 @@
 
     private int mMode = REGRESSION;
 
-    private List<Listener> mListeners = Lists.newArrayList();
+    private List<Listener> mListeners = new ArrayList<>();
     private int mPassed;
     private int mFailed;
 
diff --git a/test-runner/src/android/test/mock/MockContentResolver.java b/test-runner/src/android/test/mock/MockContentResolver.java
index d8e0977..a70152c 100644
--- a/test-runner/src/android/test/mock/MockContentResolver.java
+++ b/test-runner/src/android/test/mock/MockContentResolver.java
@@ -23,8 +23,7 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 
-import com.google.android.collect.Maps;
-
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -67,7 +66,7 @@
      */
     public MockContentResolver(Context context) {
         super(context);
-        mProviders = Maps.newHashMap();
+        mProviders = new HashMap<>();
     }
 
     /**
diff --git a/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java b/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
index 3b920cf..cf6936b 100644
--- a/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
+++ b/test-runner/src/android/test/suitebuilder/TestSuiteBuilder.java
@@ -21,7 +21,6 @@
 import android.test.TestCaseUtil;
 import android.util.Log;
 import com.android.internal.util.Predicate;
-import com.google.android.collect.Lists;
 import static android.test.suitebuilder.TestGrouping.SORT_BY_FULLY_QUALIFIED_NAME;
 import static android.test.suitebuilder.TestPredicates.REJECT_SUPPRESSED;
 
@@ -69,7 +68,7 @@
     public TestSuiteBuilder(String name, ClassLoader classLoader) {
         this.suiteName = name;
         this.testGrouping.setClassLoader(classLoader);
-        this.testCases = Lists.newArrayList();
+        this.testCases = new ArrayList<>();
         addRequirements(REJECT_SUPPRESSED);
     }
 
diff --git a/test-runner/tests/src/android/test/AndroidTestRunnerTest.java b/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
index 0574704..6723548 100644
--- a/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
+++ b/test-runner/tests/src/android/test/AndroidTestRunnerTest.java
@@ -19,8 +19,7 @@
 import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.google.android.collect.Lists;
-
+import java.util.ArrayList;
 import junit.framework.TestCase;
 import junit.framework.AssertionFailedError;
 import junit.framework.Test;
@@ -140,7 +139,7 @@
     public void testSetTestClassWithTestSuiteProvider() throws Exception {
         mAndroidTestRunner.setTestClassName(SampleTestSuiteProvider.class.getName(), null);
         List<TestCase> testCases = mAndroidTestRunner.getTestCases();
-        List<String> testNames = Lists.newArrayList();
+        List<String> testNames = new ArrayList<>();
         for (TestCase testCase : testCases) {
             testNames.add(testCase.getName());
         }
@@ -152,7 +151,7 @@
     public void testSetTestClassWithTestSuite() throws Exception {
         mAndroidTestRunner.setTestClassName(SampleTestSuite.class.getName(), null);
         List<TestCase> testCases = mAndroidTestRunner.getTestCases();
-        List<String> testNames = Lists.newArrayList();
+        List<String> testNames = new ArrayList<>();
         for (TestCase testCase : testCases) {
             testNames.add(testCase.getName());
         }
@@ -163,7 +162,7 @@
         String testMethodName = "testTwo";
         mAndroidTestRunner.setTestClassName(TwoTestTestCase.class.getName(), testMethodName);
         List<TestCase> testCases = mAndroidTestRunner.getTestCases();
-        List<String> testNames = Lists.newArrayList();
+        List<String> testNames = new ArrayList<>();
         for (TestCase testCase : testCases) {
             testNames.add(testCase.getName());
         }
@@ -255,7 +254,7 @@
     }
 
     private static class TestListenerStub implements TestListener {
-        List<String> testNames = Lists.newArrayList();
+        List<String> testNames = new ArrayList<>();
 
         public void addError(Test test, Throwable t) {
         }
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index ceb0135..cc792cc 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -45,6 +45,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.PendingIntent;
 import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
 import android.content.Context;
@@ -66,8 +67,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-
-
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class ConnectivityManagerTest {
@@ -296,6 +295,43 @@
         manager.requestNetwork(request, callback);
     }
 
+    @Test
+    public void testArgumentValidation() throws Exception {
+        ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
+
+        NetworkRequest request = mock(NetworkRequest.class);
+        NetworkCallback callback = mock(NetworkCallback.class);
+        Handler handler = mock(Handler.class);
+        NetworkCallback nullCallback = null;
+        PendingIntent nullIntent = null;
+
+        mustFail(() -> { manager.requestNetwork(null, callback); });
+        mustFail(() -> { manager.requestNetwork(request, nullCallback); });
+        mustFail(() -> { manager.requestNetwork(request, callback, null); });
+        mustFail(() -> { manager.requestNetwork(request, callback, -1); });
+        mustFail(() -> { manager.requestNetwork(request, nullIntent); });
+
+        mustFail(() -> { manager.registerNetworkCallback(null, callback, handler); });
+        mustFail(() -> { manager.registerNetworkCallback(request, null, handler); });
+        mustFail(() -> { manager.registerNetworkCallback(request, callback, null); });
+        mustFail(() -> { manager.registerNetworkCallback(request, nullIntent); });
+
+        mustFail(() -> { manager.registerDefaultNetworkCallback(null, handler); });
+        mustFail(() -> { manager.registerDefaultNetworkCallback(callback, null); });
+
+        mustFail(() -> { manager.unregisterNetworkCallback(nullCallback); });
+        mustFail(() -> { manager.unregisterNetworkCallback(nullIntent); });
+        mustFail(() -> { manager.releaseNetworkRequest(nullIntent); });
+    }
+
+    static void mustFail(Runnable fn) {
+        try {
+            fn.run();
+            fail();
+        } catch (Exception expected) {
+        }
+    }
+
     static Message makeMessage(NetworkRequest req, int messageType) {
         Bundle bundle = new Bundle();
         bundle.putParcelable(NetworkRequest.class.getSimpleName(), req);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 46dcdad..0099861 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -44,6 +44,7 @@
 import android.net.ConnectivityManager.NetworkCallback;
 import android.net.ConnectivityManager.PacketKeepalive;
 import android.net.ConnectivityManager.PacketKeepaliveCallback;
+import android.net.ConnectivityManager.TooManyRequestsException;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
 import android.net.IpPrefix;
@@ -3055,7 +3056,7 @@
                 networkCallbacks.add(networkCallback);
             }
             fail("Registering " + MAX_REQUESTS + " NetworkRequests did not throw exception");
-        } catch (IllegalArgumentException expected) {}
+        } catch (TooManyRequestsException expected) {}
         for (NetworkCallback networkCallback : networkCallbacks) {
             mCm.unregisterNetworkCallback(networkCallback);
         }
@@ -3068,7 +3069,7 @@
                 networkCallbacks.add(networkCallback);
             }
             fail("Registering " + MAX_REQUESTS + " NetworkCallbacks did not throw exception");
-        } catch (IllegalArgumentException expected) {}
+        } catch (TooManyRequestsException expected) {}
         for (NetworkCallback networkCallback : networkCallbacks) {
             mCm.unregisterNetworkCallback(networkCallback);
         }
@@ -3084,7 +3085,7 @@
             }
             fail("Registering " + MAX_REQUESTS +
                     " PendingIntent NetworkRequests did not throw exception");
-        } catch (IllegalArgumentException expected) {}
+        } catch (TooManyRequestsException expected) {}
         for (PendingIntent pendingIntent : pendingIntents) {
             mCm.unregisterNetworkCallback(pendingIntent);
         }
@@ -3099,7 +3100,7 @@
             }
             fail("Registering " + MAX_REQUESTS +
                     " PendingIntent NetworkCallbacks did not throw exception");
-        } catch (IllegalArgumentException expected) {}
+        } catch (TooManyRequestsException expected) {}
         for (PendingIntent pendingIntent : pendingIntents) {
             mCm.unregisterNetworkCallback(pendingIntent);
         }
diff --git a/tests/testables/Android.mk b/tests/testables/Android.mk
index 759bc35..0e36981 100644
--- a/tests/testables/Android.mk
+++ b/tests/testables/Android.mk
@@ -31,3 +31,5 @@
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/testables/src/android/testing/TestableSettingsProvider.java b/tests/testables/src/android/testing/TestableSettingsProvider.java
index 13056cf..fe97bca1 100644
--- a/tests/testables/src/android/testing/TestableSettingsProvider.java
+++ b/tests/testables/src/android/testing/TestableSettingsProvider.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.test.mock.MockContentProvider;
 import android.util.Log;
@@ -48,9 +49,10 @@
     }
 
     void clearValuesAndCheck(Context context) {
-        mValues.put(key("global", MY_UNIQUE_KEY), MY_UNIQUE_KEY);
-        mValues.put(key("secure", MY_UNIQUE_KEY), MY_UNIQUE_KEY);
-        mValues.put(key("system", MY_UNIQUE_KEY), MY_UNIQUE_KEY);
+        int userId = UserHandle.myUserId();
+        mValues.put(key("global", MY_UNIQUE_KEY, userId), MY_UNIQUE_KEY);
+        mValues.put(key("secure", MY_UNIQUE_KEY, userId), MY_UNIQUE_KEY);
+        mValues.put(key("system", MY_UNIQUE_KEY, userId), MY_UNIQUE_KEY);
 
         // Verify that if any test is using TestableContext, they all have the correct settings
         // provider.
@@ -66,11 +68,12 @@
 
     public Bundle call(String method, String arg, Bundle extras) {
         // Methods are "GET_system", "GET_global", "PUT_secure", etc.
+        final int userId = extras.getInt(Settings.CALL_METHOD_USER_KEY, 0);
         final String[] commands = method.split("_", 2);
         final String op = commands[0];
         final String table = commands[1];
 
-            String k = key(table, arg);
+            String k = key(table, arg, userId);
             String value;
             Bundle out = new Bundle();
             switch (op) {
@@ -103,8 +106,13 @@
             return out;
     }
 
-    private static String key(String table, String key) {
-        return table + "_" + key;
+    private static String key(String table, String key, int userId) {
+        if ("global".equals(table)) {
+            return table + "_" + key;
+        } else {
+            return table + "_" + userId + "_" + key;
+        }
+
     }
 
     /**
diff --git a/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java b/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java
index 1f71867..0e2cc57 100644
--- a/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java
+++ b/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java
@@ -66,6 +66,16 @@
     }
 
     @Test
+    public void testSeparateUsers() {
+        Secure.putStringForUser(mContentResolver, NONEXISTENT_SETTING, "something", 0);
+        Secure.putStringForUser(mContentResolver, NONEXISTENT_SETTING, "else", 1);
+        assertEquals("something",
+                Secure.getStringForUser(mContentResolver, NONEXISTENT_SETTING, 0));
+        assertEquals("else",
+                Secure.getStringForUser(mContentResolver, NONEXISTENT_SETTING, 1));
+    }
+
+    @Test
     public void testPassThrough() {
         // Grab the value of a setting that is not overridden.
         assertTrue(Secure.getInt(mContentResolver, Secure.USER_SETUP_COMPLETE, 0) != 0);
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 15648bd..ba73180 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -762,6 +762,15 @@
         return 1;
     }
 
+    // Now add any dependencies passed in.
+    for (size_t i = 0; i < bundle->getPackageIncludes().size(); i++) {
+      const String8& assetPath = bundle->getPackageIncludes()[i];
+      if (!assets.addAssetPath(assetPath, NULL)) {
+        fprintf(stderr, "ERROR: included asset path %s could not be loaded\n", assetPath.string());
+        return 1;
+      }
+    }
+
     // Make a dummy config for retrieving resources...  we need to supply
     // non-default values for some configs so that we can retrieve resources
     // in the app that don't have a default.  The most important of these is
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index 01930d0..e45d142 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -27,7 +27,7 @@
 static const char* sMajorVersion = "2";
 
 // Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "14";
+static const char* sMinorVersion = "15";
 
 int PrintVersion() {
   std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 5413b33..c192d69 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -114,6 +114,7 @@
   std::string output_path;
   Maybe<std::string> res_dir;
   bool pseudolocalize = false;
+  bool no_png_crunch = false;
   bool legacy_mode = false;
   bool verbose = false;
 };
@@ -663,6 +664,7 @@
                           "Generate resources for pseudo-locales "
                           "(en-XA and ar-XB)",
                           &options.pseudolocalize)
+          .OptionalSwitch("--no-crunch", "Disables PNG processing", &options.no_png_crunch)
           .OptionalSwitch("--legacy", "Treat errors that used to be valid in AAPT as warnings",
                           &options.legacy_mode)
           .OptionalSwitch("-v", "Enables verbose logging", &verbose);
@@ -738,7 +740,8 @@
             if (!CompileXml(&context, options, path_data, archive_writer.get(), output_filename)) {
               error = true;
             }
-          } else if (path_data.extension == "png" || path_data.extension == "9.png") {
+          } else if (!options.no_png_crunch &&
+                     (path_data.extension == "png" || path_data.extension == "9.png")) {
             if (!CompilePng(&context, options, path_data, archive_writer.get(), output_filename)) {
               error = true;
             }
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index 0291720..e92565f 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,13 @@
 # Android Asset Packaging Tool 2.0 (AAPT2) release notes
 
+## Version 2.15
+### `aapt2 compile ...`
+- Add `--no-crunch` option to avoid processing PNGs during the compile phase. Note that this
+  shouldn't be used as a performance optimization, as once the PNG is processed, its result is
+  cached for incremental linking. This should only be used if the developer has specially
+  pre-processed the PNG and wants it byte-for-byte identical to the input.
+  NOTE: 9-patches will not be processed correctly with this flag set.
+
 ## Version 2.14
 ### `aapt2 link ...`
 - If an app is building with a minSdkVersion < 26 and a --package-id XX where XX > 7F, aapt2
diff --git a/vr/Android.mk b/vr/Android.mk
new file mode 100644
index 0000000..5b65d3f
--- /dev/null
+++ b/vr/Android.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+LOCAL_PATH := $(call my-dir)
+
+# Library to perform dlopen on the actual shared library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := libdvr_loader
+LOCAL_MODULE_OWNER := google
+LOCAL_SRC_FILES := dvr_library_loader.cpp
+include $(BUILD_SHARED_LIBRARY)
+
+# Java platform library for vr stuff.
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.google.vr.platform
+LOCAL_MODULE_OWNER := google
+LOCAL_REQUIRED_MODULES := libdvr_loader libdvr
+LOCAL_SRC_FILES := $(call all-java-files-under, java)
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.google.vr.platform.xml
+LOCAL_SRC_FILES := com.google.vr.platform.xml
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_OWNER := google
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
+include $(BUILD_PREBUILT)
diff --git a/vr/com.google.vr.platform.xml b/vr/com.google.vr.platform.xml
new file mode 100644
index 0000000..952b476
--- /dev/null
+++ b/vr/com.google.vr.platform.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<permissions>
+    <library name="com.google.vr.platform"
+             file="/system/framework/com.google.vr.platform.jar" />
+</permissions>
diff --git a/vr/dvr_library_loader.cpp b/vr/dvr_library_loader.cpp
new file mode 100644
index 0000000..0b4298a
--- /dev/null
+++ b/vr/dvr_library_loader.cpp
@@ -0,0 +1,25 @@
+#include <dlfcn.h>
+#include <jni.h>
+
+#include <string>
+
+extern "C" {
+
+JNIEXPORT jlong JNICALL
+Java_com_google_vr_platform_Dvr_nativeLoadLibrary(
+    JNIEnv* env, jclass, jstring java_library) {
+  if (!java_library)
+    return 0;
+
+  // Convert the Java String object to a C++ null-terminated string.
+  const char* data = env->GetStringUTFChars(java_library, NULL);
+  size_t size = env->GetStringUTFLength(java_library);
+  std::string library(data, size);
+  env->ReleaseStringUTFChars(java_library, data);
+
+  // Return the handle to the requested library.
+  return reinterpret_cast<jlong>(
+      dlopen(library.c_str(), RTLD_NOW | RTLD_LOCAL));
+}
+
+}  // extern "C"
diff --git a/vr/java/com/google/vr/platform/DeviceInfo.java b/vr/java/com/google/vr/platform/DeviceInfo.java
new file mode 100644
index 0000000..f6da66b
--- /dev/null
+++ b/vr/java/com/google/vr/platform/DeviceInfo.java
@@ -0,0 +1,19 @@
+package com.google.vr.platform;
+
+import android.os.SystemProperties;
+
+/**
+ * Class to get information about the vr device.
+ * @hide
+ */
+public class DeviceInfo {
+
+    private static final String VR_MODE_BOOT = "ro.boot.vr";
+
+    /**
+     * Returns true if this device boots directly in VR mode.
+     */
+    public static boolean getVrBoot() {
+        return SystemProperties.getBoolean(VR_MODE_BOOT, false);
+    }
+}
diff --git a/vr/java/com/google/vr/platform/Dvr.java b/vr/java/com/google/vr/platform/Dvr.java
new file mode 100644
index 0000000..b07d634
--- /dev/null
+++ b/vr/java/com/google/vr/platform/Dvr.java
@@ -0,0 +1,22 @@
+package com.google.vr.platform;
+
+/**
+ * Class to load the dvr api.
+ * @hide
+ */
+public class Dvr {
+    /**
+     * Opens a shared library containing the dvr api and returns the handle to it.
+     *
+     * @return A Long object describing the handle returned by dlopen.
+     */
+    public static Long loadLibrary() {
+        // Load a thin JNI library that runs dlopen on request.
+        System.loadLibrary("dvr_loader");
+
+        // Performs dlopen on the library and returns the handle.
+        return nativeLoadLibrary("libdvr.so");
+    }
+
+    private static native long nativeLoadLibrary(String library);
+}